Calcolo (3 + sqrt (5)) ^ n esattamente


23

Oggi il vostro obiettivo è quello di trovare numeri interi a e b dato intero non negativo n tale che:

(3 + sqrt (5)) ^ n = a + b * sqrt (5)

Si dovrebbe scrivere un programma o una funzione che prende il parametro n ed emette un e b in un formato di vostra scelta.

Si applicano scappatoie standard. Inoltre, si intende implementare il problema sopra usando te stesso l'aritmetica di base. Quindi non è possibile utilizzare funzionalità algebriche esatte incorporate, razionali o funzioni che implementano costrutti matematici non banali (ad esempio la sequenza di Lucas ).

Vince il codice più breve in byte.


Esempio di input / output:

0 → 1, 0
1 → 3, 1
2 → 14, 6
3 → 72, 32
4 → 376, 168
5 → 1968, 880
6 → 10304, 4608
7 → 53952, 24128
8 → 282496, 126336
9 → 1479168, 661504

Risposte:


3

Dyalog APL, 18 byte

((3∘×+5 1×⌽)⍣⎕)1 0

Questo è un programma che accetta input .

 (         )         Monadic train:
  3∘×                3 times argument
     +               Plus
      5 1×⌽          (5 1) times the reverse
(           ⍣⎕)      Apply that function (input) times
               1 0   starting with (1 0)

Le funzionalità utilizzate qui sono state implementate molto prima di aprile 2015, rendendo valida questa risposta.

Provalo qui . Si noti che tryapl.org è un sottoinsieme limitato di Dyalog e non supporta .


16

Ottava, 26 byte

[3 5;1 3]**input('')*[1;0]

Perché ( a + b * sqrt (5)) * (3 + sqrt (5)) = ( 3a + 5b ) + ( a + 3b ) * sqrt (5),

moltiplicando il vettore di input

| 1 |    /* a = 1 */
| 0 |    /* b = 0 */

che sta per 1 = (3 + sqrt (5)) ^ 0 per matrice

| 3 5 |
| 1 3 |

sembra naturale. Invece di ntempi di ciclo , piuttosto eleviamo la matrice alla potenza di ne quindi la moltiplichiamo per il vettore di input.


Ti stai vendendo a corto, [3 5;1 3]**input('')*[1;0]è di 26 byte, non 41.
orlp

3
@(n)[3 5;1 3]^n*[1;0](handle di funzione) ti salverebbe cinque personaggi, mut bella idea!
flawr,

14

Python 2, 50

a=1;b=0
exec"a,b=3*a+5*b,3*b+a;"*input()
print a,b

Si moltiplica 3+sqrt(5)ripetutamente per la sua azione sulla coppia che (a,b)rappresenta a+b*sqrt(5). Equivale a iniziare con il vettore della colonna [1,0]e moltiplicare a sinistra i ntempi per la matrice [[3,5],[1,3]].


12

Julia, 22 20 byte

n->[3 5;1 3]^n*[1;0]

Questo crea una funzione lambda che accetta un singolo intero come input e restituisce un vettore a 2 elementi di numeri interi corrispondente alla soluzione [a, b]. Per chiamarlo, dagli un nome, ad es f=n->....

Inizia moltiplicando

Espansione iniziale

Possiamo quindi tradurre il lato destro di questa equazione in una matrice a 2 colonne, dove la prima corrisponde al coefficiente di a e la seconda al coefficiente di b :

Matrice

Moltiplica questa matrice per se stessa n volte, quindi moltiplica a destra per il vettore colonna (1, 0) e POOF! Out apre il vettore della soluzione.

Esempi:

julia> println(f(0))
[1,0]

julia> println(f(5))
[1968,880]

8

J, 20 byte

+/@:*(3 5,.1 3&)&1 0

Moltiplicare il vettore [1 0]per i [[3 5] [1 3]] ntempi della matrice .

2 byte salvati grazie a @algorithmshark.

Utilizzo e test:

   (+/@:*(3 5,.1 3&)&1 0) 5
1968 880

   (+/@:*(3 5,.1 3&)&1 0) every i.6
   1   0
   3   1
  14   6
  72  32
 376 168
1968 880

È possibile ottenere fino a 20 sfruttando tacita avverbio analisi: +/ .*(3 5,:1 3&)&1 0.
algoritmo

@algorithmshark Grazie, anche se perché (+/@:*&(3 5,.1 3)&1 0)funziona e (+/@:*&1 0&(3 5,.1 3))no? Il secondo non dovrebbe legare correttamente e il primo scambiato?
randomra,

Capito, si legano come mi aspettavo, ma l'esterno &fa il powering / looping in modo da modificare l'ingresso del lato sinistro durante l'alimentazione (opposto alla normale modifica del lato destro).
randomra,

7

Pyth, 20 byte

u,+*3sGyeG+sGyeGQ,1Z

uche è generalmente ridotto, viene utilizzato qui come un ciclo di applicazione ripetuta. La funzione di aggiornamento è G-> ,+*3sGyeG+sGyeG, dove Gè una tupla 2. Questa funzione si traduce in 3*sum(G) + 2*G[1], sum(G) + 2*G[1]. sè sum, yè *2.


Ho scelto la risposta di @ randomra alla tua perché la sua è stata pubblicata 16 minuti prima, scusa.
orlp,

5

APL (22)

{⍵+.×⍨2 2⍴3 5 1}⍣⎕⍨2↑1

Spiegazione:

  • {... }⍣⎕⍨2↑1: leggi un numero ed esegui la seguente funzione più volte, usando [1,0]come input iniziale.
    • 2 2⍴3 5 1: la matrice [[3,5],[1,3]]
    • ⍵+.×⍨: moltiplica il primo numero in ⍵ per 3, il secondo per 5 e sommali, questo è il nuovo primo numero; quindi moltiplica il primo numero in ⍵ per 1, il secondo per 3 e somma quelli, ovvero il nuovo secondo numero.

1
Awww yiss, APL.
Nit

5

Gelatina , 13 byte

5W×U++Ḥ
2Bdz¡

Provalo online!

Come funziona

5W×U++Ḥ    Helper link. Argument: [a, b]

5W         Yield [5].
  ×U       Multiply it by the reverse of [a, b]. This yields [5b, a].
    +      Hook; add the argument to the result. This yields [a + 5b, a + b].
     +Ḥ    Fork; add the doubled argument ([2a, 2b]) to the result.
           This yields [3a + 5b, a + 3b].

2Bdz¡      Main link. Argument: n

2B         Convert 2 to binary, yielding [1, 0].
    ¡      Repeat:
  Ç            Apply the helper link...
   ³           n times.

No, sono abbastanza sicuro che Jelly fosse molto tempo prima della creazione di Internet: P
Conor O'Brien,

1
@ Doᴡɴɢᴏᴀᴛ Per le risposte non concorrenti, preferisco mantenere il conteggio dei byte sulla seconda riga. Ciò evita che la risposta salga in cima alle classifiche e agli script utente, il che sembra ingiusto.
Dennis,


3

CJam, 21 byte

0X{_2$3*+@5*@3*+}li*p

Provalo online.

Come funziona

0X       " Stack: [ 0 1 ]                                ";
li{      " Do int(input()) times:                        ";
  _2$    " Stack: [ a b ] -> [ a b b a ]                 ";
  3*+    " Stack: [ a b b a ] -> [ a b (b+3a) ]          ";
  @5*@3* " Stack: [ a b (b+3a) ] -> [ (b+3a) 5a 3b ]     ";
  +      " Stack: [ (b+3a) 5a 3b ] -> [ (b+3a) (5a+3b) ] ";
}*       "                                               ";
p        " Print topmost stack item plus linefeed.       ";
         " Print remaining stack item (implicit).        ";

3

Javascript, 63 61 byte

Sto usando una valutazione ricorsiva del binomio: (x + y) ^ n = (x + y) (x + y) ^ {n-1}

Novità (grazie a @ edc65)

F=n=>{for(i=y=0,x=1;i++<n;)[x,y]=[3*x+5*y,x+3*y];return[x,y]}

Vecchio

F=n=>{for(i=y=0,x=1;i<n;i++)[x,y]=[3*x+5*y,x+3*y];return [x,y]}

1
Potrebbe voler prendere in considerazione la modifica della formula. Non abbiamo più MathJax.
Alex A.

Pensavo fosse appena stato introdotto pochi giorni fa?
flawr,

Sì, ma ha incasinato i frammenti dello stack, quindi ha dovuto essere disabilitato.
Alex A.

Conto 63 com'è, e posso essere ridotto a 61F=n=>{for(i=y=0,x=1;i++<n;)[x,y]=[3*x+5*y,x+3*y];return[x,y]}
edc65

n=>[...Array(n)].map(_=>[x,y]=[3*x+5*y,x+3*y],y=0,x=1)[n-1]stessa lunghezza
l4m2

2

C, 114 byte

g(n){int i,a[2]={1,0},b[2];for(i=0;i<n;i++)*b=*a*3+5*a[1],b[1]=*a+3*b[1],*a=*b,a[1]=b[1];printf("%d,%d",*a,a[1]);}

Questo implementa la moltiplicazione della matrice in modo noioso. Per una soluzione più divertente (citazione: "tremendamente orribile") da 238 byte, non cercate oltre!

f(n){int p[2][n+3],i,j,k=0,a[2]={0};for(j=0;j<n+3;j++)p[0][j]=0;*p[1]=0;(*p)[1]=1;for(j=0;j<n;j++,k=!k)for(i=1;i<n+3;i++)p[!k][i]=p[k][i-1]+p[k][i];for(i=1;i<n+2;i++)a[!(i%2)]+=p[k][i]*pow(3,n+1-i)*pow(5,(i-1)/2);printf("%d,%d",*a,a[1]);}

svelato:

g(n){
    int i,a[2]={1,0},b[2];
    for(i=0;i<n;i++)
        *b=3**a+5*a[1],b[1]=*a+3*b[1],*a=*b,a[1]=b[1];
    printf("%d,%d",*a,a[1]);
}

Questo potrebbe probabilmente essere abbreviato un po '. Prova un programma di test online !


1
Questo utilizza un algoritmo piuttosto complicato: P
orlp,

@orlp Non riuscivo a pensare a un algoritmo più breve per questa lingua. Pensavo che questo avrebbe funzionato, ma in qualche modo è sfuggito di mano, ahah. L'implementazione manuale della moltiplicazione delle matrici potrebbe essere molto più breve.
BrainSteel,

1
Voto perché questo è tremendamente orribile.
kirbyfan64sos,

2

k2 - 22 caratteri

Funzione che accetta un argomento.

_mul[(3 5;1 3)]/[;1 0]

_mulè la moltiplicazione della matrice, quindi la valutiamo con la matrice (3 5;1 3)e quindi la colpiamo con l'avverbio di potenza funzionale: si f/[n;x]applica fa x, nvolte. Ancora una volta lo curry, questa volta con il vettore iniziale 1 0.

  _mul[2 2#3 5 1]/[;1 0] 5
1968 880
  f:_mul[2 2#3 5 1]/[;1 0]
  f'!8  /each result from 0 to 7 inclusive
(1 0
 3 1
 14 6
 72 32
 376 168
 1968 880
 10304 4608
 53952 24128)

Questo non funzionerà in Kona, perché per qualche motivo f/[n;x]non è implementato correttamente. n f/xFunziona solo la sintassi, quindi la correzione più breve è {x _mul[(3 5;1 3)]/1 0}a 23 caratteri.


Wow. Questo uso del curry è così intelligente che mi sembra che la mia risposta K sia stupida. Comunque, ho sollevato il problema che hai trovato in Kona sul loro bug tracker .
Kirbyfan64sos,


2

ised, 25 byte (20 caratteri)

({:{2,4}·x±Σx:}$1)∘1

Speravo di meglio, ma ci sono troppe parentesi necessarie per renderlo competente, la precedenza dell'operatore non è ottimale per il golf.

Si aspetta che l'ingresso sia nello slot di memoria $ 1, quindi funziona:

ised '@1{9};' '({:{2,4}·x±Σx:}$1)∘1'

Per n = 0, lo zero viene ignorato (uscite 1, anziché 1 0). Se questo è un problema, sostituisci il finale 1con ~[2].


2

Scherzi a parte, 32 byte, non concorrenti

,╗43/12`╜";)@4*≈(6*-"£n.X4ì±0`n

Dump esadecimale:

2cbb34332f313260bd223b2940342af728362a2d229c6e2e58348df130606e7f

Provalo online

Ovviamente non è un contendente per i più brevi, ma almeno il metodo è originale. (Notando che un tale problema indica necessariamente una sequenza di Lucas, come menzionato nella descrizione, questo programma genera termini successivi delle sequenze usando la relazione di ricorrenza

a_n = 6 * a_ {n-1} - 4 * a_ {n-2}.)


1

Haskell, 41 byte

(iterate(\(a,b)->(3*a+5*b,a+3*b))(1,0)!!)

Esempio di utilizzo: (iterate(\(a,b)->(3*a+5*b,a+3*b))(1,0)!!) 8-> (282496,126336).


1

C / C ++ 89 byte

void g(int n,long&a,long&b){if(n){long j,k;g(n-1,j,k);a=3*j+5*k;b=j+3*k;}else{a=1;b=0;}}

formattato:

    void g(int n, long&a, long&b) {
if (n) {
    long j, k;
    g(n - 1, j, k);
    a = 3 * j + 5 * k;
    b = j + 3 * k;
} else {
    a = 1;
    b = 0;
}}

Stesso concetto:

void get(int n, long &a, long& b) {
    if (n == 0) {
        a = 1;
        b = 0;
        return;
    }
    long j, k;
    get(n - 1, j, k);
    a = 3 * j + 5 * k;
    b = j + 3 * k;
}

Il banco prova:

#include <iostream>
using namespace std;    
int main() {
    long a, b;
    for (int i = 0; i < 55; i++) {
        g(i, a, b);
        cout << i << "-> " << a << ' ' << b << endl;
    }
    return 0;
}

L'output:

0-> 1 0
1-> 3 1
2-> 14 6
3-> 72 32
4-> 376 168
5-> 1968 880
6-> 10304 4608
7-> 53952 24128
8-> 282496 126336
9-> 1479168 661504
10-> 7745024 3463680
11-> 40553472 18136064
12-> 212340736 94961664
13-> 1111830528 497225728
14-> 5821620224 2603507712
15-> 30482399232 13632143360
16-> 159607914496 71378829312
17-> 835717890048 373744402432
18-> 4375875682304 1956951097344
19-> 22912382533632 10246728974336
20-> 119970792472576 53652569456640
21-> 628175224700928 280928500842496
22-> 3289168178315264 1470960727228416
23-> 17222308171087872 7702050360000512
24-> 90177176313266176 40328459251089408
25-> 472173825195245568 211162554066534400
26-> 2472334245918408704 1105661487394848768

Benvenuti nel sito e bella prima risposta!
DJMcMayhem

0

K, 37 byte

f:{:[x;*(1;0)*_mul/x#,2 2#3 1 5;1 0]}

o

f:{:[x;*(1;0)*_mul/x#,(3 1;5 3);1 0]}

Sono entrambi la stessa cosa.


0

Python 3, 49 byte

w=5**0.5;a=(3+w)**int(input())//2+1;print(a,a//w)

anche se sulla mia macchina, questo dà solo la risposta corretta per gli input nella gamma 0 <= n <= 18.

Questo implementa la formula in forma chiusa

w = 5 ** 0.5
u = 3 + w
v = 3 - w
a = (u ** n + v ** n) / 2
b = (u ** n - v ** n) / (2 * w)

e sfrutta il fatto che la v ** nparte è piccola e può essere calcolata arrotondando anziché mediante il calcolo diretto.


1
Questa non è una soluzione valida (è necessario supportare qualsiasi n ), ma dal momento che non sei affatto vicino a essere il più corto, non vedo un motivo per votare. È una soluzione interessante.
orlp,

0

Schema, 97 byte

(define(r n)(let s([n n][a 1][b 0])(if(= 0 n)(cons a b)(s(- n 1)(+(* a 3)(* b 5))(+ a(* b 3))))))

0

C 71 byte (60 con variabili preinizializzate)

Scopo del golf, ma solo per dimostrare che C non deve essere "tremendamente orribile".

f(int n,int*a){for(*a=1,a[1]=0;n--;a[1]=*a+3*a[1],*a=(5*a[1]+4**a)/3);}

Se i valori in a sono inizializzati su {1,0}, facciamo meglio.

f(int n,int*a){for(;n--;a[1]=*a+3*a[1],*a=(5*a[1]+4**a)/3);}

Questo utilizza iterativamente le mappature a-> 3a + 5b, b-> a + 3b ma evitando una variabile temporanea calcolando invece a dal nuovo valore di b.


La tua soluzione trabocca di numeri interi per input di grandi dimensioni :)
orlp

@orlp - Questo è C per te. Concesso questa soluzione non riesce prima di altre a causa del calcolo provvisorio tra parentesi ma gestirà comunque solo un paio di passaggi aggiuntivi a meno che non modifichi il tipo di dati. Vale la pena cambiare esplicitamente la domanda per fornire l'intervallo che ci si aspetta di supportare? Probabilmente è troppo tardi ora però.
Alchymist,

Non c'è intervallo da supportare, una soluzione adeguata dovrebbe funzionare per qualsiasi input. In C questo significa che dovrai implementare numeri di larghezza arbitrari, sorry = /
orlp

Suggerisci a[*a=1]=0invece di*a=1,a[1]=0
ceilingcat il

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.