1
\$\begingroup\$

The challenge

Get familiar with the Ulam spiral:

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

Rules

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.

\$\endgroup\$
7
  • \$\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
    Commented Nov 25, 2014 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
    Commented Nov 25, 2014 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
    Commented Nov 25, 2014 at 20:57
  • 1
    \$\begingroup\$ You refer a couple of times to a "picture above", but I don't see it... \$\endgroup\$ Commented Nov 25, 2014 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
    Commented Nov 25, 2014 at 22:15

1 Answer 1

3
\$\begingroup\$

Python 3 - 506 479 bytes

q=range
def p(n):
 for d in q(2,n//2+1):
  if n%d==0:return 0
 return 1
w=int(input());m=w**2;z=len(str(m))
def k(n):
 if n==1:return'-'*(z-1)+'>'
 if p(n):return str(n).zfill(z)
 return'.'*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:
 d=c[p%4];p+=1;i=0
 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.

\$\endgroup\$
4
  • \$\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
    Commented Nov 25, 2014 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
    Commented Nov 26, 2014 at 2:36
  • \$\begingroup\$ @Kasran Thanks! I got it down over 30 characters \$\endgroup\$
    – kukac67
    Commented Nov 26, 2014 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
    Commented Nov 26, 2014 at 5:36

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