ユークリッドアルゴリズム(最大公約数を見つけるため)


22

チャレンジ

2つの入力の整数を取るプログラムや関数を書いて、iそしてj、それらの最大公約数を出力します。ユークリッドアルゴリズムを使用して計算されます(以下を参照)。


入力

入力は、スペースで区切られた文字列表現としてijまたは2つの別個の整数として取得できます。整数は10,000以下であると想定できます。また、入力整数は互いに素ではないと想定できます。


ユークリッドの内訳

との間の大きい数はijできるだけ小さい数で除算されます。次に、残りが追加されます。このプロセスは、残りがになるまで、残りと前の数で繰り返され0ます。

たとえば、入力が1599 650次の場合:

1599 = (650 * 2) + 299
 650 = (299 * 2) +  52
 299 =  (52 * 5) +  39
  52 =  (39 * 1) +  13
  39 =  (13 * 3) +   0

最後の数、13は2つの入力整数の最大公約数です。次のように視覚化できます。


出力

出力は上記の形式の内訳で、その後に改行とGCDが続く必要があります。任意のメディアを介して出力できます。


入力

18 27
50 20
447 501
9894 2628

出力

27 = (18 * 1) + 9
18 =  (9 * 2) + 0
9

50 = (20 * 2) + 10
20 = (10 * 2) +  0
10

501 = (447 * 1) + 54
447 =  (54 * 8) + 15
 54 =  (15 * 3) +  9
 15 =   (9 * 1) +  6
  9 =   (6 * 1) +  3
  6 =   (3 * 2) +  0
3

9894 = (2628 *  3) + 2010
2628 = (2010 *  1) +  618
2010 =  (618 *  3) +  156
 618 =  (156 *  3) +  150
 156 =  (150 *  1) +    6
 150 =    (6 * 25) +    0
6

注:出力は上にあるため、間隔を空ける必要はありません。間隔は明確にするためだけです。括弧が必要です。


ボーナス

出力の間隔が上記の場合、スコアに-10%のボーナスを追加できます。


1.最大数が最初に与えられると仮定できますか?2.ボーナスの場合、フィールド幅は一定で、最大数の前に1つのスペースを確保するのに十分であることを意味しますか?(数字の2番目の列の左括弧の前にスペースがあります。)出力が可変の場合、「as as above」のようなあいまいな表現は避けてください。必要な出力が修正されていれば問題ありません。
レベルリバーセント

[OK]を私はいくつかの例は、二番目に大きい数を持って見る
レベル川セント

あなたの元のタイトルは大丈夫でした。meta.codegolf.stackexchange.com/q/7043/15599で起こったことについてコメントしました。「最大公分母」というフレーズは間違っていました。「分母」は分数に関連します。「最大公約数」をグーグルで検索すると、「最大公約数/因子」の結果のみが得られます。
レベルリバーセント

タイトルは大丈夫だと思ったが、誰もが不快にならないように「The」に変更した。「除数」、ところで編集してくれてありがとう。@steveverrill
ザック・ゲイツ

回答:


4

Pyth、33バイト

ASQWGs[H\=\(G\*/HG\)\+K%HG)A,KG)H

オンラインで試す:デモンストレーションまたはテストスイート

説明:

ASQWGs[H\=\(G\*/HG\)\+K%HG)A,KG)H
  Q                                read the two numbers from input
 S                                 sort them
A                                  and assign them to G and H
   WG                              while G != 0:
                      K%HG           assign H mod G to K
     s[H\=\(G\*/HG\)\+K   )          join the following list items and print:
                                        H=(G*(H/G))+K
                           A,KG      assign K, G to G, H
                               )   end while
                                H  print H

7

CJam、46 43 39バイト

q~]$3*~\{N5$"=("3$:G'*3$Gmd")+"\}h]7>NG

CJamインタープリターでオンラインで試してください。

使い方

q~]    e# Read all input, evaluate it and wrap the results in an array.
$3*    e# Sort the array and repeat it thrice.
~\     e# Dump the array and swap its last two elements.
{      e# Do:
  N    e#   Push a linefeed.
  5$   e#   Copy the sixth topmost element from the stack.
  "=(" e#   Push that string.
  3$:G e#   Copy the fourth topmost element from the stack. Save it in G.
  '*   e#   Push that character.
  3$   e#   Copy the fourth topmost element from the stack.
  Gmd  e#   Push quotient and remainder of its division by G.
  ")+" e#   Push that string.
  \    e#   Swap the string with the remainder.
}h     e#   If the remainder is positive, repeat the loop.
]7>    e# Wrap the stack in an array and discard its first seven elements.
NG     e# Push a linefeed and G.

6

Python 2、70

f=lambda a,b:b and'%d=(%d*%d)+%d\n'%(a,b,a/b,a%b)*(a>=b)+f(b,a%b)or`a`

複数行の文字列を返す再帰関数。この関数は最初の行を作成し、ユークリッドアルゴリズムの次の数値のペアを使用して再帰的な結果に追加します。2番目の数値がゼロになると、もう一方の数値の文字列をベースケースとして使用し、最後に独自の行に印刷されるようにします。

フォーマットは、整数除算を使用して被乗数を取得する文字列置換によって行われます。

1つのしゃっくりは、小さい数字から大きな数字を取得することから始める必要があります。便利なことに、数値の順序が間違っている場合、ユークリッドアルゴリズムの最初のステップで数値が反転されます。このステップが表示されないようにするには、最初の番号が少なくとも2番目の場合にのみ現在の行を追加します(たとえば、等式が必要ですf(9,9))。


5

awk、78 77

x=$1{for(x<$2?x+=$2-(y=x):y=$2;t=y;x=t)print x"=("y"*"int(x/y)")+",y=x%y}$0=x

入力をサイズでソートするには、大量のバイトが必要です:/
これは次のようになります。

x=$1;
if(x<$2) x+=$2-(y=x); # add $2 subtract $1 and set y to $1
else y=$2;            # set y to $2

出力

650 1599(入力)
1599 =(650 * 2)+ 299
650 =(299 * 2)+ 52
299 =(52 * 5)+ 39
52 =(39 * 1)+ 13
39 =(13 * 3)+ 0
13

ちょっとした楽しみのために、適切な間隔のバージョンも作成し、233 * 0.9 == 209.7バイトのスコアを与えました。

更新 285バイトからこれを短縮することができました-M。オプションを使用してgawk4を呼び出すと、任意の長い数値で機能するようになりました。

x=$1{x<$2?x+=$2-(y=x):y=$2;a=length(x);b=length(y);for(d=length(x%y);t=y;x=t){$++i=x;$++i=y;if(c<l=length($++i=int(x/y)))c=l;$++i=y=x%y}while(j<NF)printf "%"a"d = %"b-length($(j+2))"s(%d * %"c"d) + %"d"d\n",$++j,_,$++j,$++j,$++j}$0=x

しかし、私はまだどこかに精神的なブロックにぶつかったという感じがしました...

出力(gawk4はで呼び出されますawk -M -f code.awk

6837125332653632513763 18237983363879361(入力)
6837125332653632513763 =(18237983363879361 * 374883)+ 15415252446024000
     18237983363879361 =(15415252446024000 * 1)+ 2822730917855361
     15415252446024000 =(2822730917855361 * 5)+ 1301597856747195
      2822730917855361 =(1301597856747195 * 2)+ 219535204360971
      1301597856747195 =(219535204360971 * 5)+ 203921834942340
       219535204360971 =(203921834942340 * 1)+ 15613369418631
       203921834942340 =(15613369418631 * 13)+ 948032500137
        15613369418631 =(948032500137 * 16)+ 444849416439
          948032500137 =(444849416439 * 2)+ 58333667259
          444849416439 =(58333667259 * 7)+ 36513745626
           58333667259 =(36513745626 * 1)+ 21819921633
           36513745626 =(21819921633 * 1)+ 14693823993
           21819921633 =(14693823993 * 1)+ 7126097640
           14693823993 =(7126097640 * 2)+ 441628713
            7126097640 =(441628713 * 16)+ 60038232
             441628713 =(60038232 * 7)+ 21361089
              60038232 =(21361089 * 2)+ 17316054
              21361089 =(17316054 * 1)+ 4045035
              17316054 =(4045035 * 4)+ 1135914
               4045035 =(1135914 * 3)+ 637293
               1135914 =(637293 * 1)+ 498621
                637293 =(498621 * 1)+ 138672
                498621 =(138672 * 3)+ 82605
                138672 =(82605 * 1)+ 56067
                 82605 =(56067 * 1)+ 26538
                 56067 =(26538 * 2)+ 2991
                 26538 =(2991 * 8)+ 2610
                  2991 =(2610 * 1)+ 381
                  2610 =(381 * 6)+ 324
                   381 =(324 * 1)+ 57
                   324 =(57 * 5)+ 39
                    57 =(39 * 1)+ 18
                    39 =(18 * 2)+ 3
                    18 =(3 * 6)+ 0
3

いくつかの改行とタブが追加されました

x=$1{
    x<$2?x+=$2-(y=x):y=$2;
    a=length(x);
    b=length(y);
    for(d=length(x%y);t=y;x=t)
    {
        $++i=x;
        $++i=y;
        if(c<l=length($++i=int(x/y)))c=l;
        $++i=y=x%y
    }
    while(j<NF)
        printf "%"a"d = %"b-length($(j+2))"s(%d * %"c"d) + %"d"d\n",
                                               $++j,_,$++j,$++j,$++j
}$0=x

x、y、およびx%yの初期値の長さは、各ステップで短くなるため、最初に保存できます。しかし、要因については、長さは変化する可能性があるため、何かを印刷する前に最大長を決定する必要があります。$iここでは、毎回a [i]を使用するのに比べて2文字を節約するため、ここで配列として使用します。


4

C ++、GCCコンパイラ、171バイト(-10%、つまり154バイト)

大丈夫だから私の最初の試み..

#include<iostream>
using namespace std;
int main()
{
    int a,b,c;
    cin>>a>>b;
    if(a<b)
    swap(a,b);
    while(b>0)
    {
        c=a;
        cout<<a<<" = ("<<b<<" * "<<a/b<<") + "<<a%b<<endl;
        a=b;
        b=c%b;
    }
    cout<<a;
}

ゴルフをコーディングするためのヒントをいただければ幸いです。

PS C ++を使用しているときに標準ヘッダーファイルとint mainのバイト数をカウントする必要がありますか?除外すると、50バイト削減されます


注:コードをきれいにするために使用される空白を除外しました。
デバンジャヤチャンドラン

3

T-SQL(2012 +)、268バイト

再帰CTEを実行するインラインテーブル関数として実装されます。10%のボーナスのためにフォーマットを設定しようとする価値があるかもしれませんが、それは待つ必要があります。

CREATE FUNCTION E(@ INT,@B INT)RETURNS TABLE RETURN WITH M AS(SELECT IIF(@<@B,@B,@)A,IIF(@>@B,@B,@)B),R AS(SELECT A,B,A/B D,A%B R FROM M UNION ALL SELECT B,R,B/R,B%R FROM R WHERE 0<>R)SELECT CONCAT(A,'=(',B,'*',D,')+',R)R FROM R UNION ALL SELECT STR(B)FROM R WHERE R=0

説明と使用法:

--Create the function
CREATE FUNCTION E(@ INT,@B INT)RETURNS TABLE RETURN
WITH
    --Order the input correctly
    M AS (
          SELECT IIF(@<@B,@B,@)A,
                 IIF(@>@B,@B,@)B
          )
    --Recursive selection
    ,R AS (
          SELECT A,B,A/B D,A%B R FROM M -- Anchor query
          UNION ALL
          SELECT B,R,B/R,B%R FROM R     -- Recurse until R = 0
          WHERE 0<>R
          )
SELECT CONCAT(A,'=(',B,'*',D,')+',R)R   -- Concat results into output string
FROM R 
UNION ALL                               -- ALL required to maintain order
SELECT STR(B)                           -- Add final number
FROM R WHERE R=0

--Function Usage
SELECT * FROM E(447,501)

R
-----------------------------------------------------
501=(447*1)+54
447=(54*8)+15
54=(15*3)+9
15=(9*1)+6
9=(6*1)+3
6=(3*2)+0
3

2

Rev 1:ルビー、86

Doorknobからのヒントのおかげで、再帰アルゴリズム。

f=->i,j{j>i&&(i,j=j,i)
0<j ?(print i," = (#{j} * #{i/j}) + #{i%j}
";f[j,i%j]):puts(i)}

Rev 0:ルビー、93

これは本当にうまくいきませんでした。whileループは特にして、あまりにも多くの文字を取りend。それを回避する方法がわかりません。再帰では、ラムダではなく名前付き関数が必要になります。これは、多くの文字を使い果たしてしまいます。

->i,j{j>i&&(i,j=j,i)
while j>0
print(i," = (#{j} * #{i/j}) + #{i%j}\n")
i,j=j,i%j
end
puts i}

次のように呼び出します。

f=->i,j{j>i&&(i,j=j,i)
while j>0
print(i," = (#{j} * #{i/j}) + #{i%j}\n")
i,j=j,i%j
end
puts i}

I=gets.to_i
J=gets.to_i

f.call(I,J)

あなたは経由で再帰を使用することができますa=->i,j{...}し、呼び出しaを経由してa[1,2]、これはかかわらず、あなたの文字を保存するかどう-not確認してください。
ドアノブ

@Doorknobはヒントをありがとう、ラムダ関数を呼び出すための構文を知りませんでした(f.call。の使用を参照してください)。
レベルリバーセント

2

PowerShell、84

変数に格納される再帰的なコードブロック。で呼び出します& $e num1 num2。例:

$e={$s,$b=$args|Sort;if(!$s){$b}else{$r=$b%$s;"$b=($s*$(($b-$r)/$s))+$r";&$e $s $r}}

PS D:\> & $e 9894 2628
9894=(2628*3)+2010
2628=(2010*1)+618
2010=(618*3)+156
618=(156*3)+150
156=(150*1)+6
150=(6*25)+0
6

より読みやすい形式で、次のことを行います(コードを明確にするために、完全なコマンドレット名、文字列にスペースを追加し、パイプライン出力コマンドを明示的にしました)。

function Euclid {
    $small, $big = $args|Sort-Object   #Sort argument list, assign to two vars.

    if (!$small) {                     #Recursion end, emit the last
        Write-Output $big              #number alone, for the last line.

    } else {                           #main recursive code

        $remainder = $big % $small
        Write-Output "$big = ( $small* $(($big-$remainder)/$small)) + $remainder"
        Euclid $small $remainder
    }
}

codegolfの観点からの1つの迷惑。PoShには整数除算がなく、10/3はDoubleを返しますが、結果を整数にキャストし、常に切り捨てるわけではなく、N.5を最も近い偶数に切り上げまたは切り捨てます。だから[int](99/2) == 50

それは2つの厄介な選択肢を残します:

$remainder = $x % $y
$quotient = [Math]::Floor($x/$y)

# or, worse

$remainder=$null
$quotient = [Math]::DivRem($x, $y, [ref]$remainder)

それが私がいくつかのキャラクターを燃やさなければならない理由です:

$remainder = $big % $small
($big - $remainder)/$small

それとは別に、それはの数です

そして、本当に痛い三項演算子の欠如。

また、84文字のかなり良い反復バージョンもあります。

{$r=1;while($r){$s,$b=$args|Sort;$r=$b%$s;"$b=($s*$(($b-$r)/$s))+$r";$args=$s,$r}$s}

完全に匿名のコードブロックなので、次のコマンドで実行します

& {*codeblock*} 1599 650

2

PHP、118バイト

for(list(,$n,$m)=$argv,$g=max($n,$m),$l=min($n,$m);$g;$g=$l,$l=$m)
echo$g,$l?"=($l*".($g/$l^0).")+".($m=$g%$l)."
":"";

オンラインでお試しください!

PHP、131バイト

for(list(,$n,$m)=$argv,$r=[max($n,$m),min($n,$m)];$r[+$i];)echo$g=$r[+$i],($l=$r[++$i])?"=($l*".($g/$l^0).")+".($r[]=$g%$l)."
":"";

オンラインでお試しください!

-4バイトはPHP> = 7.1のニーズに置き換えlist(,$n,$m)=$argvられ[,$n,$m]=$argvます



2

JavaScript(ES6)、74 50 62 61 55バイト

f=(x,y)=>y?y>x?y:x+`=(${y}*${x/y|0})+${x%=y}
`+f(y,x):x
  • 整数を最大の順序ではなく、任意の順序で渡すことができる12バイトを犠牲にしました。

それを試してみてください

f=(x,y)=>y?y>x?y:x+`=(${y}*${x/y|0})+${x%=y}
`+f(y,x):x
o.innerText=f(i.value=683712533265363251376,j.value=18237983363879361)
i.oninput=j.oninput=_=>o.innerText=f(+i.value,+j.value)
<input id=i type=number><input id=j type=number><pre id=o>


説明

f=          :Assign the function to variable f ...
(x,y)=>     :And take the two integer inputs as arguments via parameters x and y.
y?          :If y is greater than 0 then
y>x?        :    If y is greater than x then
f(y,x)      :        Call f again, with the order of the integers reversed.
            :        (This can only happen the first time the function is called.)
:           :    Else
x           :        Start building the string, beginning with the value of x.
+`=(        :        Append "=(".
${y}        :          The value of y.
*           :          "*"
${x/y|0}    :          The floored value of x divided by y
)+          :          ")+"
${x%=y}     :          The remainder of x divided by y, which is assigned to x
            :          (x%=y is the same as x=x%y.)
\n          :          A newline (a literal newline is used in the solution).
`+f(y,x)    :        Append the value f returns when y and the new value of x
            :        are passed as arguments.
:           :Else
x           :    Return the current value of x,
            :    which will be the greatest common divisor of the original two integers.

1

JS、151

a=prompt("g","");b=prompt("l","");c=0;l=[a,b];for(var i=0;i<=1;i++){t=c;o=c+1;r=c+2;n=l[t]%l[o];if(n!==0){l[r]=n;c=c+1;i=0;}else{p=l[o];alert(p);i=2;}}

1

C、83バイト

g(x,y,z){y&&(printf("%u=(%u*%u)+%u\n",x,y,x/y,z=x%y),z)?g(y,z,0):printf("%u\n",y);}

テストと結果

int main()
{g(18,27,0);
 g(50,20,0);
 g(447,501,0);
 g(9894,2628,0);
}

18=(27*0)+18
27=(18*1)+9
18=(9*2)+0
9
50=(20*2)+10
20=(10*2)+0
10
447=(501*0)+447
501=(447*1)+54
447=(54*8)+15
54=(15*3)+9
15=(9*1)+6
9=(6*1)+3
6=(3*2)+0
3
9894=(2628*3)+2010
2628=(2010*1)+618
2010=(618*3)+156
618=(156*3)+150
156=(150*1)+6
150=(6*25)+0
6

0

Java 133

public void z(int i,int j){for(int d=1;d!=0;i=j,j=d){d=i%j;System.out.println(i+"=("+j+"*"+((i-d)/j)+")+"+d);}System.out.println(i);}

通常のユークリッドアルゴリズムは実行しません。代わりに、モジュラスを使用し、2番目の数値を計算して、印刷時に乗算します。また、ラムダ式に変換することでこれを短くすることもできますが、どのようにすればよいかわかりません。

public void z(int i, int j)
{
    for(int d=1;d!=0;i=j,j=d)
    {
        d=i%j;
        System.out.println(i+"=("+j+"*"+((i-d)/j)+")+"+d);
    }
    System.out.println(i);
}

1.5年以上経っていますが、を削除しpublic 、2番目printlnprintに変更d!=0し、に変更できd>0ます。また、現在、最初の行の出力が正しくありません。これはif(d!=i)、の前に追加することで修正できますSystem.out.println(i+"=("+j+"*"+((i-d)/j)+")+"+d);。合計で:void z(int i,int j){for(int d=1;d>0;i=j,j=d){d=i%j;if(d!=i)System.out.println(i+"=("+j+"*"+((i-d)/j)+")+"+d);}System.out.print(i);}131バイト&バグ修正)
ケビンクルーイッセン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.