spiral

This geometric spiral looks complicated, but it's fairly simple to draw; take the following box:

box

Draw a straight line between the corner of the box and some set distance above the next corner counter-clockwise.

1 line

Continue this pattern inward, always staying that set distance away from the corner of the next line. Here's a few more lines in.

moar lines

As you can see, as the pattern continues, the spiral approaches the center and the boxes you draw begin to rotate. Note that the distance remains constant, regardless of angle.

The Challenge

The Inspiration (and also thanks to the wonderful person who introduced me to this concept <3)

Given a numerical (possibly fractional) input from 1 to 25, write an image to disk that uses this pattern or display the output on the screen, where the distance from each corner is the distance of one initial side of the box divided by the input. Continue the pattern inward until the distance from the corner specified is longer than the length of the next side.

Rules

  • You may not use built-ins for this spiral creation, but you may use image processing builtins.
  • If you write to disk, you must output an image in any of .jpg, .gif, .tiff, .pbm, .ppm, and .png.
  • The initial side length must be at least 500 pixels.
  • The initial corner may be whichever you choose.
  • As always, the Standard Loopholes are disallowed.

Shoes (Ruby) 163 bytes

Shoes is a ruby-based GUI toolkit.

Shoes.app{n=ask('').to_f
r=s=5E2
a=[0,s*i="i".to_c,s*i+s,s,0]
(q=a[-3]-a[-4]
r=q.abs/s*n
a<<a[-4]+q/r)while r>1
1.upto(a.size-1){|j|line *(a[j-1].rect+a[j].rect)}}

Ungolfed

Shoes.app{ 
  n=ask('').to_f                 #Open a dialog box with no message, get n from user
  r=s=5E2                        #Initialize s to sidelength=500. r can be initialized to any vale, we use the same one for convenience.
  a=[0,s*i="i".to_c,s*i+s,s,0]   #intialize array a with 5 points needed to draw a square, in complex number format (first point=0 is duplicated.)

  (
    q=a[-3]-a[-4]                #find the vector from point plotted 4 before to the following point (plotted 3 before)
    r=q.abs/s*n                  #r is the scale factor
    a<<a[-4]+q/r                 #add a new point derived from a[-4] by moving toward a[-3] by a distance s/n 
  )while r>1                     #break loop when length of line is less than s/n

  1.upto(a.size-1){|j|           #for all points except 1st and last one
    line *(a[j-1].rect+a[j].rect)#take the two complex numbers correspondimg to the current and previous point,
  }                              #convert to 2-element arrays (rectangular coordinates
}                                #combine to make a 4-element array, use * to splat into 4 parameters, and draw using the line method.

Outputs n=4 and n=25

enter image description here

Note that the shape always ends in a triangle, which collapses further to a line. Replacing size-1 with size makes no difference to the appearance of the output and would save 2 bytes, but I left it in for theoretical correctness.

Output n=300

Inspired by a comment by OP, the higher numbers do look great!

enter image description here

  • Is the space following line in the bottom line necessary? – Addison Crump Apr 10 '16 at 20:40
  • @CoolestVeto unfortunately yes. the * converts the four element array formed by conversion of the complex numbers into four parameters for line. The standard syntax is line(*(a[j-1].rect+a[j].rect)) so removing the parentheses and adding a space is already a saving of one byte. Removing the space makes Ruby try to multiply line by the contents of the parentheses, which makes no sense and causes it to throw an error. There is some golfing to be done here, just not that. I'll look into it later. – Level River St Apr 10 '16 at 20:51
  • I'm almost certain you can get rid of the parens around the argument to upto. Also, have you tried removing the ('') after ask? I haven't tested it, but it may be unnecessary – Nic Hartley Apr 10 '16 at 21:55
  • 3
    The output for 100 is beautiful. – Addison Crump Apr 11 '16 at 0:01
  • 1
    @CoolestVeto I find n=100 a little disturbing; it jumps out and goes all 3D on me. I've posted n=300 which is darker overall and therefore calmer. – Level River St Apr 11 '16 at 0:18

Java, 1056 1005 985 948 522 508 507 504 502 501 493 492 488 474 465 458 bytes

import java.awt.*;interface G{static void main(String[]a){new Frame(){int s=499,o=s,e,i,x,y;{o/=new Float(a[0]);add(new Component(){public void paint(Graphics g){g.drawRect(0,0,s,s);int[]p={s,s,s,0,0,0,0,s};for(double d=s,t;d>o;t=o/d,i=e*2,x=(int)((1-t)*p[i]+t*p[(2+i)%8]+.5),y=(int)((1-t)*p[1+i]+t*p[(3+i)%8]+.5),g.drawLine(p[(6+i)%8],p[(7+i)%8],x,y),p[i]=x,p[1+i]=y,e=++e%4,i=e*2,x=p[(2+i)%8]-p[i],y=p[(3+i)%8]-p[1+i],d=Math.sqrt(x*x+y*y));}});show();}};}}

Thanks to CoolestVeto and ECS for yet other ways to reduce size. :-)

  • Ok, I golfed it down a bit, but there is more possible for sure, I coded too object-oriented to be character-minimalistic :-D – Vampire Apr 11 '16 at 0:21
  • @AlexA. If I later on improve my code and make it shorter, can i then simply update the post with the shorter version? – Vampire Apr 11 '16 at 0:29
  • @BjörnKautler Yup, that's good! :) I'm working on a few places to shorten right now. – Addison Crump Apr 11 '16 at 0:30
  • 1
    @BjörnKautler You certainly can! – Alex A. Apr 11 '16 at 0:39
  • 1
    Wow, I've never seen more than 500 bytes chucked off an answer. :O – Addison Crump Apr 11 '16 at 10:23

Groovy, 412 411 403 398 bytes

import java.awt.*
new Frame(){
def s=499,o=s/(args[0]as float),e=0,i,a,b,d,t
{add new Component(){void paint(Graphics g){g.drawRect 0,0,s,s
p=[s,s,s,0,0,0,0,s]
for(d=s;d>o;d=Math.sqrt(a*a+b*b)){t=o/d
i=e*2
a=(int)((1-t)*p[i]+t*p[(2+i)%8]+0.5)
b=(int)((1-t)*p[1+i]+t*p[(3+i)%8]+0.5)
g.drawLine p[(6+i)%8],p[(7+i)%8],a,b
p[i]=a
p[1+i]=b
e=++e%4
i=e*2
a=p[(2+i)%8]-p[i]
b=p[(3+i)%8]-p[1+i]}}}
show()}}
  • I have problems to make it run with groovy 2.4.4 : Caught: groovy.lang.MissingMethodException: No signature of method: static s.div() is applicable for argument types: (java.lang.Float) values: [25.0] Possible solutions: is(java.lang.Object), wait(), run(), run(), find(), any() groovy.lang.MissingMethodException: No signature of method: static s.div() is applicable for argument types: (java.lang.Float) values: [25.0] Possible solutions: is(java.lang.Object), wait(), run(), run(), find(), any() at s$1.<init>(s.groovy:3) at s.run(s.groovy:2) – dieter Apr 11 '16 at 13:05
  • With 2.3.9 it works fine for me. – Vampire Apr 11 '16 at 13:18

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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