The challenge

Get familiar with the Ulam spiral:

The aim is to print the spiral like in the picture above!


Write a function ulam(n)

where n is a odd positive integer and describes the size of the grid to print.

All non-primes numbers should be replaced with | horizontal and - vertical as in the picture above following the spiral. (Corner elements belongs to the vertical)

All numbers need to take the same amount of space visually and smaller numbers are right centered vertically:

1000 100 10

10 needs two spaces on the left and 100 needs one space left. This property depends on the biggest number you have to calculate.

Example: (n=3)

 -  - 3 
|     |  
7   - 2  
 -  -  

The test for primes/sieve you have to write yourself.

Smallest byte code wins.

Bonus - 25 if you can make it more pretty find some symbols so that - and | takes the same space (-25 more if you can find a pretty corner symbol) and the symbol should show the line where the spiral evolves.

  • \$\begingroup\$ You can always use box-drawing characters for the lines, assuming you've got Unicode support (or code page 437)... Those are made to look nice, after all. \$\endgroup\$ – Kasran Nov 25 '14 at 19:47
  • \$\begingroup\$ @Kasran no need for unicode, you can use extended ascii (codes 128-255), which has a 'good enough' set of box-drawing characters. \$\endgroup\$ – stokastic Nov 25 '14 at 19:48
  • \$\begingroup\$ @stokastic "extended ASCII" isn't a single thing (and one such extension is exactly code page 437, which is probably what you're thinking of) \$\endgroup\$ – FireFly Nov 25 '14 at 20:57
  • 1
    \$\begingroup\$ You refer a couple of times to a "picture above", but I don't see it... \$\endgroup\$ – Peter Taylor Nov 25 '14 at 21:09
  • 1
    \$\begingroup\$ Your example for n=3 shows what looks like a 4x5 grid. Can you expand on how n describes the grid size? \$\endgroup\$ – MickyT Nov 25 '14 at 22:15

Python 3 - 506 479 bytes

def p(n):
 for d in q(2,n//2+1):
  if n%d==0:return 0
 return 1
def k(n):
 if n==1:return'-'*(z-1)+'>'
 if p(n):return str(n).zfill(z)
l=[k(n+1)for n in q(m)];s=[[0for n in q(w)]for n in q(w)];x=y=w//2;t=[n//2for n in q(2,w*w)];c=[[1,0],[0,-1],[-1,0],[0,1]];j=p=0
for r in t:
 while i<r and j<m:
  s[y][x]=l[j]+' ';x+=d[0];y+=d[1];i+=1;j+=1
s=[''.join(l)for l in s]
for l in s:print(l)

I am not sure if the byte count is correct.
Also, this can most likely be made shorter (I'm new to Python).

Right now I'm just substituting all non-primes with periods. You can change this to any character.

Note: You should only enter odd numbers as input, as otherwise the program breaks.

Furthermore, my function to determine whether a number is prime is the most primitive it can be, for the sake of less characters, so it is not efficient. Though it ran just fine on my computer with input values less than 100 in just under a second.

Note: Input values above 25 or 30 won't display correctly unless you have a ridiculously wide screen.

  • \$\begingroup\$ I just realized I didn't write a function. Oh well. One can easily change it to a function by removing w=int(input()) and adding a function header like def ulam(w): saving 13 bytes I think (though the function would have to be indented). \$\endgroup\$ – kukac67 Nov 25 '14 at 23:56
  • \$\begingroup\$ You could do, say, j=p=0. Also, boolean values are castable to 0 and 1, so you might be able to shorten your p(n) function a little bit that way if you're careful. And whitespace is costly in Python; contracting some of those statements onto a single line with semicolons can save you a few characters. \$\endgroup\$ – Kasran Nov 26 '14 at 2:36
  • \$\begingroup\$ @Kasran Thanks! I got it down over 30 characters \$\endgroup\$ – kukac67 Nov 26 '14 at 2:55
  • \$\begingroup\$ You can make your p function quite a bit shorter with p=lambda n:all([n%d for d in q(2,n//2+1)])... at least, that works in Python 2. Also, ` surrounding a thing functions like repr, which is handy for turning ints into strings in a golfy way; consider using that instead of str. \$\endgroup\$ – Kasran Nov 26 '14 at 5:36

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