Convertir une décimale répétée en une fraction


23

Cette question n'a pas besoin de s'appliquer uniquement aux décimales terminales - les décimales répétitives peuvent également être converties en fractions via un algorithme.

Votre tâche consiste à créer un programme qui prend une décimale répétée en entrée et à sortir le numérateur et le dénominateur correspondants (en termes les plus bas) qui produisent cette expansion décimale. Les fractions supérieures à 1 doivent être représentées comme des fractions impropres comme 9/5. Vous pouvez supposer que l'entrée sera positive.

La décimale répétée sera donnée dans ce format:

5.3.87

avec tout après le deuxième point répété, comme ceci:

5.3878787878787...

Votre programme affichera deux entiers représentant le numérateur et le dénominateur, séparés par une barre oblique (ou la forme équivalente dans votre langue si vous ne produisez pas de texte brut):

889/165

Notez que les décimales terminales n'auront rien après le deuxième point, et les décimales sans partie décimale non répétitive n'auront rien entre les deux points.

Cas de test

Ces cas de test couvrent tous les cas de coin requis:

0..3 = 1/3
0.0.3 = 1/30
0.00.3 = 1/300
0.6875. = 11/16
1.8. = 9/5
2.. = 2/1
5..09 = 56/11
0.1.6 = 1/6
2..142857 = 15/7
0.01041.6 = 1/96
0.2.283950617 = 37/162
0.000000.1 = 1/9000000
0..9 = 1/1
0.0.9 = 1/10
0.24.9 = 1/4

Si vous le souhaitez, vous pouvez également supposer que les fractions sans parties entières n'ont rien à gauche du premier point. Vous pouvez tester cela avec ces cas de test facultatifs:

.25. = 1/4
.1.6 = 1/6
..09 = 1/11
.. = 0/1

1
Faut-il simplifier la fraction? Ou est-il raisonnable de le laisser sous une forme non simplifiée (par exemple:) 9/99?
Justin

3
(in lowest terms)c'est-à-dire que la fraction doit être simplifiée.
Joe Z.

2
Suis-je autorisé à sortir 13au lieu de 13/1?
mniip

4
Assurez-vous de gérer ces entrées 1.9999...et sorties2/1
Thomas Eding

3
@ThomasEding 1.9999.est 19999/10000, pour obtenir 2/1ce dont vous avez besoin 1..9, n'est-ce pas?
Qwertiy

Réponses:


8

Dyalog APL ( 75 73 69 68 caractères)

Voici une autre et cinquième tentative (probablement ma dernière); J'ai passé la journée à essayer d'écrire un morceau de code de moins de 80 caractères et à être pleinement conforme aux règles. Ce défi a fait ma journée!

J'ai finalement obtenu une ligne d'APL composée de 75 caractères, fonctionnant avec Dyalog APL (mais pas sur la page d'interpréteur en ligne car utilisant la fonction d' exécution ), qui est la suivante:

(N,D)÷D∨N←(⍎'0',1↓I/⍨2=+\P)+(⍎'0',I/⍨2>+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I← '1.2.3'

Bien sûr, je pourrais le raccourcir un peu, mais les cas particuliers où un, deux ou trois champs manquent. Mon code peut même gérer le ..cas d'entrée.

Je sais qu'APL est difficile à lire, et comme les gens aiment comprendre comment fonctionne réellement un morceau de code, voici quelques explications. Fondamentalement, je calcule le dénominateur final dans la variable D et le numérateur final dans la variable N.

APL est analysé de droite à gauche.

  • Tout d'abord, la chaîne est stockée dans la variable I ( I←).
  • Il est ensuite mappé sur un vecteur de booléens indiquant où se trouve un point, et ce vecteur est appelé P ( P←'.'=). Par exemple, «1.2.3» sera mappé sur 0 1 0 1 0.
  • Ce vecteur est composé de chiffres en base 10 ( 10⊥); maintenant '1.2.3' est 1010.
  • Ensuite, 1 est soustrait de ce nombre (avec 1-⍨ou avec ¯1+, ici j'ai choisi le second). Maintenant, «1.2.3» est 1009.
  • Ensuite, ce nombre est converti en une chaîne ( ), deux chiffres initiaux sont supprimés ( 2↓), ce qui fait 09 de notre exemple initial '1.2.3'; la chaîne est inversée ( ).
  • Ici, comme cas spécial, j'ajoute un caractère initial 0 devant la chaîne; cela me rend triste d'utiliser les quatre caractères '0',mais je l'ai fait pour éviter une erreur lorsque les deuxième et troisième champs sont tous les deux vides. La chaîne est reconvertie en un nombre ( ) et elle est stockée dans D, qui est le dénominateur, sauf lorsque les deux derniers champs sont vides, car dans ce cas, D est égal à 0.
  • Le D←D+0=morceau de code définit D à 1 s'il est actuellement nul, et maintenant D contient le dénominateur (avant la division GCD cependant).
  • Ce dénominateur est multiplié ( ×) par le contenu de la chaîne initiale I jusqu'au deuxième point avec (⍎'0',I/⍨2>+\P)lequel recommence depuis P (0 1 0 1 0 dans mon exemple), ajoute les nombres successifs en les cumulant (ce qui fait 0 1 1 2 2 dans mon exemple), vérifiez quelles valeurs sont inférieures à 2 (en faisant le vecteur booléen 1 1 1 0 0), et en prenant les caractères correspondants dans I; un autre 0 est ajouté devant la chaîne pour empêcher un autre piège (si les deux champs initiaux sont vides) et le tout est converti en un nombre.
  • La dernière partie de la chaîne d'entrée est ajoutée au produit précédent avec (⍎'0',1↓I/⍨2=+\P), qui reprend P, ajoute en cumulant à nouveau, vérifie quelles valeurs sont égales à 2 (voir explication précédente), prend les caractères, supprime la première qui est un point , ajoute un caractère 0 initial empêchant et convertit en un nombre.
  • Ce produit suivi d'une somme est stocké dans N qui est le numérateur.
  • Enfin, le GCD est calculé avec D∨N et les deux nombres sont divisés par ce GCD.

edit: Voici un correctif pour 73 caractères:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I←

L'idée de ce hack est de calculer d'abord le cas où l'addition cumulative a des valeurs égales à 2, de les stocker pour plus tard et d'inverser ce masque au niveau du bit pour obtenir le premier cas; le calcul du cas suivant nécessite donc moins de caractères.

edit: Voici un autre correctif pour 69 caractères:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽2↓⍕¯1+10⊥P←'.'=I←

L'idée de ce hack est d'incorporer le cas spécial le plus compliqué en tant que code APL dans la chaîne à évaluer (au stade de la conversion chaîne en nombre).

edit: Voici un autre correctif pour 68 caractères:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽3↓⍕1-10⊥P←'.'=I←

L'idée de ce hack est de remplacer l' ajout de -1 à la valeur de soustraction de 1 à cette valeur par l'opération de soustraction de cette valeur à 1 puis de supprimer plus tard un caractère de plus au début (qui sera le signe moins).

modifier: changement cosmétique:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←1⌈⍎'0',⌽3↓⍕1-10⊥P←'.'=I←

Aucune amélioration de taille, mais plus satisfaits d'obtenir la fonction maximale du code à évaluer.


J'ai essayé d'exécuter ceci avec tryapl.org et il se plaint INVALID TOKEN. Est-ce que tu sais pourquoi?
Peter Taylor

@Peter Taylor: Oui, c'est même dit dans mon message; c'est parce que j'utilise l'opérateur "execute" qui serait dangereux pour le serveur de Dyalog et a été désactivé en ligne (mode sans échec). Vous devez l'essayer sur une version installée de Dyalog APL.
Thomas Baruchel

Ah la honte. Je ne vais pas dépenser 60 € pour pouvoir tester une soumission PCG occasionnelle. J'ai trouvé un autre testeur APL en ligne, mais il semble y avoir quelque chose de spécifique à Dyalog dans votre code car il donne des erreurs de classement ou des erreurs de longueur.
Peter Taylor

@Peter Taylor; non ;-) S'il vous plaît, utilisez mon propre site Web (encore expérimental et non officiel) avec GNU APL; mais j'ai dû ajouter deux caractères pour le rendre compatible (parenthèses autour d'un I): voir ce permalien
Thomas Baruchel

15

Perl 6 (93 101 100 80 68 66 octets)

$/=split ".",get;say ($0+($1+$2/(9 x$2.comb||1))/10**$1.comb).nude

La taille a été augmentée pour ne rien gérer, au lieu de simplement échouer. Mouq a proposé d'utiliser $/, donc il est maintenant utilisé, et le code est 20 octets plus court. Ayiko a proposé de le remplacer /par , le code est donc encore plus court (de 12 octets). Puis Mouq a proposé de les remplacer charspar comb(dans un contexte numérique, ils sont identiques, car la liste des caractères après la conversion en nombre est le nombre de caractères).

Exemple de sortie:

$ perl6 script.p6
5.3.87
889 165
$ perl6 script.p6
2.0.0
2 1
$ perl6 script.p6
0..3
1 3
$ perl6 script.p6
0.0.3
1 30
$ perl6 script.p6
0.0.0
0 1
$ perl6 script.p6
0.1.6
1 6
$ perl6 script.p6
0.01041.6
1 96
$ perl6 script.p6
0.2.283950617
37 162
$ perl6 script.p6
123.456.789
41111111 333000

Malheureusement, il s'avère que l'utilisation de zéro comme espace réservé entre deux points est un no-go. 0..09retourne 1/11, mais 0.0.09revient 1/110.
Joe Z.

@JoeZ. Ah d'accord. J'ai mis à jour mon code pour gérer le cas où rien n'est tapé.
Konrad Borowski

Je ne connais pas Perl 6, mais ai-je raison de supposer que, étant donné 'abc', votre programme utilise l'arithmétique rationnelle exacte pour calculer c / 99 ... 9, mais utilise uniquement la virgule flottante pour calculer ab? Dans ce cas, si b a plusieurs chiffres, il donnera une réponse incorrecte.
Omar

@ OmarAntolín-Camarena: Pas tout à fait. En Perl 6, les rationnels sont des nombres par défaut, pas des nombres à virgule flottante. Par exemple, 0.1 + 0.2 == 0.3en Perl 6.
Konrad Borowski

2
Joué à 80 caractères: $/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude:)
Mouq

6

J ( 85 90 89 caractères)

Ma fonction d'origine, qui était 5 caractères plus courte que la seconde, avait quelques bugs: elle ne produisait pas d'entiers comme "n / 1" et elle donnait la mauvaise réponse sur les nombres avec plus d'une douzaine de chiffres. Voici une fonction corrigée dans J qui intègre également la suggestion d'Eelvex pour enregistrer un personnage:

f=:3 :0
'a t'=.|:(".@('0','x',~]),10x^#);._1'.',y
(,'/'&,)&":/(,%+.)&1+/a%*/\1,0 1-~}.t
)

Il reçoit une chaîne et renvoie une chaîne. Voici un exemple de session:

   f '..'
0/1
   f '0.0.0'
0/1
   f '3..'
3/1
   f '..052631578947368421'
1/19
   f '0.2.283950617'
37/162
   f '.0.103092783505154639175257731958762886597938144329896907216494845360824742268041237113402061855670'
1/97

Vous devez corriger votre fonction pour produire 0/1et 3/1inf deux premiers cas de test, Voir ce commentaire
mniip

J'ai fixé la sortie pour les entiers au prix de 5 caractères, @mniip.
Omar

Utilisez ('0','x',~])et enregistrez un octet.
Eelvex

5

C, 171

Assez longtemps. Pourrait être encore réduit. Non scanf, ce qui ne peut vraiment pas le gérer s'il n'y a pas de nombres entre les points. Non strtol. Juste le calcul des nombres:

a,b,c,d,q;main(){while((q=getchar()-48)>-3)q<0?(d=b>0,b+=!b):d?(c=c*10+q,d*=10):(a=a*10+q,b*=10);for(a=a*--d+c,q=b*=d;q>1;a%q+b%q?--q:(a/=q,b/=q));printf("%d/%d\n",a,b);}

Tester:

rfc <<< "2..142857"
15/7

5

DC (pas entièrement général, raccourci à 76 caractères)

Pas entièrement général, mais s'il vous plaît, considérez que je l'ai fait avec l'une des choses les plus anciennes du monde:

5.3.87 dsaX10r^d1-rla*sasbdscX10r^dlc*rlb*rlb*la+snsdlnld[dSarLa%d0<a]dsax+dldr/rlnr/f

Modifier: je modifie ma solution; ce n'est pas plus général, mais un peu plus court:

sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f

Utilisez-le comme:

5.3.87 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
  • Le premier champ n'est pas obligatoire:

    .1.3 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
    

    est OK.

  • Le deuxième et le premier champ nécessitent au moins un chiffre


5

Javascript, 203

Beaucoup trop long, mais toujours amusant. Retour à la ligne car les points-virgules sont illisibles.

s=prompt(b=1).split(".")
P=Math.pow
a=s[0]
c=s[1]
d=P(10,l=c.length)
f=(P(10,s[2].length)-1)*P(10,l)||1
e=s[2]=+s[2]
a=d*a+b*c;b*=d
a=f*a+b*e;b*=f
function g(a,b){return b?g(b,a%b):a}g=g(a,b);a/g+"/"+b/g

Je reçois 889/NaNquand je cours 5.3.87... Est-ce que je fais quelque chose de mal?
rafaelcastrocouto

Je ne sais pas ... Si je colle simplement ce code dans la console Safari (Firefox ou Chrome devrait le faire aussi), appuyez sur Entrée et tapez "5.3.87", je viens de rentrer "889/165"dans la console. Comment le gérez-vous? @rafaelcastrocouto
tomsmeding

peu importe ... Je suppose que j'ai fait quelque chose de mal car cela fonctionne maintenant ...
rafaelcastrocouto

1
Vous pouvez enregistrer 1 caractère en déplaçant la b=1pièce à l'intérieur prompt().
user2428118

1
f=(P(10,s[2].length)-1)*P(10,l),f=f?f:1=>f=(P(10,s[2].length)-1)*P(10,l)||1
f.ardelian

3

J (méthode différente)

Une autre solution basée sur une méthode très différente; cette fois, c'est tout à fait général; ne manque que le 1-dénominateur lorsqu'un entier est soumis:

   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '.1.3'
2r15
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '.1.'
1r10
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '1..'
1
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '1..3'
4r3

3

GolfScript (67 caractères)

`{'.'/1$=.10\,?@-).!+0@+~}+3,/1$4$*]-1%~;*+*+].~{.@\%.}do;{/}+/'/'@

NB Cela prend en charge les parties entières vides.

Si la chaîne est de la forme, 'n.p.q'la valeur est n + p/E + q/(DE) = ((nD + p)E + q)/DED = 10^(len p)et E = 10^(len q) - 1, sauf quand len q = 0, dans ce cas E = 1(pour éviter la division par 0).

Dissection:

           # Stack: 'n.p.q'
`{         # Combined with the }+ below this pulls the value into the block
           # Stack: idx 'n.p.q'
    '.'/   # Stack: idx ['n' 'p' 'q']
    1$=    # Stack: idx str   (where str is the indexed element of ['n' 'p' 'q'])
    .10\,? # Stack: idx str 10^(len str)
    @-)    # Stack: str 10^(len str)-idx+1
           #   If idx = 0 we don't care about the top value on the stack
           #   If idx = 1 we compute D = 10^(len 'p')
           #   If idx = 2 we compute E' = 10^(len 'q') - 1
    .!+    # Handle the special case E'=0; note that D is never 0
    0@+~   # Stack: 10^(len str)-idx+1 eval('0'+str) (GolfScript doesn't treat 011 as octal)
}+         # See above
3,/        # Run the block for idx = 0, 1, 2
           # Stack: _ n D p E q
1$4$*      # Stack: _ n D p E q D*E
]-1%~;     # Stack: D*E q E p D n
*+*+       # Stack: D*E q+E*(p+D*n)
].~        # Stack: [denom' num'] denom' num'
{.@\%.}do; # Stack: [denom' num'] gcd
{/}+/      # Stack: denom num
'/'@       # Stack: num '/' denom

Démo en ligne qui simule l'exécution du programme avec chacune des entrées de test, une à la fois.


Je l'ai essayé, et il ne semble pas suivre toutes les règles: "Notez que les décimales terminales n'auront rien après le deuxième point, et les décimales sans partie décimale non répétée n'auront rien entre les deux points." Je ne pouvais pas faire fonctionner votre code avec l'entrée étant0.1.
Thomas Baruchel

-1. Je l'ai réessayé une autre fois après avoir remarqué que vous aviez obtenu les +300 points. Ce n'est pas juste, car d'autres solutions ont fait de leur mieux pour suivre toutes les règles, ce que vous n'avez évidemment pas fait.
Thomas Baruchel

@ ברוכאל, je m'oppose à votre affirmation selon laquelle je n'ai pas essayé de suivre les règles. La position des cas de test facultatifs m'a confondu en pensant que le bloc final couvrait tous les cas requis; il s'avère que je me trompais, et je vais modifier la question sous peu pour éviter que d'autres personnes ne commettent la même erreur. J'ai maintenant mis à jour mon code pour gérer les cas d'angle précédemment non gérés et mis à jour mon lien vers un test pour le démontrer.
Peter Taylor

c'est bon. Vous méritez probablement les 300 points. Étant nouveau sur CodeGolf, ces 300 points étaient un objectif difficile pour moi, et je suis toujours déçu de ne pas les avoir alors que je pense toujours qu'à la date limite, mon code était le plus court pour s'adapter parfaitement aux règles. Quoi qu'il en soit, j'ai toute ma vie pour gagner des points. Cordialement.
Thomas Baruchel

@ ברוכאל: Je voulais commencer 500 points (oui, je suis généreux comme ça, ce n'est pas que je puisse en donner moins) et vous donner ces points, mais je suppose qu'il y a déjà une prime commencée. Bien, peu importe. Je me demande quand cette prime prendra fin et qui obtiendra ces points.
Konrad Borowski

2

Python

Aucune bibliothèque - 156 caractères

_=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),
(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)

Utilisation fractions- 127 caractères

from fractions import*;a,b,c=raw_input().split('.');print Fraction(int(a+b+c)-bool(c)*int(a+b
),(10**len(c)-bool(c))*10**len(b))

La fractionsversion imprime des choses comme "Fraction (7, 5)" au lieu de "7/5", n'est-ce pas?
Omar

Ce n'est pas le cas; Soit dit en passant, je ne fais pas fonctionner le meilleur. _=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b), ValueError: need more than 1 value to unpack
tomsmeding

@ OmarAntolín-Camarena AFAIK, printutilise strlorsqu'il est disponible, non repr. Voici la sortie de ma part: puu.sh/7w64w.png
Oberon

@tomsmeding Les deux sont sur une même ligne; le saut de ligne a été ajouté pour les adapter à la réponse. _=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)devrait aller tout en une seule ligne.
Oberon

Ah oui, @Oberon, comme vous pouvez probablement le deviner, je n'étais pas devant mon ordinateur et je n'ai pas pu exécuter le code.
Omar

2

Mathematica, 143

Comme d'habitude, Mathematica offre de nombreuses fonctions de haut niveau pour faire le travail, mais leur donne des noms verbeux.

x=StringTake;c=ToExpression;p=s~StringPosition~".";{o,t}=First/@p;u=StringLength@s-t;d=t-o-1;Rationalize@(c@x[s,t-1]+c@x[s,-u]/((10^u)-1)/10^d)

Exemple de sortie à ajouter plus tard quand j'aurai le temps.


Il me semble que cela génère des entiers sous la forme n, plutôt que n / 1. Est-ce correct? (Ma solution a le même bug ... :()
Omar

Ah, maintenant je vois .... spécifié dans les commentaires. Quelle étrange exigence ... si toutes les autres fractions sont réduites, pourquoi ne pas permettre n/1de réduire à n? J'ajouterai les ~ 50 octets supplémentaires pour convertir les entiers plus tard.
Jonathan Van Matre

Votre approche est bonne. Le mien s'en sert FromDigitsdonc j'ai décidé de le poster aussi.
DavidC

2

Rubis - 112

x,y,z=gets.chop.split".";y||='0';z||='0';puts((y.to_i+Rational(z.to_i,10**z.length-1))/10**y.length+x.to_i).to_s

C'est ma première expérience avec le rubis, alors n'hésitez pas à suggérer des améliorations.

$ ruby20 % <<< '5.3.87'
889/165
$ ruby20 % <<< '0..3'
1/3
$ ruby20 % <<< '0.0.3'
1/30
$ ruby20 % <<< '0.00.3'
1/300
$ ruby20 % <<< '0.6875.0'
11/16
$ ruby20 % <<< '1.8.0'
9/5
$ ruby20 % <<< '2..'
2/1
$ ruby20 % <<< '..'
0/1

Supprimer le support ".." et ".1.2" signifie que vous ne suivez pas les spécifications, non? (Je préférerais les supprimer aussi.)
Omar

@ OmarAntolín-Camarena Sur ce point particulier, la spécification dit If you wish. Je ne souhaite pas, donc je ne supporte pas les fractions sans le 1er ou le 3e groupe de chiffres. Je soutiens cependant les fractions manquant du 2ème groupe de chiffres, ce qui correspond à la spécification.
mniip

@minip, vous avez mal lu la spécification: il ne dit pas "si vous le souhaitez, vous pouvez prendre en charge .. et .1.2", il dit, "si vous le souhaitez, vous pouvez supposer que 0 .. et 0.1.2 sont toujours donnés comme .. et .1.2 ".
Omar

@ OmarAntolín-Camarena Point pris. Édité.
mniip

2

C, 164

Ceci est similaire à la solution C d'Orion, même si je l'ai fait à partir de zéro. J'avoue cependant avoir volé un certain nombre de ses optimisations. Il n'est pas beaucoup plus court, mais il gère 0,25. = 1/4 et 0,00000000,1 = 1/9000000.

long a,b,c,d,e;main(){while((c=getchar()-48)>-3)c+2?a=a*10+c,b*=10:b?e=a,d=b:(b=1);
b>d?a-=e,b-=d:0;for(d=2;d<=a;)a%d+b%d?d++:(a/=d,b/=d);printf("%ld/%ld\n",a,b);}

2

Deux réponses python sans bibliothèque. Gère d'abord l'entrée facultative sans chiffre avant le premier. et 162 caractères

_=lambda a,b:b and _(b,a%b)or a;i,t,r=raw_input().split(".");b=r!="";d=(10**len(r)-b)*10**len(t);n=int((i+t+r)or 0)-b*int((i+t)or 0);f=_(d,n);print "%i/%i"%(n,d)

Le second ne gère rien avant le premier chiffre mais gère correctement toutes les entrées requises et est de 150 caractères

_=lambda a,b:b and _(b,a%b)or a;i,t,r=raw_input().split(".");b=r!="";d=(10**len(r)-b)*10**len(t);n=int(i+t+r)-b*int(i+t);f=_(d,n);print "%i/%i"%(n,d)

2

Haskell

import Data.Ratio
f n=case s '.' n of
    [x,y,z]->(r x)%1+(r y)%(10^(length y))+(r z)%((10^t-1)*(10^(length y)))
        where
            r ""=0
            r n=read n
            t = if length z==0 then 9 else length z
s _ []=[[]]
s n (x:xs) | x==n = []:(s n xs)
           | otherwise = let (l:ls)=s n xs in (x:l):ls

Hé, c'est du code-golf, vous n'essayez même pas!
mniip

@mniip Je ne suis pas bon au golf de code. Au moins, j'ai utilisé des noms de variables à caractère unique.
PyRulez

1
Vous n'avez jamais spécifié la langue ou le nombre total de caractères / octets utilisés.
Justin Fay

2
Utilisez {;} pour économiser de l'espace sur les retraits, spanpour implémenter s, ajoutez des alias courts pour les fonctions, supprimez l'espace si possible. import Data.Ratio v=span(/='.');w=tail;l=length;f n=(r x)%1+(r y)%p+(r z)%((10^t-1)*p)where{(x,b)=v n;(y,d)=v(w b);z=w d;p=10^(l y);r""=0;r n=read n;t=if null z then 9 else l z}- 178 caractères, en baisse de 321. NB Trueest synonyme de otherwise, null zestlength z==0
bazzargh

2

JavaScript (ECMAScript 6) 180 175

G=(a,d)=>d?G(d,a%d):a;P=a=>+("1e"+a);L=a=>a.length;f=prompt().split(".");B=P(L(b=f[1]));D=P(L(b)+L(c=f[2]))-P(L(b))||1;alert((m=(f[0]+b||0)*D+B*(c||0))/(g=G(m,n=B*D))+"/"+n/g)

Bien que ce ne soit pas un gagnant clair pour la prime de 300 ... c'est le plus court que je puisse trouver:

  • Changements par rapport à la version précédente: quelques légères altérations de la logique et modifications de la Pfonction Power en la modifiant au +("1e"+a)lieu d' Math.pow(10,a)enregistrer ainsi quelques caractères supplémentaires ...

1

Mathematica 175

f@i_:=
If[IntegerQ[g=FromDigits[Map[IntegerDigits@ToExpression@#&,StringSplit[i,"."]/.""-> {}]
/.{a_,b_,c_}:> {{Sequence@@Join[a,b],c},Length@a}]],HoldForm[Evaluate@g]/HoldForm@1,g]

La plupart de la routine consiste à masser l'entrée. Environ 50 caractères sont allés à la gestion des entiers.


Exemples

f["7801.098.765"]

frac1

Plus d'exemples:

TableForm[
 Partition[{#, f[#]} & /@ {"19..87", "19.3.87", "5.3.87", "0.0.3", "0..3", "0.2.283950617", 
"123.456.789", "6666.7777.8888", "2.0.0","0.0.0"}, 5], TableSpacing -> {5, 5}]

frac2


Comment cela serait normalement accompli dans Mathematica

FromDigitspeut obtenir une fraction directement à partir d'une décimale récurrente récurrente, à condition que l'entrée soit sous une forme particulière. Les entiers sont affichés sous forme d'entiers.

z={{{1, 9, {8, 7}}, 2}, {{1, 9, 3, {8, 7}}, 2}, {{5, 3, {8, 7}}, 1}, {{{3}}, -1}, {{{3}}, 0}, 
{{2, {2, 8, 3, 9, 5, 0, 6, 1, 7}}, 0}, {{1, 2, 3, 4, 5, 6, {7, 8, 9}}, 3}, 
{{6, 6, 6, 6, 7, 7, 7, 7, {8}}, 4}, {{2}, 1}, {{0}, 1}}

FromDigits/@z

z


Votre sortie est au mauvais format, elle est bien trop jolie.
Omar

Étrangement, il s'agit du format par défaut pour exprimer des fractions dans Mathematica. Il faudrait plusieurs caractères supplémentaires pour changer ce format pour le plus simple.
DavidC

1

J (96 caractères)

Je n'utilise pas le symbole de barre oblique comme séparateur (mais la solution dans Mathematica non plus car elle utilise une représentation graphique qui est de toute façon meilleure); en langage J, la fraction est affichée avec à la rplace /:

   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '1..3'
4r3
   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '123.456.789'
41111111r333000

1

APL (pas entièrement général)

Pas complètement général (comme ma solution pour DC); fonctionne avec Dyalog APL (mais pas sur la version en ligne de Dyalog APL, je ne sais pas pourquoi):

(R,F)÷(F←D×N)∨R←(⍎C)+D×(⍎I/⍨2>+\P)×N←10*¯1++/≠\P⊣D←¯1+10*⍴C←1↓I/⍨2=+\P←'.'=I← '123.456.789'

Le premier champ est facultatif, mais au moins un chiffre est requis pour les deux autres champs.


1

JavaScript (189)

i=prompt().split(".");a=i[0];b=i[1];c=i[2];B=b.length;p=Math.pow;n=a+b+c-(a+b);d=p(10,B+c.length)-p(10,B);f=1;while(f){f=0;for(i=2;i<=n;i++)if(n%i==0&&d%i==0){n/=i;d/=i;f=1}};alert(n+"/"+d)

Exemple:

Contribution:

5.3.87

Sortie:

889/165

1

C (420 caractères tels qu'écrits; moins après la suppression des espaces inutiles)

Notez que cela suppose 64 bits long(par exemple Linux 64 bits); il échouera pour le scénario de test 0.2.283950617sur les systèmes utilisant 32 bits long. Cela peut être résolu au prix de certains caractères en changeant le type en long longet en changeant la printfchaîne de format en conséquence.

#include <stdio.h>

long d[3], n[3], i;

int main(int c, char** v)
{
  while (c = *v[1]++)
    switch(c)
    {
    case '.':
      n[++i] = 1;
      break;
    default:
      d[i] = 10 * d[i] + c - '0';
      n[i] *= 10;
    }

  n[2] -= n[2] != 1;

  while (i--)
    d[2] += d[i] * n[i+1], n[i]*=n[i+1];

  i = d[2];
  *n = n[1];

  while (i)
    *d = i, i = *n%i, *n = *d;
  printf("%ld/%ld\n", d[2]/ *n, n[1]/ *n);
}

Agréable. Vous pouvez raser 1 caractère en changeant '0'en 48.
Todd Lehman

Je pense que vous pourriez également en économiser un peu plus en réécrivant la switchdéclaration sous la forme if(c==46) n[++i]=1; else d[i]=10*d[i]+c-48,n[i]*=10;.
Todd Lehman

-3

GTB , 81

`_:s;_,1,l?_)-S;_,"."
s;A;,1,S;_,".")-1
s;_,1+S;_,"."),l?_)-S;_,"."))→_
x?A;+_)►Frac

Exemple

?3.25.
            13/4

4
Jusqu'à ce qu'un compilateur soit mis gratuitement à disposition pour cette langue, je dévaloriserai chaque réponse qui l'utilise.
Gareth

1
Il semble y avoir un compilateur sur la page liée ci-dessus?
skibrianski

@skibrianski Voir cet article sur meta
mniip

2
@Gareth, il y a aussi quelques réponses Mathematica à noter. : P
Omar

2
@ OmarAntolín-Camarena Il existe un compilateur / interprète pour Mathematica. GTB n'en a pas. Suivez le GTBlien ci-dessus si vous ne me croyez pas. Vous obtiendrez des éléments compressés pour un programme propriétaire, puis vous rechercherez ce programme et constaterez que le site qui prétend fournir un téléchargement dit qu'il n'est pas disponible. Alors, comment pouvons-nous le compiler?
Gareth
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.