Scambia alcune parti periodiche e non periodiche


21

Nella rappresentazione decimale di ogni numero razionale p/q, hai una coda periodica, una testa non periodica e una sezione prima del punto decimale nel seguente formato:

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

Alcuni esempi includono:

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)

La sfida è scambiare le parti periodiche e non periodiche, lasciando il before decimal pointsolo, per creare un nuovo numero. Per esempio:

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

Se un numero non ha parti periodiche come 0.25trasformare quel numero in un nuovo numero periodico e viceversa.

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

La sfida

  • Prendi una frazione xcome input, come una stringa, due input, un numero razionale o qualunque metodo si adatti alla tua lingua.
  • Scambia le parti periodiche e non periodiche della rappresentazione decimale xper creare un nuovo numero, lasciando la parte prima del solo decimale. La parte periodica inizia sempre il più presto possibile in modo che la parte non periodica sia il più breve possibile. Gli esempi sono di seguito.
  • Restituisce il numero scambiato come nuova frazione. L'input non è necessariamente ridotto, sebbene dovrebbe essere l'output. Il formato di input può differire dal formato di output.
  • Il numeratore pdi xsarà un numero intero con un valore assoluto di un milione o meno e il denominatore qdi xsarà un numero intero diverso da zero con un valore assoluto di un milione o meno.
  • Non è garantito che il numeratore re il denominatore sdel risultato siano inferiori a un milione. Data la lunghezza delle parti periodiche di questi numeri, si consiglia di evitare la conversione diretta in float.
  • Questo è il codice golf. Vince la risposta più breve in byte.

Esempi

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

0Alla fine del test case 2 ( 10/7) manca : 1428571/100000dovrebbe essere 1428571/1000000.
JungHwan Min,

1
Come detto, non ci sarà una risposta unica per un dato input. 1/7potrebbe essere rappresentato come (0).()(142857) o (0).(1)(428571), 1potrebbe essere rappresentato come (1).()(), (0).()(9), (0).()(99), (0).(9)(9), ecc
ngenisis

@ngenisis Questo era implicito negli esempi, ma l'ho reso esplicito. Grazie per il feedback :)
Sherlock9,

@ R.Kap Ho già dichiarato nella sfida che è meglio evitare di usare i float qui. Esistono modi per trovare le cifre decimali di un numero senza convertirle in un float. Spero che questo risponda alla tua domanda :)
Sherlock9,

sia p che q possono essere negativi?
edc65,

Risposte:


5

Python 2, 292 byte

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)

Versione non golfata, funziona sia in Python 2 che in 3. Stampa anche la rappresentazione decimale.

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)

Provad=10**len(p+a)
Sherlock9,

1
Ecco un link TIO per test facili: provalo online!
Kritixi Lithos,

Complimenti per la tua risposta: D. Ulteriori suggerimenti golf: un uso più punti e virgola, ove possibile, di sbarazzarsi dello spazio in linea if n==0: p='', l'uso ``in ogni luogo si utilizza str, come ad esempio `n/d`al posto di str(n/d), e rinomina lena Lcon L=len;all'inizio della funzione.
Sherlock9,

@ Sherlock9 Non sapevo nemmeno dei backtick. Grazie per tutti i consigli.
Rainer P.

Non è un problema. Eccone altri: D Due posti per punto n=int(b+p+a);d=10**L(p+a)e virgola: e import fractions as f;g=f.gcd(n,d);return(n/g*s,d/g). Inoltre, ottengo 295 byte per la modifica corrente. C'è una nuova riga in più che stai dimenticando di lasciare fuori?
Sherlock9,

2

Gelatina , 102 101 89 87 83 81 79 78 77 74 byte

Questo ha richiesto molto tempo per scrivere, troppo tempo per il debug e ha sicuramente bisogno di molto golf ( otto sette sei cinque quattro collegamenti, mucca santa), ma è, per quanto ne sappia, corretto. Molte, molte grazie a Dennis per il suo aiuto qui, specialmente con i primi due link. Mille grazie anche a Rainer P., poiché ho finito per prendere in prestito gran parte dell'algoritmo nella loro risposta Python.

Modifiche al golf: -1 byte grazie a Xanderhall. Correzione di bug da non utilizzare il logico NON incorporato corretto. -13 byte dal golf dei collegamenti numeratore. +1 byte dalla correzione di un bug per negativo dcon grazie a Dennis. Ristrutturato i collegamenti in modo che la generazione del numeratore sia tutto in un unico collegamento. -2 byte dalla combinazione del secondo e del terzo collegamento. -4 byte dallo spostamento di alcuni elementi comuni del terzo e del quarto collegamento sul secondo e sul collegamento principale. -2 byte dalla rimozione di alcuni operatori di catena superflui. -2 byte dalla riorganizzazione del collegamento numeratore. -1 byte dallo spostamento Ḣ€alla fine del secondo collegamento. Risolto un bug nel collegamento principale. -1 byte dal passaggio Ṫ ... ,Ḣa Ḣ ... ṭ. -3 byte dallo spostamento del collegamento numeratore nel collegamento principale.

Suggerimenti di golf benvenuti! Provalo online!

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

Spiegazione

Innanzitutto, spiegherò il collegamento principale , che chiama gli altri collegamenti.

×Ṡ©⁸×%µ³,⁴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.

Quindi, il primo collegamento che ottiene le cifre.

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.

Ora, il secondo collegamento che ottiene le parti periodiche e non periodiche n/de molti altri sollevamenti pesanti.

ÇÐḶ,ÇÐĿḟ@\µḢḅÐ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.

Il terzo link , che produce il nostro nuovo denominatore.

Ç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.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.