Görsel Uzun Çarpma


28

İki tamsayı için uzun çarpma işlemini, hiçbir şey yapmak zorunda kalmadan yapmak için iyi bir yol var. Her numaranın rakamını, iki rakam 90 derecelik bir açıyla, eğimli çizgiler şeklinde yazabilirsiniz. Ardından, kesişmeleri ortaya çıkan ayrı sütunlarda kolayca sayabilirsiniz. Bir diyagram muhtemelen bunu açıklığa kavuşturur. İşte hesaplama için bir örnek 21 * 32:

görüntü tanımını buraya girin

"Görsel / grafiksel uzun çarpma" için google’a giderseniz çok daha fazla örnek bulacaksınız.

Bu zorlukla ASCII tekniğini kullanarak bu şemaları oluşturmalısınız. Aynı örnek için çıktı şöyle görünür:

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

Bunların yapım kurallarını bazı örneklerden (aşağıya bakınız) çözmek muhtemelen en kolay olanıdır, fakat işte bazı detaylar:

  • Kesişen bölümler X, çizgilerin kesişmeyen bölümleri /veya \.
  • En dıştaki kavşaklardan sonra tam olarak bir parça olmalıdır.
  • Farklı rakamlara ait kavşaklar arasında tam olarak bir segment bulunmalıdır. Sıfır basamak varsa, bunlar ardışık /veya \segmentlere neden olur.
  • Herhangi bir pozitif girişi (en azından 2 16 veya 2 32 gibi makul bir limite kadar ) ve 0ila arasındaki rakamları desteklemelisiniz 9. Ancak, ne önde ne de sonda olmadığını varsayabilirsin 0.
  • Fazladan boşluksuz beyaz boşluk ya da sonunda boş ya da sonunda boş satırlar yazdırmamalısınız.
  • Sondaki boşlukları yazdırabilirsiniz, ancak şemanın eksen hizalı sınırlama kutusunu aşmamalıdır.
  • İsteğe bağlı olarak tek bir izleyen yeni satır yazdırabilirsiniz.
  • İki giriş numarasını hangi sırayla alacağınızı seçebilirsiniz. Ancak, her iki yönde de rasgele sayıları desteklemelisiniz, bu nedenle "Önce büyük sayı verilir" gibi bir şey seçemezsiniz.
  • Girdiyi dizge olarak alıyorsanız, iki sayı arasında rakam olmayan herhangi bir ayırıcı kullanabilirsiniz.

STDIN (veya en yakın alternatif), komut satırı argümanı veya işlev argümanı yoluyla giriş alarak ve sonucu STDOUT (veya en yakın alternatif), fonksiyon dönüş değeri veya function (out) parametresi ile çıktı alarak bir program veya işlev yazabilirsiniz.

Bu kod golf, en kısa cevap (bayt cinsinden) kazanır.

Örnekler

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 \
            / \

2 dize parametresi olan bir işlev veya yalnızca bir tek dize ve koduma bölmek zorunda mıyım?
edc65

@ edc65 İki karakter hatta iki tam sayı parametresi iyi.
Martin Ender

Yanıtlar:


1

Pyth - 79 bayt

@ AlexeyBurdin'in cevabının çevirisi. Muhtemelen çok daha fazla golf olabilir.

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

Girişi iki sayı olarak alır, yeni satır ayrılmış. Açıklama çok yakında.

Burada çevrimiçi deneyin .


4

piton, 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])

Bence insan tarafından okunabilir.
Doğrulama:

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 \      "
"            / \       "
---

1
Sadece birkaç hızlı golfs: reversedaynıdır [::-1]sen, girinti üzerinde kurtarmak için bir hizaya döngü içeriğini koyabilirsiniz, len(a)+len(b)daha kısadır sum(map(len,[a,b]))kullanmayın, xrangegolf içinde, uzay ) forkaldırılır ve olduğundan edilebilir python2'yi kullanarak boşlukları ve sekmeleri girintili olarak birleştirebilirsiniz.
Maltysen

Çok teşekkürler. Bunlar 22 bayt verir. Ama bunun en kısa olacağını düşünmüyorum. Ben kodu yok pyth ama 31 bayt programları gördüm ... Btw, 303 her 4-boşluk aslında bir sekme ile değiştirilir sayısıdır.
Alexey Burdin

Burada, 276basit sözdizimsel golf oynamak
Maltysen

Ayrıca, programınızı Pyth'e çevirip ayrı bir cevap olarak gönderebilir miyim?
Maltysen

1
Sen ayarlayabilirsiniz e=enumerategolf 4 chars başında
sagiksp

2

Python 3, 205 bayt

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])

İfadeler oldukça uzun, bu yüzden iyileştirme için yeterli alan olduğunu düşünüyorum, ama yine de ...

STDIN ile ayrılan giriş alanını alır, örn.

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

Bazı çizgiler üzerinde muhtemel bir takip alanı vardır, ancak A+B-2tüm takip alanlarının sınırlayıcı kutu içinde olmasını sağlar.


1

C #, 451 bayt

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())));}

Okunabilirlik için formatlanmış, fonksiyon bağlamında:

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())));
    }
}

Bitsel OR sadece eğlenceliydi, fakat ekleme de işe yarayacaktı.


1

JavaScript ( ES6 ) 271

Çıktı satırını matematiğe ve x, y koordinatlarına (x + y == k, xy == k ...) göre dizginleyen bir çözüm olduğuna eminim. Ama hala çivileyemiyorum.

Yani burada sadece çizgileri tek tek çizen bir çözüm var.

Test etmek için snippet'i Firefox'ta çalıştırın.

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>


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++);

kullanım

#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;}

Sonuçlar

       \ /
      \ 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
         / \
  • fonksiyon tek bir döngü tekrarlar ve bazı geometri ve ascii trifling kullanır.

Ne ---48için?
LegionMammal978 14:15

@ LegionMammal978 bazen bir şeyler yazıyorum, sonra bile neden koyduğumu bile unutuyorum: D yine de başka bir şey yapmakla meşgulüm; (bu kod, derleyicinizde iyi gider)?
Abr001,

@ LegionMammal978, belirli (gerçek) dizindeki dizi içeriği azalmadan önce 48'e çıkarılır, azalan bir sıfır karakterini beklemek için
48'i çıkardıktan

48, "0" nın ascii temsilidir
Abr001am

1
Şimdi anlıyorum gibi çalışıyor ...)-- - 48)....
LegionMammal978


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);}

DENE


Her karakterden sonra boşluk sütunları varmış gibi görünüyor ve alt uçlarda kesişmeyen son bölümler eksik. Ayrıca rakamları ters sırada kullanıyorsunuz.
Martin Ender

MartinBüttner @ birisi aya bu yaptığını ve u diyagramı algılamalıdır yolu bu teleskop, bunu izlerken hayal (-joking-ı daha sonra o ayarlayacağımız)
Abr001am

0

R , 294 bayt

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")

Çevrimiçi deneyin!


0

Jöle , 58 bayt

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

Çevrimiçi deneyin!

açıklama

İki sayıyı iki tamsayının listesi olarak alan ve bir dize döndüren tam bir program.

Yardımcı link 1: matrisi döndürün

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

Yardımcı link 2: satır ve sütun şablonlarını oluşturur

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

Ana link

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.