การคูณด้วยสายตายาว


28

มีวิธีที่ดีในการดำเนินการคูณแบบยาวสำหรับจำนวนเต็มสองจำนวนโดยไม่ต้องทำอะไรนอกจากนับซึ่งบางครั้งจะมีการแชร์ผ่านอินเทอร์เน็ต คุณเขียนตัวเลขของแต่ละหมายเลขเป็นจำนวนบรรทัดเอียงโดยมีตัวเลขสองตัวทำมุม 90 องศา จากนั้นคุณสามารถนับการแยกในคอลัมน์แยกที่เกิดขึ้นได้ ไดอะแกรมอาจอธิบายสิ่งนี้ได้ นี่คือตัวอย่างสำหรับการคำนวณ21 * 32:

ป้อนคำอธิบายรูปภาพที่นี่

หากคุณ google สำหรับ "การคูณด้วยภาพ / กราฟิกแบบยาว" คุณจะพบตัวอย่างอีกมากมาย

ในการท้าทายนี้คุณต้องสร้างไดอะแกรมเหล่านี้โดยใช้ ASCII art สำหรับตัวอย่างเดียวกันเอาต์พุตจะมีลักษณะดังนี้:

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

อาจเป็นวิธีที่ง่ายที่สุดที่จะเข้าใจกฎการก่อสร้างสำหรับสิ่งเหล่านี้จากตัวอย่าง (ดูด้านล่าง) แต่ที่นี่มีรายละเอียดบางส่วน:

  • กลุ่มตัดเป็นXกลุ่มที่ไม่ได้ตัดของเส้นที่มีหรือ/\
  • ควรจะมีหนึ่งส่วนที่แน่นอนหลังจากทางแยกด้านนอกสุด
  • ควรมีหนึ่งส่วนที่แน่นอนระหว่างทางแยกที่เป็นของตัวเลขที่แตกต่างกัน หากไม่มีศูนย์ตัวเลขเหล่านี้จะส่งผลในการติดต่อกัน/หรือ\ส่วน
  • คุณได้ให้การสนับสนุนการป้อนข้อมูลเชิงบวกใด ๆ (อย่างน้อยถึงขีด จำกัด บางอย่างที่เหมาะสมเช่น 2 16หรือ 2 32 ) และตัวเลขใด ๆ จากการ0 9แต่คุณอาจคิดว่ามีค่านำมิได้ท้าย0s
  • คุณต้องไม่พิมพ์เว้นวรรคนำหน้าหรือนำหน้าหรือต่อท้ายบรรทัดว่าง
  • คุณสามารถพิมพ์ช่องว่างต่อท้ายได้ แต่ต้องไม่เกินกล่องที่จัดแนวตามแนวแกนของไดอะแกรม
  • คุณสามารถเลือกที่จะพิมพ์ขึ้นบรรทัดใหม่ขึ้นบรรทัดเดียว
  • คุณสามารถเลือกได้ว่าจะเรียงลำดับหมายเลขใดให้คุณสองหมายเลข อย่างไรก็ตามคุณต้องสนับสนุนหมายเลขที่กำหนดเองสำหรับการวางแนวทั้งสองดังนั้นคุณจึงไม่สามารถเลือกบางอย่างเช่น "กำหนดจำนวนที่มากขึ้นก่อน"
  • หากคุณรับอินพุตเป็นสตริงคุณสามารถใช้ตัวคั่นที่ไม่ใช่ตัวเลขระหว่างตัวเลขสองตัว

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่น, รับอินพุตผ่าน STDIN (หรือทางเลือกที่ใกล้เคียงที่สุด), อาร์กิวเมนต์บรรทัดคำสั่งหรืออาร์กิวเมนต์ของฟังก์ชันและส่งผลลัพธ์ผ่าน STDOUT (หรือทางเลือกที่ใกล้เคียงที่สุด), ค่าส่งคืนของฟังก์ชันหรือพารามิเตอร์

นี่คือรหัสกอล์ฟคำตอบที่สั้นที่สุด (เป็นไบต์) ชนะ

ตัวอย่าง

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 ตัวหรือเพียงสตริงเดียวและฉันต้องแยกมันในโค้ด
edc65

@ edc65 สองสตริงหรือพารามิเตอร์จำนวนเต็มสองตัวนั้นใช้ได้
Martin Ender

คำตอบ:


1

Pyth - 79 ไบต์

คำแปลของ @ AlexeyBurdin อาจจะสามารถเล่นกอล์ฟได้มากขึ้น

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

รับอินพุตเป็นตัวเลขสองตัวโดยคั่นบรรทัดใหม่ คำอธิบายจะมาเร็ว ๆ นี้

ลองมันออนไลน์ได้ที่นี่


4

หลาม, 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])

ฉันคิดว่ามันอ่านง่ายพอ
ยืนยัน:

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
เพียงไม่กี่ golfs ด่วน: reversedเป็นเช่นเดียวกับ[::-1]คุณสามารถใส่เนื้อหาของการวนรอบเป็นหนึ่งบรรทัดเพื่อประหยัดการเยื้องlen(a)+len(b)สั้นกว่าsum(map(len,[a,b]))ไม่ใช้xrangeในการเล่นกอล์ฟพื้นที่ใน) forสามารถถูกลบออกและเนื่องจากคุณ ใช้ python2 คุณสามารถรวมช่องว่างและแท็บในการเยื้อง
Maltysen

ขอบคุณมาก. สิ่งเหล่านี้ให้ 22 ไบต์ แต่ฉันไม่คิดว่ามันจะสั้นที่สุด ฉันไม่ได้เขียนโค้ดpythแต่ฉันเคยเห็นโปรแกรมขนาด 31 ไบต์ ... Btw, 303 นับว่าเมื่อทุก ๆ 4 ช่องว่างถูกแทนที่ด้วยแท็บจริง ๆ
Alexey Burdin

ที่นี่ฉันสามารถได้รับ276จากการเล่นกอล์ฟวากยสัมพันธ์ง่ายๆ: gist.github.com/Maltysen/e8231c0a9b585e2a4941
Maltysen

นอกจากนี้คุณจะรังเกียจไหมถ้าฉันแปลโปรแกรมของคุณเป็น Pyth และโพสต์เป็นคำตอบแยกต่างหาก
Maltysen

1
คุณสามารถตั้งค่าได้e=enumerateตั้งแต่เริ่มเล่นกอล์ฟ 4 ตัวอักษร
sagiksp

2

Python 3, 205 ไบต์

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

การแสดงออกค่อนข้างยาวดังนั้นฉันคิดว่ามีจำนวนพอสมควรสำหรับการปรับปรุง แต่อย่างไรก็ตาม ...

ใช้พื้นที่อินพุตแยกจากกันผ่าน STDIN เช่น

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

มีพื้นที่ต่อท้ายที่เป็นไปได้ในบางบรรทัด แต่A+B-2มั่นใจได้ว่าช่องว่างต่อท้ายทั้งหมดอยู่ในกล่องขอบเขต


1

C #, 451 ไบต์

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

จัดรูปแบบเพื่อให้อ่านง่ายฟังก์ชั่นในบริบท:

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

ค่าบิตหรือเป็นเพียงเพื่อความสนุกสนาน แต่นอกจากนี้จะทำงานด้วย


1

JavaScript ( ES6 ) 271

ฉันแน่ใจว่ามีวิธีแก้ปัญหาที่สร้างผลลัพธ์แถวต่อแถวเล่นซอกับคณิตศาสตร์และ x, y พิกัด (x + y == k, xy == k ... ) แต่ฉันก็ยังทำไม่ได้

นี่คือวิธีแก้ปัญหาที่จะวาดเส้นทีละตัว

เรียกใช้ตัวอย่างใน Firefox เพื่อทดสอบ

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

การใช้

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

ผล

       \ /
      \ 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
         / \
  • ฟังก์ชั่นวนซ้ำหนึ่งวงเดียวและใช้รูปทรงเรขาคณิตและ ascii trifling

อะไร---48หา?
LegionMammal978

@ LegionMammal978 บางครั้งฉันก็เขียนสิ่งต่าง ๆ แล้วฉันก็ลืมไปว่าทำไมฉันถึงวางมันไว้ที่นั่น: D กำลังยุ่งอยู่กับการทำอย่างอื่นเมื่อฉันทำเสร็จฉันจำไม่ได้สำหรับคุณ (รหัสนี้ทำงานได้ดีในคอมไพเลอร์ของคุณหรือไม่)?
Abr001am

@ LegionMammal978 นี่เนื้อหาอาร์เรย์ที่เฉพาะเจาะจง (จริง) ดัชนีจะหักถึง 48 ก่อนที่มัน decrements ลบ 48 เพื่อรอตัวละครที่ศูนย์มาแล้วขั้นตอนลดลงโดยการก้าวไปข้างหน้าในวง (หรือข้างหลังเป็นรูปแบบ ASCII)
Abr001am

48 คือการแทน ascii ของ "0"
Abr001am

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

ลองมัน


ดูเหมือนว่าจะมีคอลัมน์ของช่องว่างหลังจากตัวละครทุกตัวและส่วนที่ไม่ตัดกันสุดท้ายที่ด้านล่างสุดหายไป คุณกำลังใช้ตัวเลขในลำดับย้อนกลับ
Martin Ender

@ MartinBüttnerคิดว่ามีคนจะทำเช่นนี้บนดวงจันทร์และ u ดูมันโดยกล้องโทรทรรศน์ที่ s วิธีที่คุณควรรับรู้แผนภาพ (-joking ฉันจะปรับในภายหลังว่า)
Abr001am


0

เยลลี่ , 58 ไบต์

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

ลองออนไลน์!

คำอธิบาย

โปรแกรมเต็มรูปแบบที่รับตัวเลขสองตัวเป็นรายการจำนวนเต็มสองตัวและส่งคืนสตริง

ตัวช่วยลิงค์ 1: หมุนเมทริกซ์

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

ตัวช่วยลิงค์ 2: สร้างเทมเพลตแถวและคอลัมน์

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

ลิงค์หลัก

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.