시각적 긴 곱셈


28

계산하지 않고 두 개의 정수에 대해 긴 곱셈을 수행하는 좋은 방법이 있습니다. 가끔씩 인터넷에서 공유됩니다. 각 숫자의 자릿수를 기울어 진 선으로 기록하고 두 숫자는 90도 각도로 씁니다. 그런 다음 발생하는 별도의 열에서 교집합을 간단히 계산할 수 있습니다. 다이어그램은 아마도 이것을 분명히 할 것입니다. 다음은 계산 예입니다21 * 32 .

enter image description here

"비주얼 / 그래픽 긴 곱셈"에 대해 Google을 사용하는 경우 더 많은 예를 찾을 수 있습니다.

이 과제에서는 ASCII 아트를 사용하여 이러한 다이어그램을 생성해야합니다. 동일한 예에서 출력은 다음과 같습니다.

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

일부 예제에서 아래의 구성 규칙을 알아내는 것이 가장 쉬운 방법이지만 (아래 참조) 여기에 몇 가지 세부 정보가 있습니다.

  • 교차 세그먼트는 X선의 교차하지 않는 세그먼트는/ 또는 \입니다.
  • 가장 바깥 쪽 교차점 다음에 정확히 하나의 세그먼트가 있어야합니다.
  • 서로 다른 숫자에 속하는 교차점 사이에는 정확히 하나의 세그먼트가 있어야합니다. 숫자가 0이면 연속 /또는\ 세그먼트가됩니다.
  • 양수 입력 (적어도 2 16 또는 2 32 와 같은 합리적인 한도까지 )과에서 0까지의 숫자를 지원 해야 9합니다. 그러나 선행 또는 후행이 없다고 가정 할 수 있습니다.0 .
  • 불필요한 선행 공백 또는 선행 또는 후행 빈 줄을 인쇄해서는 안됩니다.
  • 후행 공백을 인쇄 할 수 있지만 다이어그램의 축 정렬 경계 상자를 초과해서는 안됩니다.
  • 선택적으로 단일 후행 줄 바꿈을 인쇄 할 수 있습니다.
  • 두 개의 입력 번호를받는 순서를 선택할 수 있습니다. 그러나 어느 방향 으로든 임의의 숫자를 지원해야하므로 "큰 숫자가 먼저 주어짐"과 같은 것을 선택할 수 없습니다.
  • 문자열로 입력하는 경우 두 숫자 사이에 숫자가 아닌 구분 기호를 사용할 수 있습니다.

STDIN (또는 가장 가까운 대안), 명령 행 인수 또는 함수 인수를 통해 입력을 받고 STDOUT (또는 가장 가까운 대안), 함수 리턴 값 또는 함수 (out) 매개 변수를 통해 결과를 출력하는 프로그램 또는 함수를 작성할 수 있습니다.

이것은 코드 골프이며, 가장 짧은 대답 (바이트)이 이깁니다.

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 2016 년

답변:


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
몇 가지 빠른 골프 : reversed와 동일 [::-1]합니다. for 루프의 내용을 들여 쓰기를 줄이기 위해 한 줄에 넣을 수 있습니다. len(a)+len(b)보다 짧고 sum(map(len,[a,b])), xrange골프에 사용하지 않으며 , 공간을 ) for제거 할 수 있습니다. python2를 사용하면 들여 쓰기로 공백과 탭을 결합 할 수 있습니다.
Maltysen

고맙습니다. 이것들은 22 바이트를 제공합니다. 그러나 나는 그것이 가장 짧을 것이라고 생각하지 않습니다. 나는 pyth를 코딩하지 않지만 31 바이트 프로그램을 보았습니다 ... Btw, 303은 모든 4 개의 공백이 실제로 탭으로 바뀔 때의 수입니다.
Alexey Burdin 2016 년

여기, 나는 276간단한 구문 골프에서 얻을 수 있었다 : gist.github.com/Maltysen/e8231c0a9b585e2a4941
Maltysen

또한 프로그램을 Pyth로 번역하여 별도의 답변으로 게시해도 괜찮습니까?
Maltysen

1
당신은 e=enumerate시작에 4 문자를 골프로 설정할 수 있습니다
sagiksp

2

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

비트 OR은 단지 재미를위한 것이었지만 추가도 효과가있었습니다.


1

자바 스크립트 ( 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 트리플 링을 사용합니다.

무엇입니까 ---48?
LegionMammal978

@ LegionMammal978 때때로 나는 물건을 쓴 다음 왜 내가 그것을 거기에 넣었는지 잊어 버립니다. (이 코드는 컴파일러에서 잘 작동합니까?)
Abr001am

@ LegionMammal978 여기에서, 특정 (실제) 인덱스의 배열 내용 이 감소 하기 전에 48로 감산됩니다 . 앞으로 nil 문자를 대기하기 위해 48을 빼고 루프에서 단계별로 감소합니다 (또는 ascii 패턴으로 뒤로)
Abr001am

48은 "0"의 ASCII 표현입니다
Abr001am

1
나는 지금처럼 작동합니다 ...)-- - 48)....
LegionMammal978


0

C (329b)

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

시도 해봐


It seems there are columns of spaces after every character, and the final non-intersecting segments at the bottom ends are missing. You're also using the digits in reverse order.
Martin Ender

@MartinBüttner imagine someone is doing this on the moon and u watching it by telescope , that s the way you should perceive the diagram (-joking-i ll adjust that later)
Abr001am

0

R, 294 bytes

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

Try it online!


0

Jelly, 58 bytes

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

Try it online!

Explanation

A full program that takes the two numbers as a list of two integers and returns a string.

Helper link 1: rotate the matrix

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

Helper link 2: generate the row and column templates

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

Main 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.