Nhân mà không nhân [đóng]


8

Viết thuật toán nhân nhanh nhất (big-O tốt nhất) và nhỏ nhất cho các số nguyên dương, mà không sử dụng các toán tử nhân. Bạn chỉ được phép cộng, trừ, các hàm logic (AND, OR, XOR, KHÔNG), dịch chuyển bit, xoay bit, lật / đặt / xóa bit và kiểm tra bit. Chương trình của bạn phải có khả năng nhân các số 16 bit để tạo ra kết quả 32 bit. Lấy đầu vào trên stdin, phân tách bằng dấu phẩy, dấu cách hoặc dòng mới (lựa chọn của bạn), nhưng làm rõ cách nhập dữ liệu.

Ví dụ đầu vào / đầu ra:

734 929
681886

1
Còn toán tử phân chia thì sao?
st0le

3
Đây là codegolf hay một thách thức? : - \
st0le

4
Nhanh nhất HOẶC nhỏ - bạn không thể có cả hai hoặc bạn cần một công thức dịch thuật để tính toán sự đánh đổi.
người dùng không xác định

3
Tôi đã đánh dấu để đóng là "không phải là một câu hỏi thực sự", vì vẫn chưa có giải pháp, làm thế nào để so sánh mã nhanh nhất và ngắn nhất. Đó là ưu tiên? Hoặc trong mối quan hệ nào là sự đánh đổi? Nó có thể được chữa lành nếu một số so sánh trong một lang di động được đưa ra - ví dụ: nếu std-algo đạt 500k thao tác trong C và thuật toán của bạn đạt 50k, bạn phải nhân số bước sóng * 10. Bằng cách đó, mọi người có thể chọn rút ngắn mã hoặc làm cho mã nhanh hơn. Người chiến thắng không cần phải là người chiến thắng ở cả hai hạng mục, nhưng tiêu chí chiến thắng sẽ khách quan hơn nhiều.
người dùng không xác định

2
Câu hỏi này là điên rồ như đã nêu. Thuật toán nhân nhanh nhất được biết đến nhanh nhất cho các số nguyên dương là thuật toán của Fürer ( en.wikipedia.org/wiki/F%C3%BCrer%27s_alacticm ) và nó phức tạp một cách kỳ cục và sẽ mất hàng ngàn dòng để thực hiện bằng bất kỳ ngôn ngữ nào. Tôi giả sử anh ta thực sự chỉ có nghĩa là thuật toán của bạn phải là O (n ^ 2) (phép nhân dài).
D Coetzee

Câu trả lời:


11

C, 84 83 78 Ký tự

m;main(a,b){for(scanf("%d%d",&a,&b);a;b+=b)a&1?m+=b:0,a>>=1;printf("%d\n",m);}

Ở dạng dễ đọc hơn

m;main(a,b)
{
    scanf("%d%d",&a,&b);
    while (a)
    {
        if (a&1)
           m+=b;
        a>>=1;
        b+=b;
    }
    printf("%d\n",m);
}

Thuật toán được biết đến nhiều hơn với tên gọi là phép nhân của người Ê-ti-ô hoặc phép nhân nông dân Nga. Đây là thuật toán:

  1. Đặt hai số được nhân là a và b.
  2. Nếu a bằng 0 thì ngắt và in kết quả.
  3. Nếu a là số lẻ thì thêm b vào kết quả.
  4. Nửa a, Đôi b. Bước 2.

không hoạt động mà không khởi tạo m=0(ít nhất cho tôi)
st0le

@ st0le Nó sẽ hoạt động ngay bây giờ, tôi đã chuyển 'm' sang chức năng chính. Xem tại đây: ideone.com/XCz8C
fR0DDY

Quên cái này đi, đây là cái ngắn hơn for(;(a&1&&m+=b)|a;a>>=1,b<<=1);Có, tôi rất xấu hổ. :)
st0le

for(m=0;(a&1&&m+=b)|a;a/=2,b*=2);Tại sao sử dụng ca, phải không?
st0le

2
@ fR0DDY: Bạn có thể nói b+=bthay vì b*=2. Tất nhiên, bạn vẫn sẽ cần sự thay đổi phù hợp.
Joey Adams

7

APL (5)

Đưa đầu vào vào đầu vào tiêu chuẩn được phân tách bằng dòng mới.

+/⎕⍴⎕

5

Golfscript - 12 nhân vật

~0\{1$+}*\;

Xin lưu ý rằng *ở đây không phải là toán tử nhân, thay vào đó là toán tử lặp lại, hãy xem cách sử dụng thứ hai ở đây .


4

Golfscript - 27 ký tự

Nông dân nhân lên. Có * đầu tiên trong đó một nhân, nhưng chỉ bằng 0 hoặc 1

~2base-1%{1&\..+\@*}%{+}*\;

Đây là lúc 31 ký tự không nhân lên chút nào

~2base-1%{1&\..+\[0\]@=}%{+}*\;

4

Python, 64 ký tự

Có lẽ không phải là hiệu quả nhất mặc dù (hoặc tuân thủ nhất, nhưng tôi đang "thêm", phải không?):

a=int(raw_input())
print sum(a for i in range(int(raw_input())))

7
Bạn có thể sử dụng input()thay int(raw_input())cho 18 ký tự. Bạn có thể xem xét sự gian lận này, nhưng print sum([input()]*input())cũng hoạt động ( *đang được sử dụng để lặp lại, không nhân lên).
James

r=input;a=r();print sum(map(lambda x:a,range(r())))ngắn hơn nhiều
Joel Cornett

@JoelCornett r=input;a=r();r(sum(a for b in range(r())))thậm chí còn ngắn hơn (43 so với 51 byte)
FatalError


2

Golf - 43

~\:@;0 1{.3$&{\@+\}{}if@@+:@;.+.3$>!}do;\;

Thực hiện phép nhân nông dân . Tôi nghĩ rằng tôi có thể chơi golf thêm một số lần sau.


2

J, 18 17 ký tự

+/({.${:)".1!:1]3

Đầu vào cần phải được phân tách không gian.


2

Python, cũng 64 ký tự

m=lambda x,n:0 if n==0 else x+m(x,n-1);print m(input(),input())

1
Bạn có thể rút ngắn nó bằng cách gán i=inputvà sử dụngi()
st0le

3
thực ra điều đó có cùng số lượng nhân vật
Doug T.

2
có thể thay thế 0 if n==0 elsebằngn and
đệ quy

1

VBA, 70 ký tự

Điều này thực sự khá chậm đối với số lượng lớn, nhưng nó nhỏ. Tôi quản lý để cải thiện kích thước mã trong khi cải thiện tốc độ. Thời gian tính toán khác nhau, tùy thuộc vào vị trí đối số - không chỉ kích thước. (tức là 1000, 5000 tính toán trong khoảng 4 giây trong khi 5000, 1000 tính toán trong khoảng 19) Vì OP liệt kê cả nhanh và nhỏ, tôi cho rằng tôi sẽ đi với cái này. Đầu vào là hai đối số số, được phân tách bằng dấu phẩy.

Sub i(j,k)
For m=1 To j:n=n & String(k," "):Next
MsgBox Len(n)
End Sub

Phiên bản dài hơn này ( 103 ký tự ) sẽ đảm bảo nó chạy với tốc độ nhanh hơn trong hai cách sắp xếp có thể:

Sub i(j,k)
If j<k Then a=j:b=k Else b=j:a=k
For m=1 To a:n=n & String(b," "):Next
MsgBox Len(n)
End Sub

Bạn có thể mất khá nhiều byte bằng cách xóa khoảng trắng trước Tovà ghép, cũng như bằng cách xuất ra cửa sổ ngay lập tức VBE quaDebug.?
Taylor Scott

1

Perl: 52 ký tự

Đây là một câu hỏi cũ, nhưng Perl cần được đại diện:

perl -pl '($m,$n,$_)=split;$_+=$m&1&&$n,$m>>=1,$n<<=1while$m'

(Đây là thuật toán nhị phân; lặp Ngoài ra là nhỏ hơn nhưng cách quá nhàm chán.)

Chương trình này bao gồm một tính năng không chủ ý: nếu dòng đầu vào của bạn chứa số thứ ba, chương trình sẽ thực sự tính A * B + C.


Nó nhanh như thế nào
người dùng không xác định

Nó chạy trong O (log n), một cách tự nhiên. Bạn đang hỏi về tốc độ thực tế của nó? Trên máy của tôi, tôi đo chậm hơn khoảng 2-3 lần so với số nhân tích hợp của Perl, nhưng tôi không biết điều đó có ý nghĩa như thế nào.
hộp bánh mì

1

Một biến thể trong Scala, được tối ưu hóa cho kích thước: 48 ký tự

def m(a:Int,b:Int):Int=if(b==1)a else a+m(a,b-1)

tối ưu hóa cho tốc độ một chút:

def mul (a:Int, b:Int) : Int = {
  print (".")
  if (a == 1) b
  else if (a > b) mul (b, a)
  else if (a % 2 == 0) mul (a >> 1, b << 1) 
  else b + mul (a - 1, b) 
}

Tôi trao đổi (a, b) nếu (a> b), để đạt được kết thúc nhanh hơn. Sự khác biệt là 11 đến 20 bước, khi gọi mul (1023,31), so với việc bỏ qua dòng mã đó.

đánh gôn: 95 ký tự:

def m(a:Int,b:Int):Int=if(a==1)b
else if(a>b)m(b,a)
else if(a%2==0)m(a>>1,b<<1)
else b+m(a-1,b)

1

K, 18 16

{#,/(!y),\:/:!x}

.

k){#,/(!y),\:/:!x}[4;20]
80
k){#,/(!y),\:/:!x}[13;21]
273
k){#,/(!y),\:/:!x}[3;6]
18

1

Ruby, 35 ký tự

p $*.map!(&:to_i).pop*$*.inject(:+)

Đây là một chương trình , nhận đầu vào và đầu ra, không chỉ là một chức năng.

.-(~/virt)-----------------------------------------------------------------------------------------------------------------------------------------------------(ice@distantstar)-
`--> wc -c golf.rb         
35 golf.rb
.-(~/virt)-----------------------------------------------------------------------------------------------------------------------------------------------------(ice@distantstar)-
`--> ruby ./golf.rb 734 929
681886

1

Ruby, 35 byte

def x(a)Array.new(*a).inject :+end

Sử dụng: x([123, 456]) #=> 56088

Có thể rút ngắn nếu các số được đọc từ ARGV, nhưng nó phàn nàn về chúng là định dạng sai (chuỗi, không phải ints). Bất kỳ đề xuất nào cũng sẽ rất tuyệt.


0

Toán học 12

Các #2trường hợp sau đây của #1.

#1~Sum~{#2}&

Sử dụng

#1~Sum~{#2} &[734, 929]

(* out *)

681886


9 ký tự?

Nếu các thông số chương trình, a, b, có thể được sử dụng cho đầu vào, kết quả tương tự có thể đạt được với 9 ký tự .

a~Sum~{b}

0

VB11, 101 ký tự

   Dim m As Func(Of Integer, Integer, Integer, Integer) = Function(a, b, t) If(a = 0, t, m(a >> 1, b << 1, t + If(a Mod 2 = 1, b, 0)))

1
Bạn đã sử dụng một vài thao tác không được phép ...
Gaffi

Tôi không nghĩ rằng điều này sử dụng các hoạt động không được phép (trừ khi luồng điều khiển không được phép; câu hỏi không rõ ràng về điều đó, đó là một phần lý do khiến nó bị hoãn). "mod 2" là một hoạt động kiểm tra bit. Tôi đoán so sánh ( ==) không được phép bởi câu hỏi, nhưng có rất nhiều câu trả lời đang sử dụng chúng.
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.