Generate a Padovan Spiral

34

4

Introduction

Similar to the Fibonacci Sequence, the Padovan Sequence (OEIS A000931) is a sequence of numbers that is produced by adding previous terms in the sequence. The initial values are defined as:

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

The 0th, 1st, and 2nd terms are all 1. The recurrence relation is stated below:

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

Thus, it yields the following sequence:

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

Using these numbers as side lengths of equilateral triangles yields a nice spiral when you place them all together, much like the Fibonacci Spiral:

enter image description here

Image courtesy of Wikipedia


Task

Your task is to write a program that recreates this spiral by graphical output, with input corresponding to which term.

Rules

  • Your submission must be able to handle at least up to the 10th term (9)
  • Your submission must be a full program or function that takes input and displays a graphical result (either outputs an image or graphs, etc)
  • You must show proof of your graphical output in your submission
  • Rotations of the output are allowed, in 60 degree multiples, with the same representation
  • Going counter-clockwise is also allowed
  • Standard loopholes are forbidden

You may assume that input will be >0 and that correct format of input will be given.

Scoring

This is , so the shortest code in bytes wins. Happy New Years everyone!

Andrew Li

Posted 2017-01-01T02:28:56.793

Reputation: 1 061

Is trailing space after lines allowed? – Pavel – 2017-01-01T02:37:56.187

@Pavel Yes. Let me add that – Andrew Li – 2017-01-01T02:38:15.083

Does the output have to be identical to the example or are reflections and rotations (multiples of 60 degrees) allowed? – Level River St – 2017-01-01T03:28:34.587

@LevelRiverSt I would allow that. Let me clarify that in the post. – Andrew Li – 2017-01-01T03:30:13.930

I think this would also be interesting as a [graphical-output] challenge. – mbomb007 – 2017-01-01T20:22:33.667

@mbomb007 added option for graphical output. – Andrew Li – 2017-01-01T20:32:51.890

Is it allowed to mirror the output? – John Dvorak – 2017-01-01T22:32:56.557

@JanDvorak what do you mean by that? – Andrew Li – 2017-01-01T22:36:03.643

I mean, is it okay if my spiral grows counter-clockwise rather than clockwise like yours does? – John Dvorak – 2017-01-01T22:36:52.380

@JanDvorak Yes, that is allowed. Let me add that into the challenge – Andrew Li – 2017-01-01T22:37:38.143

3Not a fan of allowing both ASCII art and graphical output in the same challenge. They're very very different tasks, and mixing them together makes answers solving the two different possibilities completely incomparable. It would be better to have two separate challenges, one for ASCII art and one for graphical output. – Martin Ender – 2017-01-01T22:58:11.793

@MartinEnder Ok, sure. Since both of the answers here currently are graphical-output, I could have another challenge for ASCII. Would that be ok? – Andrew Li – 2017-01-01T23:01:48.187

@AndrewLi sounds good to me. – Martin Ender – 2017-01-01T23:05:45.890

Answers

12

Mathematica, 119 108 bytes

Thanks to Martin Ender for saving 11 bytes!

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

Unnamed function taking a positive integer argument (1-indexed) and returning graphics output. Example output for the input 16:

enter image description here

Developed simulataneously with flawr's Matlab answer but with many similarities in design—even including the definition I^(2/3) for the sixth root of unity! Easier-to-read version:

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  ])&

Line 1 defines the Padovan sequence ±n = P(n). Line 4 creates a nested array of complex numbers, defining z along the way; the last part ±# z^(#+{2,4,1})&~Array~# generates many triples, each of which corresponds to the vectors we need to draw to complete the corresponding triangle (the ±# controls the length while the z^(#+{2,4,1}) controls the directions). Line 3 gets rid of the list nesting and then calculates running totals of the complex numbers, to convert from vectors to pure coordinates; line 2 then converts complex numbers to ordered pairs of real numbers, and outputs the corresponding polygonal line.

Greg Martin

Posted 2017-01-01T02:28:56.793

Reputation: 13 940

1nevermind that part was just me being stupid. – Martin Ender – 2017-03-07T22:44:38.150

9

Matlab, 202 190 bytes

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

Output for N=19 (1-based indexing):

enter image description here

Explanation

The rough idea is basically working with complex numbers. Then the edges of the triangles point always in the direction of a sixth root of unity.

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

flawr

Posted 2017-01-01T02:28:56.793

Reputation: 40 560

Nice job! Is there any possibility of an explanation? – Andrew Li – 2017-01-01T22:24:55.780

explanation added! – flawr – 2017-01-01T22:35:31.963

really like the use of complex numbers here. – don bright – 2017-03-08T05:12:35.893

7

PHP + SVG , 738 Bytes

<?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>

Output for 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

Posted 2017-01-01T02:28:56.793

Reputation: 13 026

1Two small things to golf: $k%6==0 can be $k%6<1 and $k%6==5 can be $k%6>4. – Kevin Cruijssen – 2017-03-07T16:16:42.567

4

Python 3, 280, 262 bytes

18 bytes saved thanks to ovs

Golfed:

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

Same thing with some comments:

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

Screenshot for N=9:

N=9

Bobas_Pett

Posted 2017-01-01T02:28:56.793

Reputation: 965

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}

can be tested on http://dwitter.net (use fullscreen)

enter image description here

basic idea is logo turtle, golfed. stole the P() func from above!

i imagine more could be golfed by recursion but this is not bad.

don bright

Posted 2017-01-01T02:28:56.793

Reputation: 1 189

1

LOGO, 119 bytes

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

To use, do something like this:

reset
lt 150
s 12

Sample output (can't embed because it's not HTTPS and it failed to upload to imgur)

Neil

Posted 2017-01-01T02:28:56.793

Reputation: 95 035