乗算せずに乗算[クローズ]


8

乗算演算子を使用せずに、正の整数に対して最速(最高のbig-O)および最小の乗算アルゴリズムを記述します。加算、減算、論理関数(AND、OR、XOR、NOT)、ビットシフト、ビットローテーション、ビットフリップ/セット/クリア、ビットテストのみが許可されています。プログラムは、32ビットの結果を生成するために16ビットの数値を乗算できる必要があります。コンマ、スペース、または改行(選択)で区切られた標準入力で入力を受け取りますが、データの入力方法を明確にします。

入力/出力の例:

734 929
681886

1
除算演算子はどうですか?
st0le

3
これはコードゴルフですか、それともチャレンジですか?:-\
st0le

4
最速または小-あなたは両方を持つことはできません、またはあなたはトレードオフを計算するために翻訳式が必要です。
ユーザー不明の

3
最短のコードと最短のコードを比較する方法がまだ解決されていないため、閉じるために「本当の質問ではない」とマークしました。どちらが優先されますか?またはトレードオフはどのような関係にありますか?移植可能なlangの比較アルゴが指定されている場合、それを修復できます。たとえば、Cでstd-algoが500kオペレーションに達し、アルゴが50kに達した場合、コード長* 10を掛ける必要があります。そうすれば、誰でもコードを短くするか、コードを速くするかを選択できます。勝者は両方のカテゴリの勝者である必要はありませんが、勝者の基準ははるかに客観的です。
ユーザー不明

2
述べられているように、この質問は非常識です。正の整数に対する漸近的に最も高速な既知の乗算アルゴリズムは、フュラーのアルゴリズム(en.wikipedia.org/wiki/F%C3%BCrer%27s_algorithm)であり、途方もなく複雑であり、どの言語でも何千行も実装する必要があります。私は彼が実際にあなたのアルゴリズムがO(n ^ 2)(長い乗算)でなければならないことを実際に意味していると思います。
D Coetzee

回答:


11

C、84 83 78文字

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

より読みやすい形式で

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

このアルゴリズムは、エチオピアの乗算またはロシアの農民の乗算としてよく知られています。アルゴリズムは次のとおりです。

  1. 乗算する2つの数値をaとbとします。
  2. aがゼロの場合、結果を分割して出力します。
  3. aが奇数の場合、結果にbを追加します。
  4. ハーフa、ダブルb。ステップ2に進みます。

初期化しないと機能しないm=0(少なくとも私にとって)
st0le

@ st0leこれで動作します。'm 'をmain関数の先頭に移動しました。こちらをご覧ください:ideone.com/XCz8C
fR0DDY

これについては忘れてfor(;(a&1&&m+=b)|a;a>>=1,b<<=1);しまいました。こちらは短いものですはい、とても恥ずかしいです。:)
st0le

for(m=0;(a&1&&m+=b)|a;a/=2,b*=2);なぜシフトを使うのですか?
st0le

2
@ fR0DDY:のb+=b代わりに言うことができますb*=2。もちろん、それでも正しいシフトが必要です。
Joey Adams

7

APL(5)

改行で区切られた標準入力で入力を受け取ります。

+/⎕⍴⎕

5

Golfscript-12文字

~0\{1$+}*\;

ことに注意してください*ここではない乗算演算子は、それが二次利用を参照して、代わりに繰り返し演算子です、ここ


4

Golfscript-27文字

農民の掛け算。最初に*があり、乗算があります、0または1のみです

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

これは31文字でオンで、まったく乗算されません。

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

4

Python、64文字

おそらく最も効率的ではありません(または最も準拠していますが、私は「追加」しています)。

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

7
input()代わりにint(raw_input())を使用して18文字を保存できます。あなたは、この不正行為を検討するかもしれませんが、print sum([input()]*input())また、(作品*の繰り返しではなく、乗算に使用されています)。
James

r=input;a=r();print sum(map(lambda x:a,range(r())))はるかに短い
Joel Cornett

@JoelCornett r=input;a=r();r(sum(a for b in range(r())))はさらに短い(43 vs 51バイト)
FatalError



2

J、18 17文字

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

入力はスペースで区切る必要があります。


2

Python、64文字

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

1
割り当てi=inputて使用することで短縮できますi()
st0le

3
実際には、同じ数の文字になることがわかっています
Doug T.

2
置き換えることができ0 if n==0 elsen and
再帰

1

VBA、70文字

これは実際には多数の場合は非常に遅いですが、小さいです。スピードを改善しながらコードサイズを改善することができました。計算時間は、サイズだけでなく、引数の位置によって異なります。(つまり、1000、5000は約4秒で計算され、5000、1000は約19秒で計算されます)OPは高速と小型の両方をリストしているので、私はこれでうまくいくと考えました。入力は、カンマで区切られた2つの数値引数です。

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

この長いバージョン(103文字)は、2つの可能な配置のうちの速い方で実行できるようにします。

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

To連結の前および連結で空白を削除することにより、およびDebug.?
テイラースコット

1

Perl:52文字

これは古い質問ですが、Perlを表す必要があります。

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

(これはバイナリアルゴリズムである。反復添加は小さいが、方法は、退屈します。)

このプログラムには意図しない機能が含まれています。入力行に3番目の数値が含まれている場合、プログラムは実際にA * B + Cを計算します。


どれくらい速いですか?
ユーザー不明

当然、O(log n)で実行されます。実際の速度について質問しますか?私のマシンでは、Perlの組み込み乗算よりも約2〜3倍遅い速度で測定しますが、それがどれほど重要かはわかりません。
ブレッドボックス、2012年

1

サイズに最適化されたScalaのバリエーション:48文字

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

少し速度を最適化:

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

(a> b)の場合、(a、b)を交換して、より早く最後に​​到達します。mul(1023,31)を呼び出すと、そのコード行を省略した場合と比較して、11〜20ステップ異なります。

ゴルフ:95文字:

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

ルビー、35文字

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

これは、単なる関数ではなく、入出力を行うプログラムです。

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

1

Ruby、35バイト

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

使用法: x([123, 456]) #=> 56088

数値がARGVから読み取られる場合はおそらく短くなる可能性がありますが、それらが間違った形式(intではなく文字列)であるという不満があります。どんな提案も素晴らしいでしょう。


0

Mathematica 12

以下は、の#2インスタンスを合計したものです#1

コード

#1~Sum~{#2}&

使用法

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

(* out *)

681886


9文字?

プログラム・パラメータが、場合はab入力のために使用することができる、同じ結果を用いて達成することができる9つの文字

a~Sum~{b}

0

VB11、101文字

   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
あなたはいくつかの許可されていない操作を使用しました...
Gaffi

私はこれが許可されていない操作を使用しているとは思いません(制御フローが許可されていない限り。それについての質問は不明確であり、それが保留されている理由の一部です)。「mod 2」はビットテスト操作です。==質問では比較()は許可されていませんが、多くの回答がそれらを使用しています。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.