8
\$\begingroup\$

Let's continue the based challenges stream, here's the next one:

Task

Draw a Fibonacci spiral of n segments where starting from the first term:

  • each nth segment has a length of nth Fibonacci term.
  • each segment is joined to the end of the previous, rotated by 90 degrees taking the end of previous segment as center of rotation.
  • you can choose any printable ascii character chars to draw the spiral with, although the background must be spaces.
  • You can draw the spiral in any orientation and turning clockwise or counterclockwise
  • Leading/trailing whitespace is allowed within reason

Example

Let's explain it with the help of a visual example:
Beginning of segments are highlighted with an arrow character (> < ^ v) to indicate the direction.
End of segments highlighted with o to indicate the pivot for the rotation of next segment.

Taking the first 9 terms [0,1,1,2,3,5,8,13,21] (the first term(0) doesn't draw anything) we draw clockwise.

o###################<o
                     #
                     #
                     #
                     #
                     #
                     #
                     #
             o#<o    #
             v  ^    #
             # oo    #
             #       #
             #       ^
             o>######o


As you can see we start with one character(a segment of length 1) then add one to the right, then add two by rotating 90 degrees, then 3, then 5 .. and so on.

You can choose 0 or 1 indexing in the Fibonacci sequence, f(0) can draw anything or a single character, just be consistent on this.

Some more examples

n==1 (0-indexed) or n==0 (1-indexed)-> [1]

*

n==2 -> [1,1]

2     1          or 21
1  or 2  or 12 

here we used '1' for the first segment and '2' for the second

n==3 ->[1,1,2]

1     or 12  or...
233       3
          3

Rules

  • This is : all the usual golfing rules apply.
  • Either a function or a full program is fine.
  • Input/output can be given by any convenient method.
\$\endgroup\$
6
  • \$\begingroup\$ Related \$\endgroup\$
    – AZTECCO
    Mar 5 at 21:30
  • 1
    \$\begingroup\$ A few test cases would be needed, to know exactly where each segment ends or how it is joined to the previous one (first turn, then join it seems) \$\endgroup\$
    – Luis Mendo
    Mar 5 at 22:38
  • \$\begingroup\$ Also, is it ok if the program fails for large inputs (or not so large) due to floating point precision errors? \$\endgroup\$
    – Luis Mendo
    Mar 5 at 22:47
  • 1
    \$\begingroup\$ Please also clarify if the output can be rotated so that the last segment is always in the same direction \$\endgroup\$
    – Luis Mendo
    Mar 5 at 22:52
  • 1
    \$\begingroup\$ Thanks for clarifying. I hope it gets reopened soon (only one vote left). My question about floating-point precision was because of Binet's formula. But I agree that it seems better not to allow floating-point errors, as the challenge can be done using only integers \$\endgroup\$
    – Luis Mendo
    Mar 6 at 16:32

8 Answers 8

3
\$\begingroup\$

MATL, 25 bytes

TF0i:"P!1bYs:Q1&(3MPw]Zc&

Try it online!

Explanation

TF     % Push [1, 0]. This array will contain the two most recent Fibonacci
       % numbers in each iteration k: [f(k), f(k-1)] 
0      % Push 0. This initiallizes the matrix M that will be used as output
i:"    % Input n. Do the following n times
  P!   %   Flip vertically, transpose. This rotates tmatrix M by 90 degrees
  1    %   Push 1 (*)
  b    %   Bubble up: moves the array [f(k), f(k-1)] to the top of the stack
  Ys   %   Cumulative sum: gives [f(k), f(k+1)]
  :    %   Range (uses first entry): [1, 2, ..., f(k)]
  Q    %   Add 1, element-wise: gives [2, 3, ..., f(k)+1] (**)
  1    %   Push 1 (***)
  &(   %   Write 1 (*) in M at the rows given by (**) and column 1 (***).
       %   This extends M with the new segment of the spiral, padding with 0
  3M   %   Push [f(n), f(n+1)] again
  P    %   Flip: gives [f(n+1), f(n)], ready for the next iteration
  w    %   Swap: moves the extended M to the top of the stack
]      % End
Zc     % Convert values 1 in M into char '#', and 0 to space
&      % Set alternative input/output spec for the next function, which is
       % implicit display. This causes the function to use only one input,
       % which means that only the top of the stack is displayed
\$\endgroup\$
2
\$\begingroup\$

Python 3.8 (pre-release), 99 bytes

f=lambda n:' #'[2*n:]or[k:='#'+''.join(l[1:])for l in zip(*f(n-1)[::-1])]+(k:=len(k)-1)*['#'+' '*k]

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Canvas, 17 bytes

01⁸┤[┌┌+})H#×21╋↶

Try it here!

\$\endgroup\$
2
\$\begingroup\$

05AB1E, 9 bytes

LÅf0ŽPjSΛ

Try it online.

0-based and the spiral goes counterclockwise starting towards the left, similar as the example in the challenge.
Input \$n=0\$ will always draw a single character instead of an empty output.
Draws with character 0, but this could alternatively be any other digit, the lowercase alphabet, the input digits, the digits of the 0-based \$n^{th}\$ Fibonacci number, etc. by replacing the 0.
The start and direction of the spiral can also be changed by replacing ŽPjS with Ž8O for right counterclockwise; ŽG~S for down counterclockwise; ŽNāS for left clockwise; Ƶ‘0š for up clockwise; Ž9¦S for right clockwise; or ŽICS for down clockwise (up counterclockwise is the only one that's a byte longer with Ž2„0š).

Explanation:

L          # Push a list in the range [1, (implicit) input-integer]
 Åf        # Get the (0-based) n'th Fibonacci number for each of these values
   0       # Push character "0"
    ŽPj    # Push compressed integer 6420
       S   # Pop and convert it to a list of digits: [6,4,2,0]
        Λ  # Use the Canvas builtin with these three arguments
           # (which is output immediately afterwards implicitly)

See this 05AB1E tip of mine (section How to compress large integers?) to understand why ŽPj is 6420.

As for some additional information about the Canvas builtin Λ:
It takes 3 arguments to draw an ASCII shape:

  1. Length of the lines we want to draw
  2. Character/string to draw
  3. The direction to draw in, where each digit represents a certain direction:
7   0   1
  ↖ ↑ ↗
6 ← X → 2
  ↙ ↓ ↘
5   4   3

LÅf0Ž8OS creates the following Canvas arguments:

  1. Length: the first input amount of 1-based Fibonacci numbers
  2. Character: "0"
  3. Directions: [6,4,2,0], which translates to \$[←,↓,→,↑]\$

Step 1: Draw 1 characters ("0") in direction 6/:

0

Step 2: Draw 1-1 characters ("") in direction 4/:

0

Step 3: Draw 2-1 characters ("0") in direction 2/:

00

Step 4: Draw 3-1 characters ("00") in direction 0/:

 0
 0
00

Step 5: Draw 5-1 characters ("000") in direction 6/:

00000
    0
   00

Step 6: Draw 8-1 characters ("0000000") in direction 4/:

00000
0   0
0  00
0
0
0
0
0

etc.

See this 05AB1E tip of mine for an in-depth explanation of the Canvas builtin.

\$\endgroup\$
2
\$\begingroup\$

Vyxal, 11 bytes

×3ʀd⁰ɽ∆f›ø∧

Try it Online!

-1 byte thanks to emanresu A

\$\endgroup\$
1
  • \$\begingroup\$ -1 and fixed \$\endgroup\$
    – emanresu A
    Jun 2 at 0:03
1
\$\begingroup\$

Jelly, 22*? 27 bytes

ÆḞ€R¬W€1¦t⁶;ɗ€0¦Ṛz⁶ʋ/ZṚ$⁸¡Y

A full program that accepts an integer and prints a spiral using 1s.

Try it online!

How?

ÆḞ€R¬W€1¦t⁶;ɗ€0¦Ṛz⁶ʋ/ZṚ$⁸¡Y - Main Link: integer, N
ÆḞ€                         - first N Fibbonacci numbers
   R                        - range       -> [[1],[1],[1,2],[1,2,3],[1,2,3,4,5],...]
    ¬                       - logical NOT -> [[0],[0],[0,0],[0,0,0],[0,0,0,0,0],...]
     W€1¦                   - wrap the first one
                   ʋ/       - reduce by - f(Current, Next):
            ɗ€0¦            -   apply to the final entry of Current:
         t⁶;                -     trim spaces and concatenate Next
                Ṛ           -     reverse
                 z⁶         -     transpose with spaces
                       $⁸¡  - repeat N times:
                     Z      -   transpose
                      Ṛ     -   reverse
                          Y - join with newline characters
                            - implicit print

* Awaiting clarification on whether "output can be rotated so that the last segment is always in the same direction" - 22:

ÆḞ€R¬W€1¦t⁶;ɗ€0¦Ṛz⁶ʋ/Y
\$\endgroup\$
4
  • \$\begingroup\$ This seems to use a fixed ending direction, instead of a fixed starting one as the challenge seems to require. I was considering doing the same, so I've asked for clarification \$\endgroup\$
    – Luis Mendo
    Mar 5 at 22:54
  • 1
    \$\begingroup\$ @LuisMendo I thought our choice under "Start rotating from left ,right,up or down as your wish." didn't need to be consistent across inputs ...hmm. \$\endgroup\$ Mar 5 at 22:56
  • 1
    \$\begingroup\$ @LuisMendo put in a version that has a fixed starting direction for now. \$\endgroup\$ Mar 5 at 23:03
  • 1
    \$\begingroup\$ Updated the question and your 22Byte answer should be fine \$\endgroup\$
    – AZTECCO
    Mar 6 at 17:54
1
\$\begingroup\$

Charcoal, 18 bytes

⊞υ¹FN«⌈υ↶⊞υΣ…⮌υ²»¹

Try it online! Link is to verbose version of code. Explanation:

⊞υ¹

Start with 1.

FN«

Repeat n times.

⌈υ

Output the latest Fibonacci number in unary.

Rotate ready for the next Fibonacci number.

⊞υΣ…⮌υ²

Calculate the next Fibonacci number.

»¹

Print a final character (this is because Charcoal is actually drawing the lines a character early, so it's drawing 1, 2, 3, 5, 8... and the second 1 is missing).

It's possible to draw the lines according to the specification by rotating for the last character of the line, but in this case the spiral has to be drawn clockwise instead:

⊞υ¹FN«¶⌈υ¶↷⊞υΣ✂υ±²

Try it online! Link is to verbose version of code. Explanation:

⊞υ¹

Start with 1.

FN«

Repeat n times.

¶⌈υ¶

Output the latest Fibonacci number in unary, but positioned rotated from the end of the previous one.

Rotate ready for the next Fibonacci number.

⊞υΣ✂υ±²

Calculate the next Fibonacci number, but repeating the initial 1 the first time.

\$\endgroup\$
3
  • \$\begingroup\$ It seems to skip the first term or the second, they are both 1 \$\endgroup\$
    – AZTECCO
    Mar 6 at 17:16
  • \$\begingroup\$ @AZTECCO Actually according to Charcoal's drawing approach I was skipping the very last character, but of course your example didn't show that so I hadn't realised my mistake. I've added it in and also come up with an alternative approach which follows your method more closely (except it now has to do it in a different direction). \$\endgroup\$
    – Neil
    Mar 6 at 17:50
  • \$\begingroup\$ Neil I'm sorry for the discomfort, yes adding a character at the end would be fine. Your answer works perfectly now! \$\endgroup\$
    – AZTECCO
    Mar 6 at 18:04
0
\$\begingroup\$

Python3, 326 bytes:

R=range
f=lambda n,a=1,b=1:[b]+f(n-1,b,a+b)if n else[]
def g(b,e,x,y,q,w):
 if e:x+=q;y+=w;b[x][y]=1;return g(b,e-1,x,y,q,w)
 return x,y
def d(b,r,x,y,c=1):
 if r:d(b,r,*g(b,r.pop(),x,y,0+c%2*[1,-1][c%4==1],0+(c%2==0)*[-1,1][c%4==2]),c+1)
def F(n):
 r=f(n);b=[[0 for _ in R(r[-2]+1)]for _ in R(r[-1])];d(b,r,len(b),0);return b

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ It seems it doesn't work properly for the first few terms \$\endgroup\$
    – AZTECCO
    Mar 6 at 17:19
  • \$\begingroup\$ @AZTECCO Can you clarify, the spiral generated for terms 1 to 3 matches your posted output. \$\endgroup\$
    – Ajax1234
    Mar 6 at 17:30
  • \$\begingroup\$ Ajax your answer prints nothing for 0 and may be fine, but still prints nothing for 1 and that would be fine if you 1-index in [0,1,1,...], for 2 seems to print a [1,2] spiral skipping one term, and seems to start from 2nd term for any input(e.g. [1,2,3,5..]. Anyway I updated the question and hopefully it's going to be reopened, check it out and if you have any doubt don't hesitate to ask clarifications \$\endgroup\$
    – AZTECCO
    Mar 6 at 17:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.