에티오피아 곱셈


17

이 질문은이 영감 대답 . 우연히도, 나는 어렸을 때 이디오피아 곱셈을 사용했지만 최근까지 방법의 이름을 알지 못했습니다.

에티오피아 곱셈은 더하기, 배가, 반만 사용하여 정수를 곱하는 방법입니다.

방법:

  1. 두 숫자를 곱하고 두 열의 맨 위에 적습니다.
  2. 왼쪽 열에서 마지막 숫자의 반을 반복하여 나머지를 버리고 값을 1로 쓸 때까지 같은 열의 마지막 아래에 결과를 씁니다.
  3. 오른쪽 열에 마지막 숫자를 두 번 반복하여 아래에 결과를 쓰십시오. 왼쪽 열에 1이 표시되는 것과 같은 행에 결과를 추가하면 중지됩니다.
  4. 생성 된 테이블을 검사하고 왼쪽 열의 값이 고른 행을 삭제하십시오. 원래 두 숫자를 곱한 결과를 생성하기 위해 남아있는 오른쪽 열의 값을 합산하십시오.

예를 들어 : 17 x 34

17    34

첫 번째 열을 반반 씩 :

17    34
 8
 4
 2
 1

두 번째 열을 두 배로 :

17    34
 8    68
 4   136 
 2   272
 1   544

첫 번째 셀이 짝수 인 줄 바꿈 행을 오른쪽에 대괄호로 묶어이 작업을 수행합니다.

17    34
 8   [68]
 4  [136]
 2  [272]
 1   544

오른쪽 열의 나머지 숫자를 합산하십시오.

17    34
 8   [68]
 4  [136]
 2  [272]
 1   544
    =====
     578

17에 34를 곱한 값에는 에티오피아 방법이 578입니다.

작업:

1에서 1000 사이의 두 숫자를 사용하고 동일한 레이아웃과 알고리즘을 수행하여 아래 제품을 표시하는 골프 코드.

입력 방법 : 그러나 당신은 선택 ...

입력 예 :

19 427

결과 출력 :

19   427
 9   854
 4 [1708]
 2 [3416]
 1  6832
   ======
    8113

숫자의 정렬에 유의하십시오. 이것은 레이아웃에서 가장 중요합니다. 또한 등호로 표시된 이중선은 전체 답보다 2 자 이상 길어야하며 가운데 정렬되어야합니다.

테스팅

이것을 어떻게 테스트 할 것입니까? 두 개의 숫자를 사용하여 프로그램을 제공합니다. 이 번호는 사용자 ID 번호에서 추출 할 수 있습니다 (이는 상단 창의 아바타 위로 커서를 가져 가면 얻을 수 있습니다). 숫자를 취하고 마지막 세 자리를 취하십시오.이 숫자는 B입니다. 앞에 남아있는 것을 취하십시오. 숫자는 A입니다. 그런 다음 A 곱하기 B를 테스트하십시오.

테스트 예 :

내 사용자 ID 번호는 8555이므로 내 번호는 8과 555입니다. 따라서 내 출력은 다음과 같아야합니다.

8  [555]
4 [1110]
2 [2220]
1  4440
  ======
   4440

제한 사항 :

알고리즘에 언급 된대로 "곱셈"을 사용할 경우 기본 곱셈 연산자를 사용할 수 없습니다. 즉, *와 같은 연산자를 사용하는 경우 2 만 곱하는 데만 사용할 수 있습니다.

이를 준수하지 않는 항목은 고려되지 않으며 사용자는 소지품으로 가득 찬 골판지 상자로 구내에서 에스코트됩니다. 각 항목에는 코드와 사용자 ID 번호에 따른 테스트가 있습니다.

이것은 코드 골프입니다. 가장 짧은 바이트 수는 동료의 상, 영광 및 존경을받을 것입니다 ... (그리고 아마도 람보르기니 ... 나는 "아마도"라고 말했다!)


5
"실제 곱셈은 일어나지 않아야합니다." -이것은 관찰 할 수 없습니다. 당신은 (같은 일부 문자 사용하여 제한 할 수 있습니다 *또는 x),하지만 곱셈을 사용하거나하지 않을 경우 탐지하는 것은 불가능합니다. 그 부분을 제외하고는 도전이 흥미 롭습니다.

알고리즘이 곱셈없이 구현되었음을 증명하는 코드에 대한 전체 설명 이나 원하는 출력을 제공하는 무제한 시뮬레이션을 요구해야 할 수도 있습니다. 그러나 그것은 나에게 두 가지 뚜렷한 도전처럼 보입니다.
Arnauld

1
샌드 박스에 언급 된대로 관련 가능한 dupe . @FelixPalmen, 예, 이것은 이진수로 긴 곱셈입니다.
피터 테일러

답변:


8

, 91 바이트

≔⟦⟧τ≔⁰σNθNηWθ«⊞τ⪫  Iθ⊞υ⪫⎇﹪θ²  ¦[]Iη≔⁺σ∧﹪θ²ησ≔÷θ²θ≔⁺ηηη»⊞υ…=⁺²LIσ⊞υ⪫  Iσ←E⮌τ⮌ιM⌈EυLιLυ←E⮌υ⮌ι

온라인으로 사용해보십시오! 링크는 자세한 버전의 코드입니다. 설명:

≔⟦⟧τ≔⁰σ

t빈 목록과 s로 설정 합니다 0. ( u이미 기본값은 빈 목록입니다.)

NθNη

두 숫자를 입력합니다.

Wθ«

q0이 아닌 동안 반복합니다 .

   ⊞τ⪫  Iθ

q패딩으로 싸서 목록에 추가하십시오 t.

   ⊞υ⪫⎇﹪θ²  ¦[]Iη

h패딩으로 또는 홀수 []인지에 따라 랩핑 q하여 목록에 추가하십시오 u.

   ≔⁺σ∧﹪θ²ησ

추가 hs하면 q이상하다.

   ≔÷θ²θ

정수 q를 2로 나눕니다 .

   ≔⁺ηηη»

h그 자체에 추가하십시오 .

⊞υ…=⁺²LIσ

=목록에 적합한 문자열을 추가 하십시오 u.

⊞υ⪫  Iσ

채워진 합계 s를 목록에 추가하십시오 u.

←E⮌τ⮌ι

목록 t을 180 ° 회전하고 거꾸로 인쇄하여 오른쪽 정렬합니다.

M⌈EυLιLυ←E⮌υ⮌ι

u오른쪽 정렬 된 경우 왼쪽 상단 모서리가 방금 도달 한 오른쪽 상단 모서리와 정렬 되도록 커서를 이동하고 오른쪽 정렬 된 인쇄 u합니다.


놀라운 일입니다. 당신은 지금까지 선두를 가지고 있습니다, @Neil. 언어에 대한 자세한 정보는 어디에서 찾을 수 있습니까? 링크가 있습니까?
WallyWest

1
@WallyWest 제목은 GitHub 페이지에 링크되어 있으며 여기에서 자세한 정보는 위키를 읽을 수 있습니다.

8

파이썬 (2) , 203 (202) 187 133 바이트

a,b=input()
s=0
while a:print'%3s%9s'%(a,'[ %%dd] '[a%2::2]%b);s+=[0,b][a%2];a/=2;b*=2
print'%10s==\n%11s'%(''.rjust(len(`s`),'='),s)

온라인으로 사용해보십시오!

*문자열 곱셈에 사용할 수 있다면 ('='*R )과 '선택기'( b*(a%2)대신 )로 과 같은 결과 [0,b][a%2]가 나타납니다.

118 바이트

a,b=input()
s=0
while a:print'%3s%9s'%(a,'[ %%dd] '[a%2::2]%b);s+=a%2*b;a/=2;b*=2
print'%10s==\n%11s'%('='*len(`s`),s)

온라인으로 사용해보십시오!


설명:

a,b=input()                   #Get input
L=len(`a`)                    #Get length of first number for adjusting text
l=[]                          #Output list
s=0                           #Sum
while a:
 B=['[%d]',' %d '][a%2]%b     #B is either '[b]' or ' b ' depending on if a is odd/even
 l+=[(`a`,B)]                 #Add a,B to output list
 s+=[0,b][a%2]                #Add b to sum if a is odd
 a/=2;                        #Halve a
 b*=2;                        #Double b
R=len(B)                      #Length of last B for adjusting output
l+=[('',''.rjust(R,'='))]     #Add double line ==== to output list
l+=[('','%d '%s)]             #Add sum to output list
for x,y in l:
 print x.rjust(L),y.rjust(R)  #Print adjusted numbers


4

자바 (오픈 JDK 8) , 353 (316) 267 214 210 바이트

(a,b)->{int g=0;for(;a>0;g+=a%2*b,a/=2,b*=2)System.out.printf("%1$8d%2$10s\n",a,a%2<1?"["+b+"]":b+" ");System.out.printf("%1$19s%2$18s","".valueOf(new char[(int)Math.log10(g)+3]).replace("\0","=")+"\n",g+" ");}

온라인으로 사용해보십시오!


1
214 바이트 :(a,b)->{int g=0;for(;a>0;g+=a%2*b,a/=2,b*=2)System.out.printf("%1$8d%2$10s\n",a,a%2<1?"["+b+"]":" "+b+" ");System.out.printf("%1$19s%2$18s","".valueOf(new char[(int)Math.log10(g)+3]).replace("\0","=")+"\n",g+" ");}
Nevay

@Nevay a%2*b좋고 간단합니다, 감사합니다
Roberto Graham

4

Mathematica, 264 바이트

(s=#;k=(i=IntegerLength)@s;t=#2;w=0;P=Print;T=Table;While[s>0,If[OddQ@s,P[""<>T[" ",k-i@s],s,"  ",""<>T[" ",i[s(t)]-i@t],t];w=w+t,P[""<>T[" ",k-i@s],s,""<>T[" ",i[s(t)]-i@t]," [",t,"]"]];s=Quotient[s,2];t=2t];P[" "<>T[" ",k],""<>T["=",i@w+2]];P["  "<>T[" ",k],w])&


입력

[19,427]

산출

19   427  
 9   854  
 4 [1708]  
 2 [3416]  
 1  6832  
   ======  
    8113  

infix notation을 사용하여 무려 1 바이트를 절약 할 수 있습니다 . s=Quotient[s,2]:)
numbermaniac

3

펄 5 , 157 바이트

155 바이트 코드 + 2 명령 줄 플래그 ( -nl)

$\=<>;$w=y///c;$y=2+length$\<<((log)/log 2);while($_){$s+=$\if$_%2;printf"%${w}s %${y}s\n",$_,$_%2?$\.$":"[$\]";$_>>=1;$\<<=1}say$"x++$w,'='x$y;say$"x++$w,$s

온라인으로 사용해보십시오!


3

자바 스크립트 2017, 221 바이트

대부분 출력 형식 문제

(a,b)=>{for(t=b,r=0,l=[],w=`${a}`.length;a;l.push([a,t]),a>>=1,t+=t)z=`${r+=a&1&&t}`.length+2;P=(s,w)=>`${s}`.padStart(w);return[...l.map(([a,b])=>P(a,w)+P(a&1?b+' ':`[${b}]`,z+1)),P('='.repeat(z),z-~w),P(r,z+w)].join`
`}

덜 골프

(a, b) => {
  var w=`${a}`.length, r=0, l=[]
  while(a) {
    r += a&1 && b
    l.push([a,b])
    a >>= 1
    b += b
  }
  // algo complete, result in r, now display it and the steps in l[]
  var z=`${r}`.length+2
  var P= (s,w) => `${s}`.padStart(w)
  return [... l.map( ([a,b]) => P(a,w) + P(a&1?b+' ' : `[${b}]`, z+1) )
    , P('='.repeat(z), z+w+1)
    , P(r, z+w)
  ].join`\n`
}

테스트

var F=
(a,b)=>{for(t=b,r=0,l=[],w=`${a}`.length;a;l.push([a,t]),a>>=1,t+=t)z=`${r+=a&1&&t}`.length+2;P=(s,w)=>`${s}`.padStart(w);return[...l.map(([a,b])=>P(a,w)+P(a&1?b+' ':`[${b}]`,z+1)),P('='.repeat(z),z-~w),P(r,z+w)].join`
`}

function update(){
  var i=I.value, [a,b]=i.match(/\d+/g)
  O.textContent=F(+a,+b)
}

update()
<input id=I value='21x348' oninput='update()'><pre id=O></pre>


이 질문을 다시 방문하면 padStart가 정확히 무엇을합니까? 나는 ...이 방법을 인식하지 않습니다
WallyWest


IE에서 이것을 실행하는 데 짜증이납니다! ;)
WallyWest

3

C, C ++, 319 (313) 301 299 바이트

Zacharý 덕분에 -8 바이트

printf방금 편집 사이에 60 분 동안 배운 마법 덕분에

#include<string.h>
#include<stdio.h>
#define O printf("%*d %c%*d%c\n",5,a,a%2?32:91,9,b,a%2?32:93);
void m(int a,int b){int r=0,i=0;O while(a>1){r+=a%2*b;a/=2;b*=2;O}r+=b;char t[20],p[20];memset(t,0,20);memset(p,0,20);sprintf(t,"%d",r);memset(p,61,strlen(t)+2);printf("%*c%*s\n%*d",5,32,12,p,16,r);}

C ++ 최적화, 헤더를 대체 stdio.h함으로써 cstdiostring.hcstring 2 바이트를 저장,

MSVC로 컴파일하려면 #pragma warning(disable:4996)사용하기 위해 추가 해야합니다.sprintf

내 PPCG ID로 테스트 :

72 x 535 =>

   72 [      535]
   36 [     1070]
   18 [     2140]
    9       4280
    4 [     8560]
    2 [    17120]
    1      34240
          =======
           38520

규칙을 준수하고 숫자가 정렬되며 등호는 항상 최종 숫자보다 2 문자 더 큽니다. 17 x 34 => 예

   17         34
    8 [       68]
    4 [      136]
    2 [      272]
    1        544
            =====
             578

마지막 두 줄을 다음 #define O printf("%*d %c%*d%c\n",5,a,a%2?' ':'[',9,b,a%2?' ':']');과 같이 바꿀 수 있다고 생각합니다.void m(int a,int b){int r=0,i=0;O while(a>1){r+=a%2*b;a/=2;b*=2;O}r+=b;char t[20],p[20];memset(t,0,20);memset(p,0,20);sprintf(t,"%d",r);for(;i<strlen(t)+2;++i)p[i]='=';printf("%*c%*s\n%*d",5,' ',12,p,16,r);}
Zacharý

그래, 나도 알지만 왜 중요한가? 또한 광고의 우선 순위 %*동일하므로 r+=a%2*b작동해야합니다.
Zacharý

@ Zacharý 사실, 내가 틀렸다, 당신 말이 맞아요
HatsuPointerKun

<cstdio>도 포함해야 합니까, 여기서 했던 것과 동일한 트릭을 사용할 수 없습니까?
Zacharý


3

[배시] 144 142 140 131 128 바이트

더 나은 디스플레이 존중, 후행 공백 문자가 있음에 유의하십시오.

read a b;for((;a;));{ ((a%2))&&((r+=b))&&x=$b\ ||x=[$b];printf %3s%9s\\n $a "$x"
((a/=2,b+=b));};printf %12s\\n =${r//?/=}= $r\ 

첫 번째 답변

read a b;while((a));do ((a%2))&&((r+=b))&&printf "%6s  %6s
" $a $b||printf "%6s [%6s]
" $a $b;((a/=2,b+=b));done;printf "%6s %7s
" \  ==== \  $r

2

하스켈 , 305 바이트

i=iterate
s=show
l=length.s
a!b=zip((takeWhile(>0).i(`div`2))a)(i(*2)b)
a?b=sum[y|(x,y)<-a!b,rem x 2>0]
a%b=l(snd.last$a!b)
a#b=unlines$[(' '<$[1..l a-l x])++s x++(' '<$[-1..a%b-l y])++if mod x 2<1then show[y]else(' ':s y)|(x,y)<-a!b]++map((++)(' '<$[-1..l a+a%b-l(a?b)]))['='<$[1..l a+1+a%b],' ':(s$a?b)]

온라인으로 사용해보십시오!

!연산자, 두리스트를 생성 ?하는 제품을 산출한다. %#아스키 레이아웃에 사용됩니다.


1

C, 205 201 190 183 156 150 143 바이트

이것은 C89와 같은 경고로 컴파일되며 유효한 C99라고 생각하지 않지만 HatsuPointerKun 버전보다 작습니다. #include필요에 따라 동적 길이를 사용하지 않고 동적 길이를 사용하지 않고 바이트를 생략하여 바이트를 절약합니다. log10()의 수를 계산하는 데 사용= 필요한 .

r;m(a,b){r=0;while(a){printf(a%2?"%4d%10d\n":"%4d [%8d]\n",a,b);r+=a%2?b:0;a/=2;b<<=1;}printf("%15.*s\n%14d",(int)log10(r)+3,"==========",r);}

내 번호는 64586이므로이 테스트 프로그램을 사용하여 64 * 586다음 을 계산했습니다 .

#include <stdio.h>
int m(int a, int b);
int main(void)
{
    m(64, 586);
    putchar('\n');
}

& 그것은 출력합니다 :

  64 [     586]
  32 [    1172]
  16 [    2344]
   8 [    4688]
   4 [    9376]
   2 [   18752]
   1     37504
        =======
         37504

편집하다

"암시 적 int"규칙에 의해 4 바이트 저장

편집 2

do...while()루프 로 변경 하고 printf를 매크로에서 루프로 이동하여 11 바이트를 절약했습니다 . 다음과 같은 경우에도 올바르게 작동해야합니다a=1 .

편집 3

7 바이트를 절약하고 코드가 올바르게 작동하도록했습니다.

편집 4

일부 printf 속임수로 26 바이트를 절약했습니다.

편집 5

여분의 패딩을 1 개의 숫자로 축소하여 6 바이트를 절약했습니다.

편집 6

삼항 연산자로 printf 트릭으로 7 바이트를 절약하고 사용하지 않는 변수를 선언하지 않았습니다.


잘 했어, 저스틴! 앞으로 몇 주 안에 더 많은 정보를 볼 수 있기를 기대합니다!
WallyWest

감사합니다. 앞으로 몇 주 안에 더 많은 일을하기를 바랍니다.
JustinCB 2016 년

1

Excel VBA, 183 바이트

범위에서 입력 [A1:B1]을 받아 콘솔로 출력 하는 익명의 VBE 즉시 창 기능 .

a=[A1]:b=[B1]:While a:c=a Mod 2=0:?Right(" "& a,2);Right("   "&IIf(c,"["&b &"]",b &" "),7):s=s+IIf(c,0,b):a=Int(a/2):b=b*2:Wend:?Right("     "&String(Len(s)+2,61),9):?Right("    "&s,8)

언 골프

Sub EthiopianMultiply(ByVal a As Integer, b As Integer)
    While a
        Let c = a Mod 2 = 0
        Debug.Print Right(" " & a, 2);
        Debug.Print Right("    " & IIf(c, "[" & b & "]", b & " "), 7)
        Let s = s + IIf(c, 0, b)
        Let a = Int(a / 2)
        Let b = Int(b * 2)
    Wend
    Debug.Print Right("     " & String(Len(s) + 2, 61), 9)
    Debug.Print Right("     " & s, 8)
End Sub

산출

61   486 
30  [972]
15  1944 
 7  3888 
 3  7776 
 1 15552 
  =======
   29646
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.