Wygeneruj spiralę Padovan

34

Wprowadzenie

Podobnie jak Sekwencja Fibonacciego, Sekwencja Padovana ( OEIS A000931 ) jest sekwencją liczb, która jest wytwarzana przez dodanie poprzednich terminów w sekwencji. Początkowe wartości są zdefiniowane jako:

P(0) = P(1) = P(2) = 1

Warunki 0, 1 i 2 są wszystkie 1. Relacja powtarzalności jest podana poniżej:

P(n) = P(n - 2) + P(n - 3)

W ten sposób uzyskuje się następującą sekwencję:

1, 1, 1, 2, 2, 3, 4, 5, 7, 9, 12, 16, 21, 28, 37, 49, 65, 86, 114, 151, 200, 265, 351, ...

Używanie tych liczb jako długości boków trójkątów równobocznych daje fajną spiralę, gdy umieścisz je wszystkie razem, podobnie jak Spirala Fibonacciego:

wprowadź opis zdjęcia tutaj

Zdjęcie dzięki uprzejmości Wikipedia


Zadanie

Twoim zadaniem jest napisanie programu, który odtworzy tę spiralę za pomocą wyjścia graficznego, z danymi wejściowymi odpowiadającymi temu terminowi.

Zasady

  • Twoje zgłoszenie musi być w stanie obsłużyć co najmniej do 10. kadencji (9)
  • Twoje zgłoszenie musi być pełnym programem lub funkcją, która pobiera dane wejściowe i wyświetla wynik graficzny (wyświetla obraz lub wykresy itp.)
  • Musisz przedstawić dowód swojej grafiki w swoim zgłoszeniu
  • Dozwolone są obroty wyjścia, w wielokrotnościach 60 stopni, z tą samą reprezentacją
  • Dozwolone jest również poruszanie się w lewo
  • Standardowe luki są zabronione

Możesz założyć, że dane wejściowe będą> 0 i że podany zostanie prawidłowy format danych wejściowych.

Punktacja

To jest , więc wygrywa najkrótszy kod w bajtach. Szczęśliwego Nowego Roku wszystkim!

Andrew Li
źródło
Czy dozwolona jest spacja po wierszach?
Pavel
@Pavel Tak. Dodam, że
Andrew Li
Czy wynik musi być identyczny jak w przykładzie, czy też dozwolone są odbicia i obroty (wielokrotności 60 stopni)?
Level River St
@LevelRiverSt Pozwoliłbym na to. Pozwól mi wyjaśnić to w poście.
Andrew Li
3
Nie jest fanem dopuszczania zarówno grafiki ASCII, jak i grafiki w tym samym wyzwaniu. Są to bardzo różne zadania, a mieszanie ich razem sprawia, że ​​odpowiedzi rozwiązujące dwie różne możliwości są całkowicie nieporównywalne. Lepiej byłoby mieć dwa osobne wyzwania, jedno dla grafiki ASCII i jedno dla grafiki.
Martin Ender

Odpowiedzi:

12

Mathematica, 119 108 bajtów

Dzięki Martin Ender za uratowanie 11 bajtów!

±n_:=If[n<4,1,±(n-2)+±(n-3)];Graphics@Line@ReIm@Accumulate@Flatten@{0,z=I^(2/3),±# z^(#+{2,4,1})&~Array~#}&@

Nienazwana funkcja przyjmująca dodatni argument liczby całkowitej (indeksowany 1) i zwracająca wyjście grafiki. Przykładowe dane wyjściowe dla danych wejściowych 16:

wprowadź opis zdjęcia tutaj

Opracowany równolegle z odpowiedzią Matlaba na flawr, ale z wieloma podobieństwami w projekcie - nawet z definicją I^(2/3)szóstego pierwiastka jedności! Wersja łatwiejsza do odczytania:

1  (±n_:=If[n<4,1,±(n-2)+±(n-3)];
2   Graphics@Line@ReIm@
3   Accumulate@Flatten@
4   {0,z=I^(2/3),±# z^(#+{2,4,1})&~Array~#}
5  ])&

Wiersz 1 określa sekwencję Padovana ±n = P(n). Linia 4 tworzy zagnieżdżoną tablicę liczb zespolonych, definiujących zpo drodze; ostatnia część ±# z^(#+{2,4,1})&~Array~#generuje wiele trójek, z których każdy odpowiada wektorom, które musimy narysować, aby ukończyć odpowiedni trójkąt ( ±#kontroluje długość, a z^(#+{2,4,1})kontroluje kierunki). Wiersz 3 pozbywa się zagnieżdżania listy, a następnie oblicza sumy całkowite liczb zespolonych w celu konwersji z wektorów na czyste współrzędne; linia 2 następnie konwertuje liczby zespolone na uporządkowane pary liczb rzeczywistych i wysyła odpowiednią linię wielokąta.

Greg Martin
źródło
1
nieważne, ta część była po prostu głupia.
Martin Ender,
9

Matlab, 202 190 bajtów

N=input('');e=i^(2/3);f=1/e;s=[0,e,1,f,-e,e-2];l=[1,1,1,2];M=N+9;T=[l,2:M-3;2:M+1;3:M+2];for k=5:N;l(k)=l(k-2)+l(k-3);s(k+2)=s(k+1)+e*l(k);e=e*f;end;T=[T;T(1,:)];plot(s(T(:,1:N)));axis equal

Dane wyjściowe dla N=19(indeksowanie 1):

wprowadź opis zdjęcia tutaj

Wyjaśnienie

Szorstki pomysł polega zasadniczo na pracy ze liczbami zespolonymi. Wtedy krawędzie trójkątów zawsze wskazują kierunek szóstego pierwiastka jedności.

N=input('');                         % Fetch input
e=i^(2/3);                           % 6th root of unity
f=1/e;                               %  "
s=[0,e,1,f,-e,e-2];                  % "s" is a list of vertices in the order as the spiral is defined
l=[1,1,1,2];                         % "l" is a list of edge-lengths of the triangles
for k=5:N;                           % if we need more values in "l"/"s" we calculate those
    l(k)=l(k-2)+l(k-3);
    s(k+2)=s(k+1)+e*l(k);
    e=e*f;
end;
M=N+9;
T=[[1,1,1,2,2:M-3];2:M+1;3:M+2]';    % this matrix describes which vertices from s are needed for each triangle (the cannonical way how meshes of triangles are stored)
trimesh(T(1:N,:),real(s),imag(s));   % plotting the mesh, according to "T"
axis equal
wada
źródło
Dobra robota! Czy jest jakaś możliwość wyjaśnienia?
Andrew Li
wyjaśnienie dodane!
flawr
naprawdę podoba mi się tutaj stosowanie liczb zespolonych.
don bright
7

PHP + SVG, 738 bajtów

<?php
$a=[1,1,1];
for($i=0;$i<99;)$a[]=$a[$i]+$a[++$i];
$d=$e=$f=$g=$x=$y=0;
$c=[333,999];
$z="";
foreach($a as$k=>$v){
if($k==$_GET['n'])break;
$h=$v/2*sqrt(3);
if($k%6<1){$r=$x+$v/2;$s=$y+$h;$t=$r-$v;$u=$s;}
if($k%6==1){$r=$x-$v/2;$s=$y+$h;$t=$x-$v;$u=$y;}
if($k%6==2){$r=$x-$v;$s=$y;$t=$r+$v/2;$u=$y-$h;}
if($k%6==3){$r=$x-$v/2;$s=$y-$h;$t=$r+$v;$u=$s;}
if($k%6==4){$r=$x+$v/2;$s=$y-$h;$t=$r+$v/2;$u=$y;}
if($k%6>4){$r=$x+$v;$s=$y;$t=$r-$v/2;$u=$y+$h;}
$d=min([$d,$r,$t]);
$e=max([$e,$r,$t]);
$f=min([$f,$s,$u]);
$g=max([$g,$s,$u]); 
$p="M$x,{$y}L$r,{$s}L$t,{$u}Z";
$z.="<path d=$p fill=#{$c[$k%2]} />";
$x=$r;
$y=$s;
}
?>
<svg viewBox=<?="$d,$f,".($e-$d).",".($g-$f)?> width=100% height=100%>
<?=$z?>
</svg>

Wyjście dla 16

<svg viewBox=-53,-12.124355652982,75.5,42.435244785437 width=100% height=100%>
<path d=M0,0L0.5,0.86602540378444L-0.5,0.86602540378444Z fill=#333 /><path d=M0.5,0.86602540378444L0,1.7320508075689L-0.5,0.86602540378444Z fill=#999 /><path d=M0,1.7320508075689L-1,1.7320508075689L-0.5,0.86602540378444Z fill=#333 /><path d=M-1,1.7320508075689L-2,0L0,0Z fill=#999 /><path d=M-2,0L-1,-1.7320508075689L0,0Z fill=#333 /><path d=M-1,-1.7320508075689L2,-1.7320508075689L0.5,0.86602540378444Z fill=#999 /><path d=M2,-1.7320508075689L4,1.7320508075689L0,1.7320508075689Z fill=#333 /><path d=M4,1.7320508075689L1.5,6.0621778264911L-1,1.7320508075689Z fill=#999 /><path d=M1.5,6.0621778264911L-5.5,6.0621778264911L-2,-8.8817841970013E-16Z fill=#333 /><path d=M-5.5,6.0621778264911L-10,-1.7320508075689L-1,-1.7320508075689Z fill=#999 /><path d=M-10,-1.7320508075689L-4,-12.124355652982L2,-1.7320508075689Z fill=#333 /><path d=M-4,-12.124355652982L12,-12.124355652982L4,1.7320508075689Z fill=#999 /><path d=M12,-12.124355652982L22.5,6.0621778264911L1.5,6.0621778264911Z fill=#333 /><path d=M22.5,6.0621778264911L8.5,30.310889132455L-5.5,6.0621778264911Z fill=#999 /><path d=M8.5,30.310889132455L-28.5,30.310889132455L-10,-1.7320508075689Z fill=#333 /><path d=M-28.5,30.310889132455L-53,-12.124355652982L-4,-12.124355652982Z fill=#999 /></svg>

Jörg Hülsermann
źródło
1
Dwie małe rzeczy do gry w golfa: $k%6==0mogą być $k%6<1i $k%6==5mogą być $k%6>4.
Kevin Cruijssen
4

Python 3, 280 , 262 bajtów

18 bajtów zapisanych dzięki ovs

Gra w golfa:

import turtle
P=lambda n:n<4or P(n-3)+P(n-2)
N=int(input())
M=9
t=turtle.Turtle()
Q=range
R=t.right
L=t.left
F=t.forward
S=[P(x)*M for x in Q(N,0,-1)]
A=S[0]
F(A)
R(120)
F(A)
R(120)
F(A)
L(120)
i=1
while i<N:
 A=S[i]
 for j in Q(3):F(A);L(120)
 F(A)
 L(60)
 i+=1

To samo z niektórymi komentarzami:

import turtle

# P(n) returns nth term in the sequence
P=lambda n:n<4or P(n-3)+P(n-2)

# M: scales the triangle side-length
M=9
# N: show triangles from 1 to (and including) N from sequence
N=int(input())
t=turtle.Turtle()
Q=range
R=t.right # R(a) -> turn right "a" degrees
L=t.left  # L(a) -> turn left "a" degrees
F=t.forward # F(l) -> move forward "l" units

# S: M*P(N),M*P(N-1), ... M*P(1)
S=[P(x)*M for x in Q(N,0,-1)]

# draw the largest triangle
A=S[0]
F(A)
R(120)
F(A)
R(120)
F(A)
L(120)
i=1

# draw the next N-1 smaller triangles
while i<N:
 A=S[i]
 for j in Q(3):F(A);L(120)
 F(A)
 L(60)
 i+=1

Zrzut ekranu dla N=9:

N = 9

Bobas_Pett
źródło
2

dwitter 151

s=(n)=>{P=(N)=>N<3||P(N-3)+P(N-2)
for(a=i=0,X=Y=500,x.moveTo(X,Y);i<n*4;i++)k=9*P(i/4),x.lineTo(X+=C(a)
*k,Y+=S(a)*k),x.stroke(),a+=i%4>2?1.047:2.094}

można przetestować na http://dwitter.net (użyj pełnego ekranu)

wprowadź opis zdjęcia tutaj

Podstawowym pomysłem jest logo żółwia, golfa. ukradł P () func z góry!

Wyobrażam sobie, że rekurencja może zwiększyć golfa, ale nie jest źle.

Don Bright
źródło
1

LOGO, 119 bajtów

to s:n
make"x 10
make"y:x
make"z:y
bk:z
repeat:n[lt 60
fw:z
rt 120
fw:z
bk:z
make"w:y+:z
make"z:y
make"y:x
make"x:w]end

Do użytku, coś takiego zrobić to :

reset
lt 150
s 12

Przykładowe dane wyjściowe (nie można osadzić, ponieważ nie jest to HTTPS i nie można przesłać do imgur)

Neil
źródło