Calcola la norma p-adica di un numero razionale


11

Calcola la norma p-adica di un numero razionale

Scrivi una funzione o un programma, che accetta 3 numeri interi m,n,p(dove pè un numero primo positivo) come input, che genera la norma p-adica (indicata da |m/n|_p) come una frazione (completamente ridotta). Fermat è noto per avere solo margini molto piccoli, ma ciò che è piuttosto sconosciuto è che aveva solo uno schermo di computer molto piccolo. Quindi cerca di rendere il codice il più corto possibile affinché si adatti allo schermo di Fermat!

Definizione

Dato un numero primo p, ogni frazione m/npuò essere scritta in modo univoco (ignorando i segni) in quanto (a/b)* p^etale eè un numero intero e pnon divide né ané né b. La norma p-adica di m/nè p^-e. C'è un caso particolare, se la frazione è 0: |0|_p = 0.

Il formato di output deve essere x/y(ad esempio 1/3; per numeri interi sono consentiti entrambi 10o equivalentemente 10/1, per numeri negativi deve essere presente un segno meno ad esempio -1/3)

Dettagli

Il programma deve usare stdin / stdout o essere semplicemente costituito da una funzione che restituisce il numero o la stringa razionali. Devi supporre che l'input m/nnon sia completamente ridotto. Puoi presumere che psia un numero primo. Il programma deve essere in grado di elaborare numeri interi tra un -2^28massimo di 2^28e non dovrebbe richiedere più di 10 secondi.

Non sono consentite funzionalità integrate di fattorizzazione e controllo di base, così come conversazioni di base integrate e funzioni integrate che calcolano la valutazione o la norma p-adic.

Esempi (rubati da Wikipedia ):

x = m/n = 63/550 = 2^-1 * 3^2 * 5^-2 * 7 * 11^-1
|x|_2 = 2
|x|_3 = 1/9
|x|_5 = 25
|x|_7 = 1/7
|x|_11 = 11
|x|_13 = 1

interessante curiosità

(Non è necessario conoscere / leggere per questa sfida, ma forse bello da leggere come motivazione.)

(Per favore, correggimi se uso parole sbagliate o qualcos'altro non va, non sono abituato a parlarne in inglese.)

Se consideri i numeri razionali come un campo, allora la norma p-adica induce la metrica p-adica d_p(a,b) = |a-b|_p. Quindi puoi completare questo campo per quanto riguarda questa metrica, ciò significa che puoi costruire un nuovo campo in cui convergono tutte le sequenze cauchy, che è una bella proprietà topologica da avere. (Che ad esempio i numeri razionali non hanno, ma i reali lo fanno.) Questi numeri p-adici sono, come avresti potuto immaginare, usati molto nella teoria dei numeri.

Un altro risultato interessante è il teorema di Ostrowski che sostanzialmente dice che qualsiasi valore assoluto (come definito di seguito) sui numeri razionali è uno dei tre seguenti:

  • Il banale: |x|=0 iff x=0, |x|=1 otherwise
  • Lo standard (reale): |x| = x if x>=0, |x| = -x if x<0
  • Il p-adic (come lo abbiamo definito).

Un valore assoluto / una metrica è solo la generalizzazione di ciò che consideriamo una distanza . Un valore assoluto |.|soddisfa le seguenti condizioni:

  • |x| >= 0 and |x|=0 if x=0
  • |xy| = |x| |y|
  • |x+y| <= |x|+|y|

Nota che puoi facilmente costruire metriche da valori assoluti e viceversa: |x| := d(0,x)o d(x,y) := |x-y|, quindi, sono quasi uguali se puoi aggiungere / sottrarre / moltiplicare (cioè in domini integrali). Ovviamente puoi definire una metrica su insiemi più generali, senza questa struttura.


Presumo che anche la PadicNormfunzione di Mathematica sia fuori servizio? : P
Alex A.

Si assume corretto / ly. (quale viene usato qui?)
flawr

A meno che la sezione Proprietà interessanti non sia utile per completare la sfida, direi che è meglio collegarsi a tali informazioni per le parti interessate. Altrimenti ingombra inutilmente la posta.
Alex A.

Giusto per essere chiari, l'output dovrebbe essere qualcosa del genere |x|_11 = 11, giusto? O va 11bene? E deve gestire il x=0caso?
Glen O,

@GlenO Corretto, deve gestire il x=0caso e per questo esempio è possibile eseguire l'output 11e anche 11/1, ma non è necessario stampare |x|_11.
flawr

Risposte:


3

Julia, 94 80 75 byte

f(m,n,p)=(k=gcd(m,n)
g(m)=m%p>0?g(m÷p)p:1
m!=0?print(g(n÷k),/,g(m÷k)):0)

Nota: l'utilizzo di avanzamenti di riga al posto dei punti e virgola per leggibilità - funzionerà allo stesso modo in entrambi i modi.

Questo è abbastanza semplice: la g(m,n)funzione utilizza la ricorsione e il resto ( %) per estrarre il p^nfattore dall'input m, con n=1il valore predefinito e quindi moltiplicato per pogni passaggio della ricorsione, in modo che l'output sia p^n. Il codice si applica a n/gcd(m,n), quindi m/gcd(m,n)a ottenere l'espressione appropriata. k=gcd(m,n)viene utilizzato per evitare il calcolo del gcd(m,n)doppio, per salvare i caratteri. m!=0è un test per gestire il caso in cui x=0.

L'output è nella forma N/1o, 1/Nse del caso, dove si Ntrova p^e.


1

J, 35 34 byte

(,'/'&,)&":/@(%+./)@(]<.^+.|.@])x:

Questo è un verbo binario che prende il primo pcome argomento sinistro e l'array m ncome argomento destro. Stampa sempre la barra /e restituisce 0/1if m = 0. Usalo in questo modo:

  f =: (,'/'&,)&":/@(%+./)@(]<.^+.|.@])x:
  5 f 63 550
25/1

Spiegazione

La x:svolta aumenta la precisione, poiché stiamo gestendo numeri molto grandi. Il resto del codice funziona come segue:

(,'/'&,)&":/@(%+./)@(]<.^+.|.@])
                        ^         Power: this gives the array p^n p^m
                         +.       Take element-wise GCD with
                           |.@]   the rotated array n m; this gives
                                  the largest powers of p that divide n and m
                      <.          Take element-wise minimum with
                     [            The array m n to handle the m=0 case correctly
              %+./                Divide this array by its GCD to get it to lowest terms
        &":/                      Convert both elements to strings
 ,'/'&,                           Insert the slash '/' between them

0

CJam, 42 byte

q~)\_:*g_sW<o@*28#f{{{_@\%}h;}:G~}_~Gf/'/*

Questo termina con un errore (dopo aver stampato 0) per l'ingresso 0. Provalo online nell'interprete CJam .


0

Stax , 32 byte

éE▌ΦΔΘao£╙)ΩuÅI~AAε3∞xC█&½╤%╩▌ïö

Esegui ed esegui il debug

Dovrebbe essere in grado di renderlo più breve. Il supporto nativo per la frazione di Stax è abbastanza accurato.

Equivalente ASCII:

hY{y:+y|aEGsG-ys|**}0?}0{^scxHY%Cy/sWd
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.