14
\$\begingroup\$

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.
\$\endgroup\$
13
  • 4
    \$\begingroup\$ Closely related. \$\endgroup\$ Commented Apr 9, 2016 at 22:30
  • \$\begingroup\$ Is there a minimum for how many levels deep this spiral must be? \$\endgroup\$ Commented Apr 9, 2016 at 22:39
  • \$\begingroup\$ @LegionMammal978 I would never ask for an input greater than 25, I'll add that. \$\endgroup\$ Commented Apr 9, 2016 at 22:42
  • \$\begingroup\$ Including .pbm or .ppm might help some of the less graphical languages. \$\endgroup\$ Commented Apr 10, 2016 at 0:47
  • \$\begingroup\$ also related \$\endgroup\$ Commented Apr 10, 2016 at 3:34

3 Answers 3

13
\$\begingroup\$

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

\$\endgroup\$
6
  • \$\begingroup\$ Is the space following line in the bottom line necessary? \$\endgroup\$ Commented Apr 10, 2016 at 20:40
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Apr 10, 2016 at 20:51
  • \$\begingroup\$ 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 \$\endgroup\$
    – anon
    Commented Apr 10, 2016 at 21:55
  • 3
    \$\begingroup\$ The output for 100 is beautiful. \$\endgroup\$ Commented Apr 11, 2016 at 0:01
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ Commented Apr 11, 2016 at 0:18
4
\$\begingroup\$

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. :-)

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

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()}}
\$\endgroup\$
2
  • \$\begingroup\$ 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) \$\endgroup\$
    – dieter
    Commented Apr 11, 2016 at 13:05
  • \$\begingroup\$ With 2.3.9 it works fine for me. \$\endgroup\$
    – Vampire
    Commented Apr 11, 2016 at 13:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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