Solução Fundamental da Equação de Pell


28

Dado um número inteiro positivo que não é um quadrado, encontre a solução fundamental da equação de Pell associadan(x,y)

x2ny2=1

Detalhes

  • O fundamental é um par de números inteiros satisfazendo a equação em que é mínimo e positivo. (Sempre existe a solução trivial que não é contada.)(x,y)x,yx(x,y)=(1,0)
  • Você pode assumir que não é um quadrado.n

Exemplos

 n           x    y
 1           -    -
 2           3    2
 3           2    1
 4           -    -
 5           9    4
 6           5    2
 7           8    3
 8           3    1
 9           -    -
10          19    6
11          10    3
12           7    2
13         649    180
14          15    4
15           4    1
16           -    -
17          33    8
18          17    4
19         170    39
20           9    2
21          55    12
22         197    42
23          24    5
24           5    1
25           -    -
26          51    10
27          26    5
28         127    24
29        9801    1820
30          11    2
31        1520    273
32          17    3
33          23    4
34          35    6
35           6    1
36           -    -
37          73    12
38          37    6
39          25    4
40          19    3
41        2049    320
42          13    2
43        3482    531
44         199    30
45         161    24
46       24335    3588
47          48    7
48           7    1
49           -    -
50          99    14
51          50    7
52         649    90
53       66249    9100
54         485    66
55          89    12
56          15    2
57         151    20
58       19603    2574
59         530    69
60          31    4
61  1766319049    226153980
62          63    8
63           8    1
64           -    -
65         129    16
66          65    8
67       48842    5967
68          33    4
69        7775    936
70         251    30
71        3480    413
72          17    2
73     2281249    267000
74        3699    430
75          26    3
76       57799    6630
77         351    40
78          53    6
79          80    9
80           9    1
81           -    -
82         163    18
83          82    9
84          55    6
85      285769    30996
86       10405    1122
87          28    3
88         197    21
89      500001    53000
90          19    2
91        1574    165
92        1151    120
93       12151    1260
94     2143295    221064
95          39    4
96          49    5
97    62809633    6377352
98          99    10
99          10    1

Sequências OEIS relevantes: A002350 A002349 A033313 A033317


Surpreendeu-me que ainda não haja nenhum desafio com a equação de Pell, já que é bem conhecido, pensei. Pelo menos, lembro-me de usá-lo às vezes com os desafios do Project Euler.
Kevin Cruijssen 16/04

@Fatalize " Você pode supor que não é um quadrado.n " Provavelmente seria mais claro se os casos de teste omitissem aqueles imho.
Kevin Cruijssen 16/04

2
@KevinCruijssen Eu considerei isso, mas achei que seria mais confuso omitir alguns dos ns. (aliás, também fiquei surpreso, mas tive esse desafio na caixa de areia por cerca de um ano)
flawr 16/04

Respostas:


16

Piet , 612 codéis

Toma n da entrada padrão. Emite y e x , separados por espaço.

Codel size 1: Programa de equação de Pell com tamanho de codel 1

Codel tamanho 4, para facilitar a visualização: Programa de equação de Pell com tamanho de codel 1

Explicação

Confira este rastreamento NPiet , que mostra o programa calculando a solução para um valor de entrada 99.

Não tenho certeza se alguma vez ouvi falar da equação de Pell antes desse desafio, por isso recebi o seguinte na Wikipedia; especificamente, essas seções de três artigos:

Basicamente, o que fazemos é o seguinte:

  1. Obtenha da entrada padrão.n
  2. Encontre incrementando um contador até que seu quadrado exceda , em seguida, diminua-o uma vez. (Este é o primeiro loop que você pode ver no rastreamento, no canto superior esquerdo.)nn
  3. Defina-se algumas variáveis para calcular e a partir da fracção de continuação .xyn
  4. Verifique se e caber equação de Pell ainda. Se o fizerem, produza os valores (este é o ramo descendente cerca de 2/3 do caminho) e saia (correndo para o bloco vermelho na extrema esquerda).xy
  5. Caso contrário, atualize iterativamente as variáveis ​​e volte para a etapa 4. (Este é o loop amplo para a direita, de volta para baixo e voltando a entrar no meio do caminho.)

Sinceramente, não tenho idéia se uma abordagem de força bruta seria mais curta, e não vou tentar! Ok, então eu tentei.


9

Piet , 184 codéis

Essa é a alternativa de força bruta que eu disse (na minha outra resposta ) que não queria escrever. Demora mais de 2 minutos para calcular a solução para n = 13. Eu realmente não quero experimentá-lo em n = 29 ... mas ele faz check-out para cada n até 20, por isso estou confiante de que está correto.

Assim como a outra resposta, isso leva n da entrada padrão e gera y e x , separados por espaço.

Codel size 1: Programa de equação de Pell (variante de força bruta) com tamanho de codel 1

Codel tamanho 4, para facilitar a visualização: Programa de equação de Pell (variante de força bruta) com tamanho de codel 4

Explicação

Aqui está o rastreamento NPiet para um valor de entrada 5.

Esta é a força bruta mais brutal, repetindo tanto quanto . Outras soluções podem iterar sobre e calcular , mas são fracos .xyxy=x21n

Começando com e , isso verifica se e já resolveram a equação. Se tiver (o garfo na parte inferior, próximo à direita), ele gera os valores e sai.x=2y=1xy

Caso contrário, ele continua à esquerda, onde é incrementado e comparado com . (Depois, há algumas mudanças de direção para seguir o caminho em zig-zag.)yx

Esta última comparação é onde o caminho se divide em torno do meio esquerdo. Se eles são iguais, é incrementado e é retornado para 1. E voltamos a verificar se ainda é uma solução.xy

Ainda tenho algum espaço em branco disponível, então talvez eu veja se consigo incorporar esse cálculo de raiz quadrada sem ampliar o programa.


2
Haha Eu concordo com os fracos que usam raízes quadradas: D
flawr

6

Braquilog , 16 bytes

;1↔;Ċz×ᵐ-1∧Ċ√ᵐℕᵐ

Experimente online!

Explicação

;1↔                Take the list [1, Input]
   ;Ċz             Zip it with a couple of two unknown variables: [[1,I],[Input,J]]
      ×ᵐ           Map multiply: [I, Input×J]
        -1         I - Input×J must be equal to 1
          ∧        (and)
           Ċ√ᵐ     We are looking for the square roots of these two unknown variables
              ℕᵐ   And they must be natural numbers
                   (implicit attempt to find values that match those constraints)

5

Pari / GP , 34 bytes

O PARI / GP quase possui um recurso interno para isso: quadunitfornece a unidade fundamental do campo quadrático , onde é o discriminante do campo. Em outras palavras, resolve a equação de Pell . Então eu tenho que pegar o quadrado quando sua norma é .Q(D)Dx2-ny2=±1-1quadunit(4*n)x2ny2=±11

Não sei qual algoritmo ele usa, mas funciona mesmo quando não é quadrado.n

As respostas são fornecidas no formulário x + y*w, onde wdenota .n

n->(a=quadunit(4*n))*a^(norm(a)<0)

Experimente online!


4

Wolfram Language (Mathematica) , 46 bytes

FindInstance[x^2-y^2#==1&&x>1,{x,y},Integers]&

Experimente online!


1
É garantido que isso sempre encontre a solução fundamental ?
Greg Martin

@GregMartin sim, é. Isso sempre encontra a primeira solução (mínima). Nesse caso, isso sempre retorna {1,0}. É por isso que temos que escolher x> 1 e obter a segunda solução (fundamental)
J42161217 17/04

1
Eu gostaria que isso fosse verdade, mas nada na documentação parece indicar que ...
Greg Martin

@ GregMartin Eu usei essa função várias vezes e já sabia como ela funcionava. Minha única preocupação era pular a primeira solução e isso me custou esses 5 bytes extras. Você pode facilmente escrever um programa e testá-lo (apenas para confirmar milhões de resultados)
J42161217 17/04

4

05AB1E , 17 16 14 bytes

Guardou um byte graças a Kevin Cruijssen .
Saídas[y, x]

∞.Δn*>t©1%_}®‚

Experimente online!

Explicação

∞                 # from the infinite list of numbers [1 ...]
 .Δ        }      # find the first number that returns true under
   n              # square
    *             # multiply with input
     >            # increment
      t©          # sqrt (and save to register as potential x)
        1%        # modulus 1
          _       # logical negation
            ®‚    # pair result (y) with register (x)

E você me venceu de novo .. tinha 17 byter também, mas não funcionou porque Ųestá cheio de casas decimais ..>. <De qualquer forma, você pode remover os dois ,e adicionar um final (não, as vírgulas não são as mesmo; p) para salvar um byte.
Kevin Cruijssen 16/04

@KevinCruijssen: Obrigado! Sim, eu também fui pela Ųprimeira vez perceber que não funcionava como o esperado.
Emigna 16/04

4

Java 8, 74 73 72 bytes

n->{int x=1;var y=.1;for(;y%1>0;)y=Math.sqrt(-x*~++x/n);return x+" "+y;}

-1 byte graças a @Arnauld .
-1 byte graças a @ OlivierGrégoire .

Experimente online.

Explicação:

n->{                 // Method with double parameter and string return-type
  int x=1;           //  Integer `x`, starting at 1
  var y=.1;          //  Double `y`, starting at 0.1
  for(;y%1>0;)       //  Loop as long as `y` contains decimal digits:
    y=               //   Set `y` to:
      Math.sqrt(     //    The square-root of:
        -x*          //     Negative `x`, multiplied by
           ~++x      //     `(-x-2)` (or `-(x+1)-1)` to be exact)
                     //     (because we increase `x` by 1 first with `++x`)
               /n);  //     Divided by the input
  return x+" "+y;}   //  After the loop, return `x` and `y` with space-delimiter as result

1
72 bytes , mudando npara um double, e xa um int, jogando sobre o facto de que x*x-1é igual a (-x-1)*(-x+1).
Olivier Grégoire

Bem, na verdade estou brincando com o fato de que (x+1)*(x+1)-1é igual a -x*-(x+2), para ser totalmente correto.
Olivier Grégoire

3

R, 66 56 54 53 52 47 45 bytes

um programa completo

n=scan();while((x=(1+n*T^2)^.5)%%1)T=T+1;x;+T

-1 -2 graças a @Giuseppe

-7 graças a @ Giuseppe e @Robin Ryder -2 @JAD


1
usar em .5vez de0.5
Giuseppe

5
46 bytes . Encontrar o menor valor de xé equivalente a encontrar o menor valor de y. Isso permite que você salve 2 bytes porque a expressão xem termos de yé mais curta do que o contrário e 4 bytes usando o truque de usar Tinicializado em 1.
Robin Ryder

1
@RobinRyder, você pode precisar de um +Tno final para garantir que quando y==1ele retornar, em 1vez de, TRUEmas eu não tenho certeza.
Giuseppe

3
@ Giuseppe Bem avistado! Você está certo. Isso torna 47 bytes
Robin Ryder

1
Parece falhar em n = 61 (o caso de teste grande e bobo) devido a problemas de grande número. Eu acho que é bom permitir limites de idioma, apenas observando a exceção.
CriminallyVulgar

3

Geléia , 40 bytes

½©%1İ$<®‘¤$п¹;Ḋ$LḂ$?Ḟṭ@ṫ-ṚZæ.ʋ¥ƒØ.,U¤-ị

Experimente online!

Uma resposta alternativa da Jelly, menos eficiente, mas mais eficiente quando algoritmos x e y são grandes. Ele encontra os convergentes da fração contínua regular que se aproxima da raiz quadrada de n e, em seguida, verifica qual resolve a equação de Pell. Agora encontra corretamente o período da fração contínua regular.

Graças a @TimPederick, também implementei uma solução baseada em número inteiro que deve lidar com qualquer número:

Geléia , 68 bytes

U×_ƭ/;²®_$÷2ị$}ʋ¥µ;+®Æ½W¤:/$$
¹©Æ½Ø.;ÇƬṪ€F¹;Ḋ$LḂ$?ṭ@ṫ-ṚZæ.ʋ¥ƒØ.,U¤-ị

Experimente online!

Por exemplo, a solução para 1234567890 possui dígitos de 1936 e 1932 para o numerador e o denominador, respectivamente.


Agradável! Adotei a mesma abordagem na minha resposta. Eu não leio Jelly, então não sei por que você está tendo problemas com o 61. Você está armazenando cada convergente como um par de números inteiros (numerador e denominador)?
Tim Pederick 16/04

@TimPederick Sim. Não sei onde o problema surge
Nick Kennedy

Tentei aprender como isso funciona para que eu pudesse ajudar na depuração, mas não consegui entender! A única coisa que posso sugerir é tomar a palavra de quaisquer carros alegóricos, uma vez que (se isso faz usar o mesmo algoritmo como o meu) todos os valores intermediários deve sair como inteiros de qualquer maneira.
Tim Pederick 17/04

@TimPederick Era imprecisão de ponto flutuante. Agora fiz parar de procurar mais continuação da fração continuada, uma vez que atinge o período. Isso funciona até 150, mas, acima disso, acho que de novo encontro erros de precisão de ponto flutuante em, por exemplo, 151
Nick Kennedy

@ TimPederick também é problemática a geração da fração continuada, não os convergentes que são feitos com aritmética inteira.
Nick Kennedy

2

JavaScript (ES7), 47 bytes

n=>(g=x=>(y=((x*x-1)/n)**.5)%1?g(x+1):[x,y])(2)

Experimente online!

Abaixo está uma versão alternativa de 49 bytes, que monitora diretamente em vez de esquadrinhar a cada iteração:x²1x

n=>[(g=x=>(y=(x/n)**.5)%1?1+g(x+=k+=2):2)(k=3),y]

Experimente online!

Ou podemos seguir o caminho não recursivo por 50 bytes :

n=>eval('for(x=1;(y=((++x*x-1)/n)**.5)%1;);[x,y]')

Experimente online!


2

TI-BASIC,  44  42 41 bytes

Ans→N:"√(N⁻¹(X²-1→Y₁:1→X:Repeat not(fPart(Ans:X+1→X:Y₁:End:{X,Ans

Entrada é . Saída é uma lista cujos valores correspondem a .n
(x,y)

Usa a equação para para calcular a solução fundamental. O par atual para essa equação é uma solução fundamental se .y=x21nx2
(x,y)ymod1=0

Exemplos:

6
               6
prgmCDGF12
           {5 2}
10
              10
prgmCDGF12
          {19 6}
13
              13
prgmCDGF12
       {649 180}

Explicação:

Ans→N:"√(N⁻¹(X²+1→Y₁:1→X:Repeat not(fPart(Ans:X+1→X:Y₁:End:{X,Ans  ;full logic

Ans→N                                                              ;store the input in "N"
      "√(N⁻¹(X²+1→Y₁                                               ;store the aforementioned
                                                                   ; equation into the first
                                                                   ; function variable
                     1→X                                           ;store 1 in "X"
                         Repeat not(fPart(Ans          End         ;loop until "Ans" is
                                                                   ; an integer
                                              X+1→X                ;increment "X" by 1
                                                    Y₁             ;evaluate the function
                                                                   ; stored in this variable
                                                                   ; at "X" and leave the
                                                                   ; result in "Ans"
                                                           {X,Ans  ;create a list whose
                                                                   ; values contain "X" and
                                                                   ; "Ans" and leave it in
                                                                   ; "Ans"
                                                                   ;implicitly print "Ans"

Nota: TI-BASIC é um idioma tokenizado. Contagem de caracteres não é igual à contagem de bytes.


2

MATL , 17 bytes

`@:Ut!G*-!1=&fts~

Experimente online!

Explicação

O código continua aumentando um contador k = 1, 2, 3, ... Para cada k , as soluções x , y com 1 ≤ xk , 1 ≤ yk são pesquisadas. O processo quando alguma solução for encontrada.

Esse procedimento é garantido para encontrar apenas uma solução, que é precisamente a fundamental. Para ver o porquê, observe que

  1. Qualquer solução x > 0, y > 0 para n > 1 satisfaz x > y .
  2. Se x , y é uma solução ex ', y ' é uma solução diferente, então necessariamente xx ' e yy '.

Como conseqüência de 1 e 2,

  • Quando o procedimento para em um determinado k , existe apenas uma solução para esse k , porque se houvesse duas soluções, uma delas seria encontrada anteriormente e o processo teria parado com um k menor .
  • Essa solução é fundamental, porque, novamente, se houvesse uma solução com x menor, ela teria sido encontrada anteriormente.

`       % Do...while
  @:U   %   Push row vector [1^2, 2^2, ..., k^2] where k is the iteration index
  t!    %   Duplicate and transpose. Gives the column vector [1^2; 2^2; ...; k^2]
  G*    %   Multiply by input n, element-wise. Gives [n*1^2; n*2^2; ...; n*k^2]
  -     %   Subtract with broadcast. Gives a square matrix of size n
  !     %   Transpose, so that x corresponds to row index and y to column index
  1=&f  %   Push row and column indices of all entries that equal 1. There can
        %   only be (a) zero such entries, in which case the results are [], [],
        %   or (b) one such entry, in which case the results are the solution x, y
  ts~   %   Duplicate, sum, negate. This gives 1 in case (a) or 0 in case (b)
        % End (implicit). Proceed with next iteration if top of the stack is true;
        % that is, if no solution was found.
        % Display (implicit). The stack contains copies of [], and x, y on top.
        % The empty array [] is not displayed

2

Python 2 , 49 bytes

a=input()**.5
x=2
while x%a*x>1:x+=1
print x,x//a

Experimente online!

Encontra xcomo o menor número acima de 1 em que x % sqrt(n) <= 1/x. Então, encontra yde xcomo y = floor(x / sqrt(n)).


2

Haskell , 46 bytes

Uma busca direta por força bruta. Isso faz uso do fato de que uma solução fundamental satisfaz deve ter .(x,y)x2ny2=1yx

f n=[(x,y)|x<-[1..],y<-[1..x],x^2-n*y^2==1]!!0

Experimente online!


Parece que você precisa mudar npara xin y<-[1..n]para poder calcular f 13.
Christian Sievers

@ChristianSievers Obrigado por apontar, eu o corrigi!
flawr 26/07



1

Casca , 12 bytes

ḟΛ¤ȯ=→*⁰□π2N

Experimente online!

Explicação

ḟΛ¤ȯ=→*⁰□π2N  Input is n, accessed through ⁰.
           N  Natural numbers: [1,2,3,4,..
         π2   2-tuples, ordered by sum: [[1,1],[1,2],[2,1],[1,3],[2,2],..
ḟ             Find the first that satisfies this:
 Λ             All adjacent pairs x,y satisfy this:
  ¤     □       Square both: x²,y²
   ȯ  *⁰        Multiply second number by n: x²,ny²
     →          Increment second number: x²,ny²+1
    =           These are equal.

1

MathGolf , 12 bytes

ökî²*)_°▼Þ√î

Experimente online!

Estou jogando uma Ave Maria quando se trata da formatação de saída. Se não for permitido, tenho uma solução com 1 byte a mais. O formato de saída é x.0yonde .0está o separador entre os dois números.

Explicação

ö       ▼      do-while-true with popping
 k             read integer from input
  î²           index of current loop (1-based) squared
    *          multiply the two
     )         increment (gives the potential x candidate
      _        duplicate TOS
       °       is perfect square
         Þ     discard everything but TOS
          √    square root
           î   index of previous loop (1-based)

Eu me inspirei na resposta 05AB1E de Emigna, mas consegui encontrar algumas melhorias. Se o separador escolhido não for permitido, adicione um espaço antes do último byte para uma contagem de 13 bytes.


1

APL (NARS), 906 bytes

r←sqrti w;i;c;m
m←⎕ct⋄⎕ct←0⋄r←1⋄→3×⍳w≤3⋄r←2⋄→3×⍳w≤8⋄r←w÷2⋄c←0
i←⌊(2×r)÷⍨w+r×r⋄→3×⍳1≠×r-i⋄r←i⋄c+←1⋄→2×⍳c<900⋄r←⍬
⎕ct←m

r←pell w;a0;a;p;q2;p2;t;q;P;P1;Q;c;m
   r←⍬⋄→0×⍳w≤0⋄a0←a←sqrti w⋄→0×⍳a≡⍬⋄m←⎕ct⋄⎕ct←0⋄Q←p←1⋄c←P←P1←q2←p2←0⋄q←÷a
L: t←p2+a×p⋄p2←p⋄p←t
   t←q2+a×q
   :if c≠0⋄q2←q⋄:endif
   q←t           
   P←(a×Q)-P
   →Z×⍳Q=0⋄Q←Q÷⍨w-P×P
   →Z×⍳Q=0⋄a←⌊Q÷⍨a0+P
   c+←1⋄→L×⍳(1≠Qׯ1*c)∧c<10000
   r←p,q
   :if c=10000⋄r←⍬⋄:endif
Z: ⎕ct←m

Acima, existem 2 funções sqrti função que iria encontrar a função de raiz e Pell quadrado chão voltaria Zilde para erro, e baseia-se ler a página http://mathworld.wolfram.com/PellEquation.html seria usar a algo para saber a sqrt de um número trhu continue a fração (mesmo se eu usar um algo para saber sqrt usando o método newton) e pare quando encontrar p e q de modo que

 p^2-w*q^2=1=((-1)^c)*Qnext

Teste:

  ⎕fmt pell 1x
┌0─┐
│ 0│
└~─┘
  ⎕fmt pell 2x
┌2───┐
│ 3 2│
└~───┘
  ⎕fmt pell 3x
┌2───┐
│ 2 1│
└~───┘
  ⎕fmt pell 5x
┌2───┐
│ 9 4│
└~───┘
  ⎕fmt pell 61x
┌2────────────────────┐
│ 1766319049 226153980│
└~────────────────────┘
  ⎕fmt pell 4x
┌0─┐
│ 0│
└~─┘
  ⎕fmt pell 7373x
┌2───────────────────────────────────────────────────────────┐
│ 146386147086753607603444659849 1704817376311393106805466060│
└~───────────────────────────────────────────────────────────┘
  ⎕fmt pell 1000000000000000000000000000002x
┌2────────────────────────────────────────────────┐
│ 1000000000000000000000000000001 1000000000000000│
└~────────────────────────────────────────────────┘

Existe um limite para ciclos no loop na função sqrti e um limite para ciclos no loop na função Pell, ambos para o número possível de casos são muito grandes ou algo não converge ... (não sei se o sqrti convergem todas as entradas possíveis e a mesma função Pell também)



0

Pitão, 15 bytes

fsIJ@ct*TTQ2 2J

Experimente online aqui . A saída é xentão yseparada por uma nova linha.


0

Wolfram Language (Mathematica) , 41 bytes

{1//.y_/;!NumberQ[x=√(y^2#+1)]:>y+1,x}&

é o caractere Unicode de 3 bytes # 221A. Emite a solução na ordem (y, x) em vez de (x, y). Como de costume com o imperfeito //.e suas iterações limitadas, funciona apenas em entradas em que o valor real de yé no máximo 65538.

Experimente online!


0

> <> , 45 bytes

11v
+$\~:1
:}/!?:-1v?=1-*}:{*:@:{*:
$  naon;>

Experimente online!

Algoritmo de força bruta, pesquisando de x=2cima para baixo , com y=x-1e diminuindo em cada loop, incrementando xquando yatingir 0. A saída é xseguida por y, separada por uma nova linha.



0

Python 3 , 75 bytes

lambda i:next((x,y)for x in range(2,i**i)for y in range(x)if~-x**2==i*y**2)

Experimente online!

Explicação

Força bruta. Usando como um limite superior de pesquisa, que está bem abaixo do limite superior definido da solução fundamental da equação de Pell

x<ii
xi!

Esse código também seria executado no Python 2. No entanto, a função range () no Python 2 cria uma lista em vez de um gerador como no Python 3 e, portanto, é imensamente ineficiente.


Com tempo e memória inifinte, pode-se usar uma compreensão de lista em vez do iterador e salvar 3 bytes da seguinte forma:

Python 3 , 72 bytes

lambda i:[(x,y)for x in range(i**i)for y in range(x)if~-x**2==i*y**2][1]

Experimente online!


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.