Calcular a norma p-adic de um número racional

11

Calcular a norma p-adic de um número racional

Escreva uma função ou um programa, que use 3 números inteiros m,n,p(onde pé um primo positivo) como entrada, que produza a norma p-adic (indicada por |m/n|_p) como uma fração (completamente reduzida). Sabe-se que Fermat possui apenas margens muito pequenas, mas o que é desconhecido é que ele tinha apenas uma tela de computador muito pequena. Portanto, tente tornar o código o mais curto possível para caber na tela de Fermat!

Definição

Dado um primo p, cada fração m/npode ser escrita exclusivamente (ignorando os sinais), como (a/b)* p^etal, que eé um número inteiro e pnão divide nem anem b. A norma p-adic de m/né p^-e. Não é um caso especial, se a fração for 0: |0|_p = 0.

O formato de saída deve ser x/y(por exemplo 1/3, para números inteiros ambos 10ou equivalentemente 10/1é permitido, para números negativos deve haver um sinal de menos à frente -1/3)

Detalhes

O programa deve usar stdin / stdout ou apenas consistir em uma função que retorna o número racional ou a sequência. Você deve assumir que a entrada m/nnão está totalmente reduzida. Você pode assumir que isso pé primo. O programa deve ser capaz de processar números inteiros entre -2^28até 2^28e não deve demorar mais de 10 segundos.

Não são permitidas funcionalidades embutidas de fatoração e verificação primária, bem como conversação básica e função incorporada que calculam a avaliação ou norma p-adic.

Exemplos (roubados 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

Curiosidades interessantes

(Não é necessário saber / ler para este desafio, mas talvez seja bom ler como motivação.)

(Corrija-me se eu usar as palavras erradas, ou se algo estiver errado, não estou acostumado a falar sobre isso em inglês.)

Se você considerar os números racionais como um campo, a norma p-adic induz a métrica p-adic d_p(a,b) = |a-b|_p. Em seguida, você pode preencher esse campo com relação a essa métrica, o que significa que você pode construir um novo campo onde todas as sequências cauchy convergem, o que é uma boa propriedade topológica. (Que, por exemplo, os números racionais não têm, mas os reais.) Esses números p-adic são como você deve ter adivinhado, muito usados ​​na teoria dos números.

Outro resultado interessante é o teorema de Ostrowski, que basicamente diz que qualquer valor absoluto (conforme definido abaixo) nos números racionais é um dos três seguintes:

  • O trivial: |x|=0 iff x=0, |x|=1 otherwise
  • O padrão (real): |x| = x if x>=0, |x| = -x if x<0
  • O p-adic (como o definimos).

Um valor absoluto / uma métrica é apenas a generalização do que consideramos uma distância . Um valor absoluto |.|satisfaz as seguintes condições:

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

Observe que você pode facilmente construir métricas a partir de valores absolutos e vice-versa: |x| := d(0,x)ou d(x,y) := |x-y|, então, elas são quase as mesmas se você puder adicionar / subtrair / multiplicar (que está em domínios integrais). É claro que você pode definir uma métrica em conjuntos mais gerais, sem essa estrutura.

flawr
fonte
Presumo que a PadicNormfunção do Mathematica também esteja fora? : P
Alex A.
Você assume correto / ly. (o que um é usado aqui?)
flawr
A menos que a seção Propriedades interessantes seja útil para concluir o desafio, eu diria que é melhor vincular essas informações às partes interessadas. Caso contrário, ele desorganiza desnecessariamente a publicação.
Alex A.
Só para esclarecer, a saída deve ser algo como |x|_11 = 11, certo? Ou está 11bem? E tem que lidar com o x=0caso?
Glen O
@GlenO Correto, ele precisa lidar com o x=0caso e, neste exemplo, você pode imprimir 11também 11/1, mas não precisa imprimir |x|_11.
flawr

Respostas:

3

Julia, 94 80 75 bytes

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: o uso de feeds de linha no lugar de ponto e vírgula para facilitar a leitura - funcionará da mesma maneira.

Isso é bastante simples - a g(m,n)função usa recursão e restante ( %) para extrair o p^nfator da entrada m, com n=1o padrão e depois multiplicado por pcada etapa da recursão, para que a saída seja p^n. O código aplica isso a n/gcd(m,n)e, em seguida, m/gcd(m,n)para obter a expressão apropriada. k=gcd(m,n)é usado para evitar o cálculo gcd(m,n)duas vezes, para salvar caracteres. m!=0é um teste para lidar com o caso em que x=0.

A saída é da forma N/1ou, 1/Nconforme apropriado, onde Nestá p^e.

Glen O
fonte
1

J, 35 34 bytes

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

Este é um verbo binário que usa o primo pcomo argumento à esquerda e a matriz m ncomo argumento à direita. Ele sempre imprime a barra /e retorna 0/1se m = 0. Use-o assim:

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

Explicação

A x:precisão aumenta, já que estamos lidando com números muito grandes. O restante do código funciona da seguinte maneira:

(,'/'&,)&":/@(%+./)@(]<.^+.|.@])
                        ^         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
Zgarb
fonte
0

CJam, 42 bytes

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

Isso termina com um erro (após a impressão de 0) para a entrada 0. Experimente on-line no intérprete CJam .

Dennis
fonte
0

Stax , 32 bytes

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

Execute e depure

Deve ser capaz de torná-lo mais curto. O suporte nativo para fração por Stax é bastante elegante.

Equivalente ASCII:

hY{y:+y|aEGsG-ys|**}0?}0{^scxHY%Cy/sWd
Weijun Zhou
fonte