L'algorithme euclidien (pour trouver le plus grand diviseur commun)

22

Le défi

Ecrire un programme ou une fonction qui prend deux entiers d'entrée, iet j, et produit leur plus grand commun diviseur; calculé en utilisant l' algorithme euclidien (voir ci-dessous).


Contribution

L'entrée peut être considérée comme une représentation sous forme de chaîne délimitée par des espaces iet jou comme deux entiers distincts. Vous pouvez supposer que les nombres entiers seront inférieurs ou égaux à 10 000. Vous pouvez également supposer que les entiers en entrée ne seront pas premiers entre eux.


Répartition euclidienne

Le plus grand nombre entre iet jest divisé par le plus petit nombre de fois possible. Ensuite, le reste est ajouté. Ce processus est répété avec le reste et le numéro précédent, jusqu'à ce que le reste devienne 0.

Par exemple, si l'entrée était 1599 650:

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

Le nombre final,, 13est le plus grand commun diviseur des deux entiers d'entrée. Il peut être visualisé comme ceci:


Sortie

Votre sortie doit être la ventilation dans le formulaire ci-dessus, suivie d'une nouvelle ligne et du GCD. Il peut être sorti sur n'importe quel support.


Exemples

Contributions

18 27
50 20
447 501
9894 2628

Les sorties

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

Remarque: Les sorties ne doivent pas être espacées comme elles le sont ci-dessus. L'espacement est uniquement à des fins de clarté. Des parenthèses sont requises.


Prime

Si votre sortie est espacée comme ci-dessus, vous pouvez ajouter un bonus de -10% à votre score.

Portes Zach
la source
1. Peut-on supposer que le plus grand nombre est donné en premier? 2. Pour le bonus, vous voulez dire que la largeur du champ doit être constante et juste assez pour permettre un espace avant le plus grand nombre? (avec les espaces devant la parenthèse gauche dans la deuxième colonne de nombres.) Vous devez éviter les expressions ambiguës telles que "telles qu'elles sont au-dessus" lorsque la sortie est variable. C'est OK si la sortie requise est fixe.
Level River St, du
Ok, je vois que certains exemples ont le plus grand nombre de secondes
Level River St
Votre titre d'origine était OK, j'ai commenté ce qui s'est passé sur meta.codegolf.stackexchange.com/q/7043/15599 . Toutefois, l'expression "le plus grand dénominateur commun" était erronée. Le "dénominateur" concerne les fractions. La recherche sur le "plus grand dénominateur commun" donne uniquement des résultats pour "le plus grand diviseur / facteur commun".
Level River St, du
Je pensais que le titre était OK, mais je l'ai changé en "The" pour ne déplaire à personne. Merci d'avoir édité dans "diviseur", BTW. @steveverrill
Zach Gates

Réponses:

4

Pyth, 33 octets

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

Essayez-le en ligne: démonstration ou suite de tests

Explication:

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
Jakube
la source
7

CJam, 46 43 39 octets

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

Essayez-le en ligne dans l' interpréteur CJam .

Comment ça marche

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.
Dennis
la source
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`

Une fonction récursive qui renvoie une chaîne multiligne. La fonction crée la première ligne, puis l'ajoute au résultat récursif avec la paire de nombres suivante dans l'algorithme euclidien. Une fois que le deuxième nombre est zéro, nous prenons la chaîne de l'autre nombre comme cas de base, ce qui entraîne son impression sur sa propre ligne à la fin.

Le formatage est effectué via la substitution de chaîne, en utilisant la division entière pour obtenir le multiplicande.

Un hoquet doit commencer par prendre le plus grand nombre et le plus petit. Commodément, si les nombres sont dans le mauvais ordre, la première étape de l'algorithme euclidien les retourne. Pour empêcher cette étape de s'afficher, n'ajoutez la ligne actuelle que si le premier nombre est au moins le second (l'égalité est nécessaire pour, disons f(9,9)).

xnor
la source
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

Le tri de l'entrée par taille prend beaucoup d'octets: /
Cela se résume à ceci:

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

Sortie

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

Juste pour le plaisir, j'ai également fait une version correctement espacée, me donnant un score de 233 * 0,9 == 209,7 octets.

Mise à jour J'ai pu raccourcir cela de 285 octets et maintenant cela fonctionne pour des nombres arbitrairement longs si j'appelle gawk4 avec l' -Moption.

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

Mais j'ai toujours le sentiment d'avoir rencontré un blocage mental quelque part ...

Sortie (gawk4 appelé avec awk -M -f code.awk)

6837125332653632513763 18237983363879361 (entrée)
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

Ajout de nouvelles lignes et d'onglets

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

Je peux enregistrer les longueurs des valeurs initiales pour x, y et x% y au début, car elles ne peuvent que raccourcir à chaque étape. Mais pour le facteur, je dois déterminer la longueur maximale avant d'imprimer quoi que ce soit, car sa longueur peut varier. J'utilise $iici un tableau, car il enregistre deux caractères par rapport à l'utilisation d'un [i] à chaque fois.

Cabbie407
la source
4

C ++, compilateur GCC, 171 octets (-10%, donc 154 octets)

ok donc mon premier essai ..

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

conseils pour coder le golf appréciés.

PS Est-il nécessaire de compter les octets des fichiers d'en-tête standard et int main lors de l'utilisation de c ++? L'exclusion réduit de 50 octets

Devang Jayachandran
la source
Remarque: j'ai exclu l'espace blanc utilisé pour rendre le code joli.
Devang Jayachandran
3

T-SQL (2012+), 268 octets

Implémenté comme une fonction de table en ligne qui exécute un CTE récursif. Cela pourrait valoir la peine d'essayer de mettre en forme le bonus de 10%, mais cela devra attendre.

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

Explication et utilisation:

--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
MickyT
la source
2

Rév 1: Ruby, 86

Algorithme récursif, grâce au conseil de 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)}

Rév 0: Ruby, 93

Cela n'a vraiment pas bien fonctionné du tout. La whileboucle prend trop de caractères, en particulier avec le end. Je ne vois pas comment l'éviter. La récursivité nécessiterait une fonction nommée au lieu d'un lambda, qui consommerait également beaucoup de caractères.

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

Appelez ça comme ceci:

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)
Level River St
la source
Vous pouvez utiliser la récursivité via a=->i,j{...}et appeler avia a[1,2]- mais vous ne savez pas si cela vous sauverait des caractères.
Poignée de porte
@ Doorknob merci pour l'astuce, je n'étais pas au courant de cette syntaxe pour appeler les fonctions lambda (voir mon utilisation de f.call.) Elle est en fait un peu plus courte, mais toujours loin de Python.
Level River St, du
2

PowerShell, 84

Un bloc de code récursif, stocké dans une variable. Invoquez-le avec & $e num1 num2, par exemple:

$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

Dans une forme plus lisible, il fait ce qui suit (nb. Pour un code plus clair, j'ai mis les noms de commandlet complets, plus d'espaces dans la chaîne et rendu les commandes de sortie du pipeline explicites):

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

Un ennui du point de vue du codegolf; PoSh n'a pas de division entière, 10/3 renvoie un Double, mais transforme le résultat en entier et il n'est pas toujours arrondi, il arrondit N.5 au nombre pair le plus proche - vers le haut ou vers le bas. Alors [int](99/2) == 50.

Cela laisse deux choix maladroits:

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

# or, worse

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

C'est pourquoi je dois graver certains personnages en faisant:

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

A part ça, c'est le nombre de

et le manque d'opérateur ternaire qui fait vraiment mal.

J'ai également une version itérative qui, plutôt joliment, compte également 84 caractères:

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

Codeblock complètement anonyme, alors exécutez-le avec

& {*codeblock*} 1599 650
TessellatingHeckler
la source
2

PHP, 118 octets

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)."
":"";

Essayez-le en ligne!

PHP, 131 octets

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)."
":"";

Essayez-le en ligne!

-4 octets remplacer list(,$n,$m)=$argvpar les [,$n,$m]=$argvbesoins PHP> = 7.1

Jörg Hülsermann
la source
2

Japt , 43 42 41 octets

Mes nouvelles "compétences" Japt semblent empirer, pas s'améliorer!

?U>V?ßVU :[V'='(U'*V/U|0')'+V%=UR,ßVU]¬:V

Essayez-le en ligne

Hirsute
la source
2

JavaScript (ES6), 74 50 62 61 55 octets

f=(x,y)=>y?y>x?y:x+`=(${y}*${x/y|0})+${x%=y}
`+f(y,x):x
  • Sacrifié 12 octets permettant aux nombres entiers d'être passés dans n'importe quel ordre, plutôt que le plus grand en premier.

Essayez-le

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>


Explication

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.
Hirsute
la source
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;}}
Nautile
la source
1

C, 83 octets

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

test et résultats

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
RosLuP
la source
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);}

Il ne fait pas l'algorithme euclidien normal. Au lieu de cela, il utilise le module, puis calcule le 2e nombre à multiplier par lorsqu'il est imprimé. Vous pouvez également le raccourcir en le transformant en une expression lambda, mais je ne sais pas comment.

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);
}
Lumineux
la source
Je sais que cela fait plus d'un an et demi, mais vous pouvez supprimer le public , changer le second printlnen printet changer d!=0en d>0. En outre, il donne actuellement une sortie incorrecte pour les premières lignes. Cela peut être corrigé en ajoutant if(d!=i)devant System.out.println(i+"=("+j+"*"+((i-d)/j)+")+"+d);. Donc au total: 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 octets et correction de bugs)
Kevin Cruijssen