Penggandaan Panjang Visual

28

Ada cara yang bagus untuk melakukan perkalian panjang untuk dua bilangan bulat tanpa harus melakukan apa pun selain menghitung, yang sesekali dibagikan di internet. Anda menulis digit setiap angka sebagai sekelompok garis miring, dengan dua angka pada sudut 90 derajat. Kemudian Anda bisa menghitung simpang pada kolom terpisah yang muncul. Diagram mungkin akan memperjelas hal ini. Berikut ini contoh untuk menghitung 21 * 32:

masukkan deskripsi gambar di sini

Jika Anda mencari "perkalian panjang visual / grafis", Anda akan menemukan lebih banyak contoh.

Dalam tantangan ini, Anda harus membuat diagram ini menggunakan seni ASCII. Untuk contoh yang sama, hasilnya akan terlihat seperti ini:

   \ /
    X /
 \ / X /
\ X / X
 X X / \ /
/ X X   X /
 / X \ / X
  / \ X / \
     X X
    / X \
     / \

Mungkin paling mudah untuk mengetahui aturan konstruksi untuk ini dari beberapa contoh (lihat di bawah), tetapi di sini beberapa detail:

  • Segmen berpotongan adalah X, segmen non-garis berpotongan adalah /atau \.
  • Harus ada tepat satu segmen setelah persimpangan terluar.
  • Harus ada tepat satu segmen antara persimpangan yang memiliki digit berbeda. Jika ada nol digit, ini akan menghasilkan berturut /- turut atau \segmen.
  • Anda harus mendukung input positif apa pun (setidaknya hingga batas yang masuk akal seperti 2 16 atau 2 32 ), dan angka apa pun dari 0hingga 9. Namun, Anda dapat berasumsi bahwa tidak ada yang memimpin maupun yang tertinggal 0.
  • Anda tidak boleh mencetak spasi putih terkemuka di luar angkasa atau memimpin atau mengikuti garis kosong.
  • Anda dapat mencetak trailing whitespace tetapi tidak boleh melebihi kotak bounded aligned diagram.
  • Anda dapat secara opsional mencetak satu baris baru.
  • Anda dapat memilih dalam urutan mana Anda mengambil dua nomor input. Namun, Anda harus mendukung angka sembarang untuk salah satu orientasi, sehingga Anda tidak dapat memilih sesuatu seperti "Jumlah yang lebih besar diberikan terlebih dahulu".
  • Jika Anda mengambil input sebagai string, Anda dapat menggunakan pemisah non-digit di antara kedua angka tersebut.

Anda dapat menulis sebuah program atau fungsi, mengambil input melalui STDIN (atau alternatif terdekat), argumen baris perintah atau argumen fungsi dan mengeluarkan hasilnya melalui STDOUT (atau alternatif terdekat), nilai pengembalian fungsi atau parameter function (out).

Ini adalah kode golf, jawaban terpendek (dalam byte) menang.

Contohnya

1*1
\ /
 X
/ \

2*61
 \ /
\ X /
 X X /
/ X X /
 / X X /
  / X X /
   / X X
    / X \ /
     / \ X
        X \
       / \

 45*1
         \ /
        \ X
       \ X \
      \ X \
     \ X \
      X \
   \ / \
  \ X
 \ X \
\ X \
 X \
/ \

21001*209
       \ /
        X /
       / X
      / / \
   \ / /   \ /
    X /     X /
 \ / X     / X /
\ X / \   / / X /
 X X   \ / / / X /
/ X \   X / / / X /
 / \ \ / X / / / X /
    \ X / X / / / X /
     X X / X / / / X /
    / X X / X / / / X
     / X X / X / / / \
      / X X / X / /
       / X X / X /
        / X X / X
         / X X / \
          / X X
           / X \
            / \
Martin Ender
sumber
Fungsi dengan 2 parameter string atau hanya satu string tunggal dan saya harus membaginya dalam kode saya?
edc65
@ edc65 Dua string atau bahkan dua parameter integer baik-baik saja.
Martin Ender

Jawaban:

1

Pyth - 79 byte

Terjemahan dari jawaban @ AlexeyBurdin. Mungkin bisa bermain golf lebih banyak.

AzHmu++Gm1sH]Zd]Z,_zwK+lzlHJmm\ KK .e.eX@J+kY+-Yklz@" \/x"+byZHzjbmjk:d2_1:J1_2

Mengambil input sebagai dua angka, baris baru dipisahkan. Penjelasan segera hadir.

Cobalah online di sini .

Maltysen
sumber
4

python, 303

def f(s):
    a,b=s.split('*')
    a,b=map(lambda l:reduce(lambda x,y:x+[1]*int(y)+[0],l,[0]),[reversed(a),b])
    n=sum(map(len,[a,b]))
    l=[[' ']*n for i in xrange(n)]
    for i,x in enumerate(a):
        for j,y in enumerate(b):
            l[i+j][j-i+len(a)]=r' \/x'[x+2*y]
    return '\n'.join(''.join(x[2:-1]) for x in l[1:-2])

Saya pikir itu cukup dapat dibaca manusia.
Verifikasi:

print '---'
print '\n'.join('"%s"'%x for x in f('21001*209').split('\n'))
print '---'
---
"       \ /            "
"        x /           "
"       / x            "
"      / / \           "
"   \ / /   \ /        "
"    x /     x /       "
" \ / x     / x /      "
"\ x / \   / / x /     "
" x x   \ / / / x /    "
"/ x \   x / / / x /   "
" / \ \ / x / / / x /  "
"    \ x / x / / / x / "
"     x x / x / / / x /"
"    / x x / x / / / x "
"     / x x / x / / / \"
"      / x x / x / /   "
"       / x x / x /    "
"        / x x / x     "
"         / x x / \    "
"          / x x       "
"           / x \      "
"            / \       "
---
Alexey Burdin
sumber
1
Hanya beberapa golf cepat: reversedsama dengan [::-1], Anda dapat meletakkan isi loop for ke dalam satu baris untuk menghemat lekukan, len(a)+len(b)lebih pendek daripada sum(map(len,[a,b])), tidak digunakan xrangedalam golf, ruang dalam ) fordapat dihapus, dan karena Anda menggunakan python2, Anda bisa menggabungkan spasi dan tab di lekukan.
Maltysen
Terimakasih banyak. Ini memberikan 22 byte. Tapi saya tidak berpikir itu akan menjadi yang terpendek. Saya tidak kode pyth tapi saya sudah melihat program 31-byte ... Btw, 303 adalah hitungan ketika setiap 4-ruang digantikan oleh tab sebenarnya.
Alexey Burdin
Di sini, saya bisa mendapatkan 276dari golf sintaksis sederhana: gist.github.com/Maltysen/e8231c0a9b585e2a4941
Maltysen
Juga, apakah Anda keberatan jika saya menerjemahkan program Anda ke Pyth dan mempostingnya sebagai jawaban terpisah?
Maltysen
1
Anda dapat mengatur e=enumeratedi awal untuk golf 4 karakter
sagiksp
2

Python 3, 205 byte

L=a,b=[eval("+[0]+[1]*".join("0%s0"%x)[2:])for x in input().split()]
A,B=map(len,L)
for c in range(2,A+B-1):print((" "*abs(c-A)+" ".join(" \/X"[a[i-c]+2*b[i]]for i in range(max(0,c-A),min(c,B))))[1:A+B-2])

Ekspresi cukup panjang jadi saya pikir ada cukup banyak ruang untuk perbaikan, tapi tetap saja ...

Membawa input yang dipisahkan ruang melalui STDIN, mis

21 32
   \ /
    X /
 \ / X /
\ X / X  
 X X / \ /
/ X X   X /
 / X \ / X 
  / \ X / \
     X X  
    / X \
     / \

Ada ruang trailing yang mungkin pada beberapa garis, tetapi A+B-2memastikan bahwa semua ruang trailing berada di dalam kotak pembatas.

Sp3000
sumber
1

C #, 451 byte

void d(string s){var S=s.Split('*');int X=S[1].Select(c=>c-47).Sum(),Y=S[0].Select(c=>c-47).Sum(),L=9*(X+Y),A=1,B=L/3,i,j;var a=Range(0,L).Select(_=>new int[L]).ToArray();foreach(var c in S[1]){for(i=48;i<c;++i){for(j=-1;j<Y;++j)a[B-j][A+j]=1;A++;B++;}A++;B++;}A=1;B=L/3;foreach(var c in S[0]){for(i=48;i<c;++i){for(j=-1;j<X;++j)a[B+j][A+j]|=2;A++;B--;}A++;B--;}Write(Join("\n",a.Select(r=>Concat(r.Select(n=>@" /\X"[n]))).Where(r=>r.Trim().Any())));}

Diformat agar mudah dibaca, fungsi dalam konteks:

using System.Linq;
using static System.Console;
using static System.Linq.Enumerable;
using static System.String;

class VisualMultiply
{
    static void Main(string[] args)
    {
        new VisualMultiply().d("21001*209");

        WriteLine();
    }

    void d(string s)
    {
        var S = s.Split('*');

        int X = S[1].Select(c => c - 47).Sum(), 
            Y = S[0].Select(c => c - 47).Sum(),
            L = 9 * (X + Y),
            A = 1,
            B = L / 3,
            i,
            j;

        var a = Range(0, L).Select(_ => new int[L]).ToArray();

        foreach (var c in S[1])
        {
            for (i = 48; i < c; ++i)
            {
                for (j = -1; j < Y; ++j)
                    a[B - j][A + j] = 1;
                A++;
                B++;
            }
            A++;
            B++;
        }

        A = 1;
        B = L / 3;
        foreach (var c in S[0])
        {
            for (i = 48; i < c; ++i)
            {
                for (j = -1; j < X; ++j)
                    a[B + j][A + j] |= 2;
                A++;
                B--;
            }
            A++;
            B--;
        }

        Write(Join("\n", a.Select(r => Concat(r.Select(n => @" /\X"[n]))).Where(r => r.Trim().Any())));
    }
}

Bitwise OR hanya untuk bersenang-senang, tetapi penambahan akan bekerja juga.

Carl Walsh
sumber
1

JavaScript ( ES6 ) 271

Saya yakin ada solusi yang membangun output baris demi baris, mengutak-atik matematika dan koordinat x, y (x + y == k, xy == k ...). Tapi aku masih belum bisa memahaminya.

Jadi di sini adalah solusi yang hanya menggambar garis satu per satu.

Jalankan cuplikan di Firefox untuk menguji.

F=(a,b)=>( // string parameters
  t=u=0,[for(v of a)t-=~v],[for(v of b)u-=~v],
  r=t+u,o=[...' '.repeat(r*r-r)],
  L=(x,y,n,z,m,c)=>{
    for(i=0;d=n[i++];)
      for(j=0;++x,y+=z,j++<d;)
        for(l=m+1,p=x+y*r-1-r;l--;p+=r-z,o[p-p%r-1]='\n')
          o[p]=o[p]>' '&&o[p]!=c?'X':c
  },
  L(u,0,a,1,u,'/'),
  L(0,u,b,-1,t,'\\'),
  o.join('')
)

// TEST

function test()
{
  O.innerHTML= F(A.value, B.value);
}

test();
<input id=A value=21001> * <input id=B value=209> <button onclick='test()'>-></button>
<pre id=O></pre>

edc65
sumber
1

VC ++ (289)280

t(char*a){int i,j,k,r,c=1,e,A=0,B=0,*C,G[99],f,u;for(C=&A;c+48|(k=(c=(*(a+=c<1))---48)>0);G[2**(C=!(c+6)?&(B+=A):&(++*C))]=k**C);for(i=0;i<B*B;printf("\n%c"+!!j,32+15*((k=(c<(f=G[(c=i/B)+(j=i%B)+A+2]))*(j<f)*(f>A))+4*(r=(!!e*B>c+(e=G[A+j-c]))*(!!e*c>A-e-2)*(e<A)))+13*k*r),i++);

Pemakaian

#include  <stdio.h>
#include  <conio.h>

int t(char*);

int main(void)
{   char a[]="123*45";
    t((char*)a);
    getch();
    return 0;
}

int 
//-------- padded code ------
t(char*a){int i,j,k,r,c=1,e,A=0,B=0,*C,G[99],f,u;memset(G,0,396);for(C=&A;c+48|(k=(c=(*(a+=c<1))---48)>0);G[2**(C=!(c+6)?&(B+=A):&(++*C))]=k**C);for(i=0;i<B*B;printf("\n%c"+!!j,32+15*((k=(c<(f=G[(c=i/B)+(j=i%B)+A+2]))*(j<f)*(f>A))+4*(r=(!!e*B>c+(e=G[A+j-c]))*(!!e*c>A-e-2)*(e<A)))+13*k*r),i++);

//---------------------------
return 0;}

Hasil

       \ /
      \ x /
     \ x x /
      x x x /
   \ / x x x
  \ x / x x \ /
   x x / x \ x /
\ / x x / \ x x /
 x / x x   x x x /
/ x / x \ / x x x /
 / x / \ x / x x x
  / x   x x / x x \
   / \ / x x / x \
      x / x x / \
     / x / x x
      / x / x \
       / x / \
        / x
         / \
  • fungsi ini mengulangi satu loop tunggal, dan menggunakan beberapa geometricks dan ascii trifling.
Abr001am
sumber
Untuk apa ini ---48?
LegionMammal978
@ LegionMammal978 kadang-kadang saya menulis sesuatu kemudian saya lupa bahkan mengapa saya meletakkannya di sana: D toh saya sibuk melakukan sesuatu yang lain, ketika saya selesai, saya tidak ingat untuk Anda; (apakah kode ini berjalan baik di kompiler Anda)?
Abr001am
@ LegionMammal978 di sini, konten larik pada indeks spesifik (aktual) dikurangi menjadi 48 sebelum dikurangi, mengurangi 48 untuk menunggu karakter nol mendatang, kemudian mengurangi langkah demi langkah maju dalam lingkaran (atau mundur sebagai pola ascii)
Abr001am
48 adalah representasi ascii dari "0"
Abr001am
1
Saya melihat sekarang, itu berfungsi seperti ...)-- - 48)....
LegionMammal978
1

Kanvas , 41 byte

(A┬{[1}0}┐)
⁷L├X⁷lYø;{³×?³y³-╵x\╋
⁸⤢↔╶╶⁸n

Coba di sini!

dzaima
sumber
0

C (329 b)

int f(char*a){int i,j,r,k,c,h,o,e=15,m=99,A=0,B=0,*C,L[m][m],G[m],*g=G;for(C=&A;(c=*a-48)+48;C=!(c+6)?&B:&(*C+=(*g++=c+1)),a++);for(i=B-1,j=0;j<(r=A+B-1);i--,j++)for(k=0,o=4*!!((*(g-=!*g))---1);k<=*(C=(h=i<0)?&B:&A);k++)L[abs(i)+k][j+k-2*k*h]+=o/(3*h+1)*e;for(i=0;i<r*r;i++)printf("\n%c"+!!(i%r),((h=L[i/r][i%r])>e*4)?120:h+32);}

COBALAH

Abr001am
sumber
Tampaknya ada kolom spasi setelah setiap karakter, dan segmen non-berpotongan terakhir di ujung bawah hilang. Anda juga menggunakan angka dalam urutan terbalik.
Martin Ender
@ MartinBüttner bayangkan seseorang melakukan ini di bulan dan kamu menontonnya dengan teleskop, begitulah seharusnya kamu memahami diagram (-canda-aku akan menyesuaikannya nanti)
Abr001am
0

R , 294 byte

d=do.call;r=outer;m=d(r,c(Map(function(y,w)d(c,c(lapply(y%/%10^rev(0:log10(y))%%10,function(z)c(0,rep(w,z))),0)),scan(),1:2),`+`))+1;p=matrix(" ",u<-sum(dim(m)),u);p[d(r,c(lapply(dim(m),seq),function(a,b)nrow(m)-a+b+u*(a+b-2)))]=c(" ","\\","/","X")[m];cat(apply(p,1,paste,collapse=""),sep="\n")

Cobalah online!

Nick Kennedy
sumber
0

Jelly , 58 byte

ŒDṙLN‘ƊṚị“\/X ”K€
L‘0xż1xⱮ$F
DÇ€Ḥ2¦+þ/µZJUṖ;J’⁶xⱮżÑṖḊẎḊ$€Y

Cobalah online!

Penjelasan

Program lengkap yang menggunakan dua angka sebagai daftar dua bilangan bulat dan mengembalikan sebuah string.

Tautan bantuan 1: memutar matriks

ŒD                        | get the diagonals
  ṙ                       | rotate left by
   LN‘Ɗ                   | minus num columns +1
       Ṛ                  | reverse order
        ị“\/X ”           | index into \/X
               K€         | join each with spaces

Tautan bantuan 2: buat templat baris dan kolom

L‘0x                      | 0 copied (num digits + 1) times
    ż                     | interleaved with
     1xⱮ$                 | 1 copied as specified by the digits
         F                | flattened

Tautan utama

D                         | convert to decimal digits
 ǀ                       | call above link for each number
   Ḥ2¦                    | double the second one
      +þ/                 | outer product using +
         µ                | start a new monadic chain
          ZJUṖ;J’         | reversed range counting down
                          | the columns, followed by range
                            counting up the rows (without
                            duplicating 0 in the middle)
                   ⁶xⱮ    | that many spaces (to provide indents)
                      ż   | interleaved with
                       Ñ  | rotated matrix
                        ṖḊẎḊ$€ Y | remove blank rows and columns and join with newlines
Nick Kennedy
sumber