Phép nhân


17

Câu hỏi này được lấy cảm hứng từ câu trả lời này . Thật trùng hợp, tôi đã từng sử dụng phép nhân của người Ethiopia khi tôi còn là một đứa trẻ, nhưng chưa bao giờ biết tên của phương pháp này cho đến gần đây.

Phép nhân của người Ê-ti-ô là một phương pháp nhân các số nguyên chỉ sử dụng phép cộng, nhân đôi và chia đôi.

Phương pháp:

  1. Lấy hai số để được nhân và viết chúng xuống ở đầu hai cột.
  2. Trong cột bên trái liên tục giảm một nửa số cuối cùng, loại bỏ mọi phần dư và viết kết quả bên dưới số cuối cùng trong cùng một cột, cho đến khi bạn viết giá trị 1.
  3. Trong cột bên phải liên tục nhân đôi số cuối cùng và viết kết quả bên dưới. dừng khi bạn thêm một kết quả trong cùng một hàng với nơi cột bên trái hiển thị 1.
  4. Kiểm tra bảng được tạo và loại bỏ bất kỳ hàng nào trong đó giá trị trong cột bên trái là chẵn. Tính tổng các giá trị trong cột bên phải vẫn tạo ra kết quả nhân hai số ban đầu với nhau.

Ví dụ: 17 x 34

17    34

Giảm một nửa cột đầu tiên:

17    34
 8
 4
 2
 1

Nhân đôi cột thứ hai:

17    34
 8    68
 4   136 
 2   272
 1   544

Các hàng xuất hiện có ô đầu tiên là số chẵn, chúng tôi sẽ thực hiện điều này bằng cách đặt các số đó ở bên phải trong dấu ngoặc vuông:

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

Tính tổng các số còn lại trong cột bên phải:

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

Vậy 17 nhân với 34, theo phương pháp của người Ê-ti-ô là 578.

Nhiệm vụ:

Mã golf có hai số từ 1 đến 1000 và thực hiện cùng bố cục và thuật toán, hiển thị sản phẩm bên dưới.

Phương thức nhập: Tuy nhiên, bạn chọn ...

Ví dụ đầu vào:

19 427

Kết quả đầu ra:

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

Xin lưu ý sự liên kết của các chữ số. Điều này là quan trọng nhất trong bố trí. Cũng lưu ý rằng dòng kép được đặt bằng các dấu bằng phải dài hơn hai ký tự so với câu trả lời chung và phải là trung tâm hợp lý.

Kiểm tra

Làm thế nào bạn sẽ được thử nghiệm này? Bằng cách cung cấp một chương trình của bạn bằng cách sử dụng hai số. Những số này có thể được trích xuất từ ​​số ID người dùng của bạn (có thể lấy số này bằng cách di con trỏ lên hình đại diện của bạn trên cửa sổ trên cùng). Lấy số của bạn và lấy ba chữ số cuối cùng, đây sẽ là số B, lấy bất cứ thứ gì còn lại ở phía trước, đó sẽ là số A. Sau đó kiểm tra A lần B.

Ví dụ kiểm tra:

Số ID người dùng của tôi là 8555, vì vậy số của tôi là 8 và 555. Vì vậy, đầu ra của tôi sẽ giống như thế này:

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

Những hạn chế:

Không có toán tử nhân nào được phép lưu trong khi sử dụng "nhân đôi", như được đề cập trong thuật toán. Nói cách khác, nếu bạn đang sử dụng một toán tử như *, thì nó chỉ có thể được sử dụng để nhân 2 mà thôi.

Các tác phẩm không tuân thủ điều này sẽ không được xem xét và người dùng sẽ được hộ tống ra khỏi cơ sở với một hộp các tông chứa đầy đồ đạc của họ. Mỗi mục sẽ có mã, cộng với kiểm tra dựa trên số ID người dùng của bạn.

Đây là mã golf. Số byte ngắn nhất sẽ nhận được giải thưởng, vinh quang và sự ngưỡng mộ của các đồng nghiệp của họ ... (Và có thể là một chiếc Lamborghini ... Tôi đã nói "có thể"!)


5
"Không nhân giống thực tế phải diễn ra." - Điều này là không thể quan sát được. Bạn có thể hạn chế sử dụng một số ký tự (như *hoặc x), nhưng không thể phát hiện xem phép nhân có được sử dụng hay không. Ngoại trừ phần đó, thử thách là thú vị.

Có lẽ bạn nên yêu cầu mô tả đầy đủ về mã chứng minh rằng thuật toán được triển khai không có phép nhân HOẶC mô phỏng không giới hạn cung cấp đầu ra mong muốn. Nhưng đó có vẻ là hai thách thức riêng biệt đối với tôi.
Arnauld

1
Như đã lưu ý trong hộp cát, có liên quan, có thể bị lừa . @FelixPalmen, vâng, đây là phép nhân dài trong hệ nhị phân.
Peter Taylor

Câu trả lời:


8

Than , 91 byte

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

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Giải trình:

≔⟦⟧τ≔⁰σ

Đặt tvào danh sách trống và sđến 0. ( uđã được mặc định cho danh sách trống.)

NθNη

Nhập hai số.

Wθ«

Lặp đi lặp lại trong khi qlà khác không.

   ⊞τ⪫  Iθ

Bọc qtrong phần đệm và nối nó vào danh sách t.

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

Bọc hhoặc trong phần đệm hoặc []tùy thuộc vào việc qcó lẻ hay không và thêm nó vào danh sách u.

   ≔⁺σ∧﹪θ²ησ

Thêm hvào snếu qlà số lẻ.

   ≔÷θ²θ

Số nguyên chia qcho 2.

   ≔⁺ηηη»

Thêm hvào chính nó.

⊞υ…=⁺²LIσ

Nối một chuỗi các =dấu hiệu phù hợp vào danh sách u.

⊞υ⪫  Iσ

Nối tổng số đệm svào danh sách u.

←E⮌τ⮌ι

Xoay danh sách t180 ° và in nó úp xuống, do đó, chứng minh đúng.

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

Di chuyển con trỏ sao cho khi uđược chứng minh đúng góc trên cùng bên trái của nó thẳng hàng với góc trên bên phải chúng ta vừa chạm tới và in ubên phải.


Công việc tuyệt vời. Bạn đã dẫn đầu cho đến nay, @Neil. Tôi có thể tìm hiểu thêm về ngôn ngữ ở đâu, có liên kết không?
WallyWest

1
@WallyWest Tiêu đề được liên kết đến trang GitHub và từ đó bạn có thể đọc wiki để biết thêm thông tin.
Neil

8

Python 2 , 203 202 187 133 byte

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)

Hãy thử trực tuyến!

Nếu tôi có thể sử dụng *để nhân chuỗi ( '='*R) và làm 'bộ chọn' ( b*(a%2)thay vì [0,b][a%2]), tôi nhận được:

118 byte

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)

Hãy thử trực tuyến!


Giải trình:

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

Java (OpenJDK 8) , 353 316 267 214 210 byte

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

Hãy thử trực tuyến!


1
214 byte:(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đẹp và đơn giản, cảm ơn bạn
Roberto Graham

4

Toán học, 264 byte

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


đầu vào

[19,427]

đầu ra

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

Bạn có thể có thể tiết kiệm được một byte bằng cách sử dụng ký hiệu infix trên s=Quotient[s,2]:)
numbermaniac

3

Perl 5 , 157 byte

155 byte mã + 2 cờ dòng lệnh ( -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

Hãy thử trực tuyến!


3

JavaScript 2017, 221 byte

Chủ yếu là một vấn đề về định dạng đầu ra

(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`
`}

Ít chơi gôn

(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`
}

Kiểm tra

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>


chỉ cần xem lại câu hỏi này ... padStart làm gì chính xác? Tôi không nhận ra phương pháp này ...
WallyWest


Sẽ hút để được chạy này trong IE! ;)
WallyWest

3

C, C ++, 319 313 301 299 byte

-8 byte nhờ Zacharý

Rất cảm ơn printfphép thuật tôi mới học được trong 60 phút giữa các lần chỉnh sửa

#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 ++ tối ưu hóa, thay thế tiêu đề stdio.hbằng cstdiostring.hbởi cstring, tiết kiệm 2 byte

Biên dịch với MSVC yêu cầu thêm #pragma warning(disable:4996)để sử dụngsprintf

Kiểm tra với ID PPCG của tôi:

72 x 535 =>

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

Nó tôn trọng các quy tắc, chữ số được căn chỉnh và các dấu bằng sẽ luôn lớn hơn 2 char so với số cuối cùng. Ví dụ với 17 x 34 =>

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

Tôi nghĩ bạn có thể thay đổi hai dòng cuối cùng thành #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ý

Vâng, tôi biết điều đó, nhưng tại sao điều đó lại quan trọng?. Quảng cáo cũng vậy, ưu tiên %*giống nhau, r+=a%2*bnên hoạt động.
Zacharý

@ Zacharý trên thực tế, tôi đã sai, bạn đúng
HatsuPulumKun

Bạn thậm chí có cần bao gồm <cstdio> không, bạn có thể sử dụng cùng một mẹo bạn đã làm ở đây không?
Zacharý


3

[Bash], 144 142 140 131 128 byte

Tôn trọng hơn màn hình, lưu ý có một ký tự không gian dấu

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\ 

Câu trả lời đầu tiên

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

Haskell , 305 byte

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

Hãy thử trực tuyến!

Các !nhà điều hành sẽ tạo ra hai danh sách, ?tính toán sản phẩm. %#được sử dụng cho bố trí ascii.


1

C, 205 201 190 183 156 150 143 byte

Điều này sẽ biên dịch với các cảnh báo là C89, và tôi không tin đó là C99 hợp lệ, nhưng cuối cùng nó nhỏ hơn phiên bản của HatsuPulumKun, vì nó tiết kiệm byte bằng #includecách sử dụng, không sử dụng độ dài động để in khi chúng không cần thiết, & sử dụng log10()để tính số lượng= cần thiết:

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

Theo số của tôi 64586, tôi đã sử dụng chương trình kiểm tra này để tính toán64 * 586 :

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

& nó xuất ra:

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

biên tập

đã lưu 4 byte theo quy tắc "ngầm định"

chỉnh sửa 2

đã lưu 11 byte bằng cách thay đổi thành một do...while()vòng lặp và di chuyển printf vào vòng lặp từ một macro. Cũng nên hoạt động chính xác nếu a=1.

chỉnh sửa 3

lưu 7 byte và làm cho mã hoạt động đúng.

chỉnh sửa 4

Lưu 26 ​​byte với một số thủ thuật printf.

chỉnh sửa 5

đã lưu 6 byte bằng cách thu gọn phần đệm thêm vào 1 số.

chỉnh sửa 6

đã lưu 7 byte bằng thủ thuật printf với toán tử ternary & không khai báo một biến không sử dụng


Tuyệt vời, Justin! Mong muốn được nhìn thấy nhiều hơn từ bạn trong những tuần tới!
WallyWest

Cảm ơn bạn. Tôi hy vọng sẽ làm nhiều hơn trong những tuần tới, quá.
JustinCB

1

VBA Excel, 183 byte

Một chức năng cửa sổ ngay lập tức VBE ẩn danh nhận đầu vào từ phạm vi [A1:B1]và đầu ra đến bàn điều khiển.

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)

Bị đánh cắp

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

Đầu ra

61   486 
30  [972]
15  1944 
 7  3888 
 3  7776 
 1 15552 
  =======
   29646
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.