Échangez certaines parties périodiques et non périodiques

21

Dans la représentation décimale de chaque nombre rationnel p/q, vous avez une queue périodique, une tête non périodique et une section avant la virgule décimale au format suivant:

(before decimal point).(non-periodic)(periodic)

Quelques exemples:

1/70 = 0.0142857... = (0).(0)(142857)
10/7 = 1.428571... = (1).()(428571)            ## no non-periodic part
1/13 = 0.076923... = (0).()(076923)
3/40 = 0.075 = (0).(075)()                    ## no periodic part
-2/15 = -0.13... = -(0).(1)(3)                ## negative
75/38 = 1.9736842105263157894... = (1).(9)(736842105263157894)
                                              ## periodic part longer than float can handle
25/168 = 0.148809523... = (0).(148)(809523)
120/99 = 40/33 = 1.212121... = (1).()(21)
2/1 = 2 = (2).()()                            ## no periodic, no non-periodic
0/1 = 0 = (0).()()
0/2 = 0 = (0).()()
299/792 = 0.37752... = (0).(377)(52)
95/-14 = -6.7857142... = -(6).(7)(857142)
-95/-14 = 6.7857142... = (6).(7)(857142)

Le défi est d'échanger les parties périodiques et non périodiques, en laissant le before decimal pointseul, pour créer un nouveau nombre. Par exemple:

25/168 = 0.148809523... = (0).(148)(809523)
       => (0).(809523)(148) = 0.809523148148... = 870397/1080000

Si un nombre n'a pas de partie périodique, 0.25transformez ce nombre en un nouveau nombre périodique, et vice versa.

1/4 = 0.25 = (0).(25)() => (0).()(25) = 0.252525... = 25/99
4/9 = 0.444444... = (0).()(4) => (0).(4)() = 0.4 = 2/5
5/1 = 5 = (5).()() => (5).()() = 5 = 5/1

Le défi

  • Prenez une fraction xen entrée, une chaîne, deux entrées, un nombre rationnel ou toute autre méthode adaptée à votre langue.
  • Échangez les parties périodiques et non périodiques de la représentation décimale de xpour créer un nouveau nombre, en laissant la partie avant la décimale seule. La partie périodique démarre toujours dès que possible afin que la partie non périodique soit aussi courte que possible. Voici des exemples.
  • Renvoie le nombre échangé en tant que nouvelle fraction. L'entrée n'est pas nécessairement réduite alors que la sortie devrait l'être. Le format d'entrée peut différer du format de sortie.
  • Le numérateur pde xsera un entier avec une valeur absolue d'un million ou moins et le dénominateur qde xsera un entier non nul avec une valeur absolue d'un million ou moins.
  • Le numérateur ret le dénominateur sdu résultat ne sont pas garantis inférieurs à un million. Étant donné la longueur des parties périodiques de ces nombres, il est recommandé d'éviter la conversion directe en flottants.
  • C'est le golf de code. La réponse la plus courte en octets gagne.

Exemples

1/70 = (0).(0)(142857)     => (0).(142857)(0) = (0).(142857)() = 0.142857 = 142857/1000000
10/7 = (1).()(428571)      => (1).(428571)() = 1.428571 = 1428571/1000000
1/13 = (0).()(076923)      => (0).(076923)() = 0.076293 = 76923/1000000
3/40 = (0).(075)()         => (0).()(075) = 0.075075... = 75/999 = 25/333
-2/15 = -(0).(1)(3)        => -(0).(3)(1) = -0.311111... = -28/90 = -14/45
75/38 = (1).(9)(736842105263157894)
      => (1).(736842105263157894)(9) = (1).(736842105263157895)()  ## since 0.999... = 1
      = 1.736842105263157895 = 1736842105263157895/1000000000000000000
      = 347368421052631579/200000000000000000
25/168 = (0).(148)(809523) => (0).(809523)(148) = 0.809523148148... = 870397/1080000
120/99 = (1).()(21)        => (1).(21)() = 1.21 = 121/100
2/1 = (2).()()             => (2).()() = 2 = 2/1
0/1 = (0).()()             => (0).()() = 0 = 0/1
0/2 = (0).()()             => (0).()() = 0 = 0/1
299/792 = (0).(377)(52)    => (0).(52)(377) = 0.52377377... = 2093/3996
95/-14 = -(6).(7)(857142)  => -(6).(857142)(7) = -6.857142777... = -12342857/1800000
-95/-14 = (6).(7)(857142)  => (6).(857142)(7) = 6.857142777... = 12342857/1800000
Sherlock9
la source
Il manque un élément 0à la fin du cas de test 2 ( 10/7): 1428571/100000devrait l'être 1428571/1000000.
JungHwan Min
1
Comme indiqué, il n'y aura pas de réponse unique pour une entrée donnée. 1/7pourrait être représentée comme (0).()(142857) ou (0).(1)(428571), 1pourrait être représentée comme (1).()(), (0).()(9), (0).()(99), (0).(9)(9), etc.
ngenisis
@ngenisis C'était implicite dans les exemples, mais je l'ai rendu explicite. Merci pour les commentaires :)
Sherlock9
@ R.Kap J'ai déjà déclaré dans le défi qu'il vaut mieux éviter d'utiliser des flotteurs ici. Il existe des moyens de trouver les chiffres décimaux d'un nombre sans le convertir en flottant. J'espère que cela répond à votre question :)
Sherlock9
p et q peuvent-ils être négatifs?
edc65

Réponses:

5

Python 2, 292 octets

def x(n,d):
 L=len;s=cmp(n*d,0);n*=s;b=p=`n/d`;a={};n%=d
 while not n in a:
  a[n]=p;q=n/d;n=n%d
  if q==0:n*=10;p+=' '
  p=p[:-1]+`q`
 p=p[L(a[n]):];a=a[n][L(b):]
 if n==0:p=''
 n=int(b+p+a);d=10**L(p+a)
 if a!='':n-=int(b+p);d-=10**L(p)
 import fractions as f;g=f.gcd(n,d);return(n/g*s,d/g)

Version non golfée, fonctionne à la fois en python 2 et 3. Imprime également la représentation décimale.

def x(n,d):
# sign handling
 s=n*d>0-n*d<0
 n*=s
# b, a, p: BEFORE decimal, AFTER decimal, PERIODIC part
 b=p=str(n//d)
 a={}
 n%=d
# long division
 while not n in a:
  a[n]=p
  q=n//d
  n=n%d
  if q==0:
   n*=10
   p+=' '
  p=p[:-1]+str(q)
# a/p still contain b/ba as prefixes, remove them
 p=p[len(a[n]):]
 a=a[n][len(b):]
 if n==0: p=''
# print decimal representation
 print("(" + b + ").(" + a + ")(" + p + ")")
# reassemble fraction (with a and p exchanged)
 n=int(b+p+a)
 d=10**len(p+a)
 if a!='':
  n-=int(b+p)
  d-=10**len(p)
# reduce output
 from fractions import gcd
 g=gcd(n,d)
 return(n//g*s,d//g)
Rainer P.
la source
Essayezd=10**len(p+a)
Sherlock9
1
Voici un lien TIO pour un test facile: essayez-le en ligne!
Kritixi Lithos
Bravo pour votre réponse: D. Quelques conseils de golf supplémentaires: utilisez plus de points-virgules si possible, supprimez l'espace dans la ligne if n==0: p='', utilisez-le ``à chaque endroit que vous utilisez str, comme à la `n/d`place de str(n/d), et renommez- lenle Lavec L=len;au début de la fonction.
Sherlock9
@ Sherlock9 Je ne connaissais même pas les backticks. Merci pour tous les conseils.
Rainer P.
Pas de problème. En voici encore plus: D Deux emplacements pour les points-virgules: n=int(b+p+a);d=10**L(p+a)et import fractions as f;g=f.gcd(n,d);return(n/g*s,d/g). De plus, j'obtiens 295 octets pour votre édition actuelle. Y a-t-il une nouvelle ligne supplémentaire que vous oubliez de laisser de côté?
Sherlock9
2

Gelée , 102 101 89 87 83 81 79 78 77 74 octets

Cela a pris beaucoup de temps à écrire, beaucoup trop de temps à déboguer et a certainement besoin de beaucoup de golf ( huit sept six cinq quatre liens, sainte vache), mais c'est, à ma connaissance, correct. Un grand merci à Dennis pour son aide ici, surtout avec les deux premiers liens. Merci également à Rainer P., car j'ai fini par emprunter une grande partie de l'algorithme dans leur réponse Python.

Modifications du golf: -1 octet grâce à Xanderhall. Correction d'un bug de ne pas utiliser la bonne logique NOT intégrée. -13 octets de golf sur les liens du numérateur. +1 octet de correction d'un bug pour le négatif davec merci à Dennis. Restructuré les liens afin que la génération du numérateur soit tout en un seul lien. -2 octets de la combinaison des deuxième et troisième liens. -4 octets du déplacement de certains éléments communs des troisième et quatrième liens vers le deuxième lien et le lien principal. -2 octets de suppression de certains opérateurs de chaîne superflus. -2 octets de la réorganisation de la liaison du numérateur. -1 octet du déplacement Ḣ€à la fin du deuxième lien. Correction d'un bug dans le lien principal. -1 octet de passer Ṫ ... ,Ḣà Ḣ ... ṭ. -3 octets de déplacer le lien numérateur dans le lien principal.

Suggestions de golf bienvenues! Essayez-le en ligne!

2ị×⁵d⁴
ÇÐḶ,ÇÐĿḟ@\µḢḅÐfıṭµḢḊṭµḢ€€µF,ḢQ
ÇL€⁵*
×Ṡ©⁸×%µ³,⁴A:/;Ѐ2ĿḌ×®,Ç_/€µ:g/

Explication

Tout d'abord, je vais expliquer le lien principal , qui appelle les autres liens.

×Ṡ©⁸×%µ³,⁴A:/;Ѐ2ĿḌ×®,Ç_/€µ:g/  Main link. Left argument: n (int), right argument: d (int)
                                Split into three chains.
×Ṡ©⁸×%  First chain
×       Multiply n by d.
 Ṡ©     Yield sign(n*d) and save it to the register.
   ⁸×   Multiply by n.
     %  Yield n*sgn(n*d) modulo d.

µ³,⁴A:/;Ѐ2ĿḌ×®,Ç_/€  Second chain
                        What follows is the formula for the numerator.
                        (+) means combining the digits of two numbers into one number.
                        ( `integer (+) periodic (+) non-periodic` - `integer (+) periodic` )
µ                     Start a new monadic chain with n*sgn(n*d)%d.
 ³,⁴                  Pair the original two arguments as a nilad.
    A                 Get their absolute values.
     :/               Integer divide to get the integer part of abs(n)/abs(d).
          2Ŀ          Yield the results of the second link.
       ;Ѐ            Append the integer part to each item in the right argument.
                        This appends to both lists from the second link.
            Ḍ         Convert each list from decimal to integer.
             ×®       Multiply by sign(n*d) retrieved from the register.
               ;Ç     Concatenate with the result of the third link (our new denominator).
                 _/€  Reduced subtract over each list.
                        Yields the proper numerator and denominator.

µ:g/  Third chain
µ     Start a new monadic chain with [numerator, denominator].
  g/  Yield gcd(numerator, denominator).
 :    Divide [numerator, denominator] by the gcd.
      Return this as our new fraction.

Ensuite, le premier lien qui obtient les chiffres.

2ị×⁵d⁴  First link: Gets the decimal digits one at a time in the format:
          [digit, remainder to use in the next iteration]
2ị      Gets the second index (the remainder).
  ×⁵    Multiply by 10.
    d⁴  Divmod with d.

Maintenant, le deuxième lien qui obtient les parties périodiques et non périodiques de n/d, et beaucoup d'autres levées de poids.

ÇÐḶ,ÇÐĿḟ@\µḢḅÐfıṭµḢḊṭµḢ€€µF,ḢQ  Second link: Loops the first link,
                                  separates the periodic digits and non-periodic digits,
                                  removes the extras to get only the decimal digits,
                                  and prepares for the third and fourth links.
                                Split into five chains.
ÇÐḶ,ÇÐĿḟ@\  First chain
ÇÐḶ         Loop and collect the intermediate results **in the loop**.
    ÇÐĿ     Loop and collect **all** of the intermediate results.
   ,        Pair into one list.
       ḟ@\  Filter the loop results out the list of all results,
              leaving only [[periodic part], [non-periodic part]].

µḢḅÐfıṭµḢḊṭ  Second and third chains
µ            Start a new monadic chain.
 Ḣ           Get the head [periodic part].
   Ðf        Filter out any [0, 0] lists from a non-periodic number,
  ḅ  ı        by converting to a complex number before filtering.
               Only removes 0+0j. This removes extra zeroes at the end.
      ṭ      Tack the result onto the left argument again.
       µ     Start a new monadic chain.
        Ḣ    Get the head [non-periodic and extra baggage].
         Ḋ   Dequeue the extra baggage.
          ṭ  Tack the result onto the left argument again.

µḢ€€µF,ḢQ  Fourth and fifth chains
µ          Start a new monadic chain with the processed periodic and non-periodic parts.
 Ḣ€€       Get the head of each list (the digits)
            in both the periodic and non-periodic parts.
    µ      Start a new monadic chain with these lists of digits.
     F     Left argument flattened.
       Ḣ   Head of the left argument.
      ,    Pair the flattened list and the head into one list.
        Q  Uniquify this list. (Only removes if non-periodic part is empty)
             Removes any duplicates resulting from a purely periodic n/d.

Le troisième maillon , qui donne notre nouveau dénominateur.

ÇL€⁵*  Third link: Generate the denominator.
         What follows is the formula for the denominator.
         ( 10**(num_digits) - ( 10**(num_periodic_digits) if len(non-periodic) else 0 ) )
Ç      Yield the results of the second link.
 L€    Get the length of each item in the list.
         The number of digits in total and the number of digits in the periodic part.
   ⁵*  10 to the power of each number of digits.
Sherlock9
la source