Obliczanie (3 + sqrt (5)) ^ n dokładnie


23

Dziś twoim celem jest znalezienie liczby całkowite a i b daną liczbę całkowitą nieujemną n takie, że:

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

Należy napisać program lub funkcję, która przyjmuje parametr n i wyjść i B w formacie do wyboru.

Obowiązują standardowe luki. Ponadto zamierzone jest samodzielne wdrożenie powyższego problemu za pomocą podstawowej arytmetyki. Dlatego nie możesz używać wbudowanej funkcji algebry dokładnej, wymiernych ani funkcji implementujących nietrywialne konstrukcje matematyczne (na przykład sekwencję Lucas ).

Najkrótszy kod w bajtach wygrywa.


Przykładowe wejście / wyjście:

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

Odpowiedzi:


3

Dyalog APL, 18 bajtów

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

Jest to program, który pobiera dane wejściowe .

 (         )         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)

Zastosowane tutaj funkcje zostały wdrożone na długo przed kwietniem 2015 r., Dzięki czemu ta odpowiedź jest ważna.

Wypróbuj tutaj . Pamiętaj, że tryapl.org jest ograniczonym podzbiorem Dyalog i nie obsługuje .


16

Oktawa, 26 bajtów

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

Ponieważ ( a + b * sqrt (5)) * (3 + sqrt (5)) = ( 3a + 5b ) + ( a + 3b ) * sqrt (5),

pomnożenie wektora wejściowego

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

co oznacza 1 = (3 + sqrt (5)) ^ 0 według macierzy

| 3 5 |
| 1 3 |

wydaje się naturalne. Zamiast nczasów zapętlania , raczej podnosimy macierz do potęgi, na następnie mnożymy ją przez wektor wejściowy.


Sprzedajesz się krótko, [3 5;1 3]**input('')*[1;0]ma 26 bajtów, a nie 41.
lub

3
@(n)[3 5;1 3]^n*[1;0](uchwyt funkcji) pozwoliłby ci zaoszczędzić pięć znaków, mut fajny pomysł!
flawr

14

Python 2, 50

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

Mnoży się 3+sqrt(5)wielokrotnie przez działanie na (a,b)reprezentującą parę a+b*sqrt(5). Równoważne do rozpoczęcia od wektora kolumny [1,0]i nczasów pomnożenia w lewo przez macierz [[3,5],[1,3]].


12

Julia, 22 20 bajtów

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

Tworzy to funkcję lambda, która przyjmuje na wejściu pojedynczą liczbę całkowitą i zwraca 2-elementowy wektor liczb całkowitych odpowiadający rozwiązaniu [a, b]. Aby to nazwać, nadaj mu nazwę, np f=n->....

Zacznij od pomnożenia

Początkowe rozwinięcie

Następnie możemy przetłumaczyć prawą stronę tego równania na macierz 2-kolumnową, gdzie pierwsza odpowiada współczynnikowi a, a druga współczynnikowi b :

Matryca

Pomnóż tę macierz sama n razy, a następnie pomnóż w prawo przez wektor kolumny (1, 0) i POOF! Wyskakuje wektor rozwiązania.

Przykłady:

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

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

8

J, 20 bajtów

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

Pomnóż wektor [1 0]przez [[3 5] [1 3]] nczasy macierzy .

2 bajty zapisane dzięki @al algorytmshark.

Zastosowanie i 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

Można zejść do 20 wykorzystując milczącą przysłówek parsowania: +/ .*(3 5,:1 3&)&1 0.
algorytmshark

@al algorytmshark Dzięki, chociaż dlaczego (+/@:*&(3 5,.1 3)&1 0)działa, a (+/@:*&1 0&(3 5,.1 3))nie? Czy drugie nie powinno być prawidłowo połączone, a pierwsze zamienione?
randomra

Rozumiem, łączą się tak, jak się spodziewałem, ale zewnętrzne &powoduje zasilanie / zapętlenie, więc modyfikujesz wejście po lewej stronie podczas zasilania (przeciwnie do normalnej modyfikacji po prawej stronie).
randomra

7

Pyth, 20 bajtów

u,+*3sGyeG+sGyeGQ,1Z

uktóry jest ogólnie redukowany, jest tutaj stosowany jako pętla powtarzania zastosowania. Funkcja aktualizacji to G-> ,+*3sGyeG+sGyeG, gdzie Gjest 2 krotki. Ta funkcja przekłada się na 3*sum(G) + 2*G[1], sum(G) + 2*G[1]. sjest sum, yjest *2.


Wybrałem odpowiedź @ randomra ponad twoją, ponieważ jego / jej została opublikowana 16 minut wcześniej, przepraszam.
orlp

5

APL (22)

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

Wyjaśnienie:

  • {... }⍣⎕⍨2↑1: przeczytaj liczbę i uruchom następującą funkcję wiele razy, używając [1,0]jako danych wejściowych.
    • 2 2⍴3 5 1: macierz [[3,5],[1,3]]
    • ⍵+.×⍨: pomnóż pierwszą liczbę w ⍵ przez 3, drugą przez 5, i zsumuj je, to jest nowa pierwsza liczba; następnie pomnóż pierwszą liczbę w ⍵ przez 1, drugą przez 3 i zsumuj te, czyli nową drugą liczbę.

1
Awww yiss, APL.
Nit

5

Galaretka , 13 bajtów

5W×U++Ḥ
2Bdz¡

Wypróbuj online!

Jak to działa

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.

Nie, jestem całkiem pewien, że Jelly była na długo przed stworzeniem Internetu: P
Conor O'Brien

1
@ Doᴡɴɢᴏᴀᴛ W przypadku niekonkurencyjnych odpowiedzi wolę utrzymywanie liczby bajtów w drugiej linii. To powstrzymuje odpowiedź od awansowania na szczyt w rankingach i skryptach użytkowników, co wydaje się niesprawiedliwe.
Dennis


3

CJam, 21 bajtów

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

Wypróbuj online.

Jak to działa

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 bajtów

Korzystam z rekurencyjnej oceny dwumianu: (x + y) ^ n = (x + y) (x + y) ^ {n-1}

Nowość (dzięki @ edc65)

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

Stary

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

1
Może warto rozważyć edycję formuły. Nie mamy już MathJax.
Alex A.,

Myślałem, że to właśnie zostało wprowadzone kilka dni temu?
flawr

Tak, ale zawiodło fragmenty stosu, więc trzeba było je wyłączyć.
Alex A.,

Liczę 63 jak jest i można je skrócić do 61F=n=>{for(i=y=0,x=1;i++<n;)[x,y]=[3*x+5*y,x+3*y];return[x,y]}
edc65 13.04.15

n=>[...Array(n)].map(_=>[x,y]=[3*x+5*y,x+3*y],y=0,x=1)[n-1]ta sama długość
l4m2

2

C, 114 bajtów

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]);}

To powoduje nudne mnożenie macierzy. Aby uzyskać więcej zabawy (cytat: „niesamowicie przerażający”) 238 bajtów, nie szukaj dalej!

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]);}

Rozpruty:

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]);
}

Prawdopodobnie można to nieco skrócić. Wypróbuj program testowy online !


1
Wykorzystuje się w tym dość skomplikowany algorytm: P
orlp

@orlp Nie mogłem wymyślić krótszego algorytmu dla tego języka. Myślałem, że to się uda, ale to wymknęło się spod kontroli, haha. Ręczne wdrożenie mnożenia macierzy może być krótsze.
BrainSteel

1
Głosuj, ponieważ jest to niesamowicie przerażające.
kirbyfan64sos

2

k2 - 22 znak

Funkcja przyjmująca jeden argument.

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

_muljest mnożenie macierzy więc curry go z matrycy (3 5;1 3), a następnie uderzył go z funkcjonalnej mocy przysłówek: f/[n;x]stosuje fsię x, nczasy. Ponownie curry, tym razem z wektorem początkowym 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)

To nie zadziała w Kona, ponieważ z jakiegoś powodu f/[n;x]nie jest poprawnie zaimplementowane. n f/xDziała tylko składnia, więc najkrótsza poprawka to {x _mul[(3 5;1 3)]/1 0}23 znaki.


Łał. To curry jest tak inteligentne, że wydaje mi się, że moja odpowiedź na K jest głupia. W każdym razie podniosłem problem, który znalazłeś w Kona na ich narzędziu do śledzenia błędów .
kirbyfan64sos


2

ised, 25 bajtów (20 znaków)

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

Miałem nadzieję, że będzie lepiej, ale jest po prostu zbyt wiele aparatów ortodontycznych potrzebnych, aby uczynić go kompetentnym, priorytet operatorów nie jest optymalny do gry w golfa.

Oczekuje, że wejście znajdzie się w gnieździe pamięci o wartości 1 USD, więc działa to:

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

Dla n = 0 zero jest pomijane (wyjścia 1, zamiast 1 0). Jeśli to problem, wymień ostateczna 1z ~[2].


2

Poważnie, 32 bajty, niekonkurujące

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

Hex Dump:

2cbb34332f313260bd223b2940342af728362a2d229c6e2e58348df130606e7f

Wypróbuj Onlline

Oczywiście nie jest to zawodnik najkrócej, ale przynajmniej metoda jest oryginalna. (Zwracając uwagę, że taki problem niekoniecznie wskazuje sekwencję Lucas, jak wspomniano w opisie, ten program generuje kolejne terminy sekwencji przy użyciu relacji powtarzalności

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


1

Haskell, 41 bajtów

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

Przykład użycia: (iterate(\(a,b)->(3*a+5*b,a+3*b))(1,0)!!) 8-> (282496,126336).


1

C / C ++ 89 bajtów

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;}}

Sformatowany:

    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;
}}

Ta sama koncepcja:

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;
}

Stanowisko testowe:

#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;
}

Wyjście:

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

Witamy na stronie i fajna pierwsza odpowiedź!
DJMcMayhem

0

K, 37 bajtów

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

lub

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

Oba są tym samym.


0

Python 3, 49 bajtów

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

chociaż na mojej maszynie daje to tylko prawidłową odpowiedź dla danych wejściowych w zakresie 0 <= n <= 18.

To implementuje formułę formularza zamkniętego

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

i wykorzystuje fakt, że v ** nczęść jest niewielka i można ją obliczyć raczej zaokrąglając niż bezpośrednio.


1
To nie jest poprawne rozwiązanie (musisz wesprzeć dowolne n ), ale ponieważ nie jesteś wcale najkrótszy, nie widzę powodu, aby głosować negatywnie. To fajne rozwiązanie.
orlp

0

Schemat, 97 bajtów

(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 bajtów (60 ze wstępnie zainicjalizowanymi zmiennymi)

Możliwości gry w golfa, ale tylko po to, aby udowodnić, że C nie musi być „strasznie przerażający”.

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);}

Jeśli wartości w a są inicjalizowane na {1,0}, robimy to lepiej.

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

Jest to iteracyjnie użycie odwzorowań a-> 3a + 5b, b-> a + 3b, ale unikanie zmiennej tymczasowej poprzez obliczenie a na podstawie nowej wartości b.


Twoje rozwiązanie przepełnia liczby całkowite dla dużych danych wejściowych :)
lub

@orlp - To C dla ciebie. Przyznaję, że to rozwiązanie zawodzi wcześniej niż inne z powodu tymczasowego obliczenia w nawiasach, ale i tak wykonałby tylko kilka dodatkowych kroków, chyba że zmienię typ danych. Czy warto wyraźnie zmienić pytanie, aby podać zakres, który ma być obsługiwany? Prawdopodobnie za późno.
Alchymist

Nie ma zakresu obsługiwanego, właściwe rozwiązanie powinno działać dla każdego wejścia. W C oznacza to, że będziesz musiał zaimplementować liczby całkowite o dowolnej szerokości, przepraszam = /
orlp 14.04.15

Sugerować a[*a=1]=0 zamiast*a=1,a[1]=0
ceilingcat

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.