# ASCII ruler generation

The challenge is to generate an ASCII character count ruler in the following format:

+-------------------------------------------------------------------------+
||    |    |    |    |    |    |    |    |    |    |    |    |    |    |  |
|0         10        20        30        40        50        60        70 |
|                                                                         |
+-------------------------------------------------------------------------+


The length of the ruler should be scalable to any multiple of 10.

Rules:

• Ruler must be horizontal.
• Let's say, to keep things simpler, that the ruler must work until the 1000 mark, all numbers left-aligned, one space after the final number.
• Asking for a ruler with zero length should print NaR
• Negative numbers should print a reversed ruler (-90, -80, -70, ...) with right-aligned numbers, in the exact same format as the one above otherwise

And, just printing to console is fine

• How does the program know how long to make the ruler? Is it provided as a number on STDIN? Feb 15 '12 at 4:11
• Yes, as usual I guess! Feb 15 '12 at 4:26
• Does the ruler have to be horizontal or vertical? if it's horizontal, can we assume a maximum of 80 characters, or do we output this to a file to avoid wrapping instead? or do we have to resize the console/terminal when writing to stdout? Feb 15 '12 at 4:49
• One of the main points of code-golf is that the problem must be 100 % unambiguously specified (see the faq). There is little room for creativity in the actual output, because the creativity is in the code itself. In the future, please try to think through all of these possible cases before posting the question, but since you're new, we're helping you out :) Feb 15 '12 at 19:14
• Could you please edit the challenge to include rules specified in the comments? Feb 16 '12 at 12:38

# Python - 227 232

Supports entire specification

edit: improved generator expression.

Supporting right aligned negative numbers adds a surprising amount of code.

b,p,d,w,='|+- '
g=input
s=''.join(('%'+d[:i>0]+'10s')%i+['',9*w][i==0] for i in range(g(),g()+1,10)).strip()+w
m,n=s[0]==d and s.find(w)-1,len(s)
t=p+n*d+p
print['\n'.join([t,b+(w*m+'|    '*n)[:n]+b,b+s+b,b+n*w+b,t]),'NaR'][n<9]


Sample outputs:

-30 30

+-----------------------------------------------------------------+
|  |    |    |    |    |    |    |    |    |    |    |    |    |  |
|-30       -20       -10         0         10        20        30 |
|                                                                 |
+-----------------------------------------------------------------+


-30 -30

NaR


100 150

+------------------------------------------------------+
||    |    |    |    |    |    |    |    |    |    |   |
|100       110       120       130       140       150 |
|                                                      |
+------------------------------------------------------+


-1000 -950

+--------------------------------------------------------+
|    |    |    |    |    |    |    |    |    |    |    | |
|-1000      -990      -980      -970      -960      -950 |
|                                                        |
+--------------------------------------------------------+


Not going to beat the dynamic languages today, but anyway...

import Data.List
main=interact$unlines.m.map read.words m[l,r]|r>l=ᴛ.("┌│││└":).(++["┬ ─","┐│││┘"]).ʀ.t.ʀ.t.takeWhile((>4).length).ᴛ$[c"┬",c"│    ",[l,l+10..r]>>=h.show,c" ",c"─"]|True=["NaR"]
h s=p s$length s;p s@('-':_)l=r(6-l)ꜱ++s++r 4ꜱ;p s l=r 5ꜱ++s++r(5-l)ꜱ ᴛ=transpose;ʀ=reverse;r=replicate;c=cycle ꜱ=' ';t l@(c:o)|c!!2==ꜱ=t o|True=l  I took the liberty of exchanging the actual ASCII characters with better-looking unicode box drawing chars. $ echo "-50 30" | runhaskell  def0.hs
┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐
│  │    │    │    │    │    │    │    │    │    │    │    │    │    │    │    │    │  │
│-50       -40       -30       -20       -10         0         10        20        30 │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘

• The ruler looks very, very nice. Feb 18 '12 at 0:47

Python 2.7, 342 266 260 chars

a,b,c,d,m='+|- \n'
def f(y):x=map(str,(range(0,y+1,10)if y>0 else range(y,1,10)));h,g=len(x[-1])+1,len(x)-1;u=a+(c*10)*g+c*h+a;return'NaR'if y==0 else u+m+b+(b+d*4)*2*g+b+d*(h-1)+b+m+b+''.join(i.ljust(10)for i in x[:-1])+x[-1].ljust(h)+b+m+b+(d*10)*g+d*h+b+m+u


returns a tuple of each line string, which you can then print or save to a file (I prefer the latter for lengths longer than 70 becuase the console will jsut make it look messed up with wrapping)

Assumes y to be a string (raw_input() n python, or sys.argv[1] if you wish to invoke via cmd) an integer (eg with input() in 2.x or int(input()) in 3.x)

I made this a function to be more flexible

edit: reduced to 266 characters. no longer returns a tuple, but a string instead. Now takes an integer instead of a string as the argument

edit2: reduced to 260 chars, single line function

note: does handle negative numbers, but doesn't right justify (I don't really htink the justification is too important anyways

• Or just use a non-linebreaking console (e.g. Terminator). Feb 15 '12 at 18:34
• @leftaroundabout I wasn't sure such a thing existed Feb 15 '12 at 18:46
• regardless, having to install a separate platform just to make a ruler seemspretty pointless, where-as creating a return value that anybody could use (write to a file, etc) is more universal Feb 15 '12 at 18:57
• @Blazer, does your shell not have pipes and redirects? Feb 15 '12 at 20:25

# PowerShell, 256253233225 222 bytes

param($a,$b)('NaR',$($d=@{}
$a..$b|%{$d.$_=' ';0..($l=($s="$($_-$_%10)").Length-1)|%{$d[$_+$s-$l*(0-gt$s)]=$s[$_]}}
$d.Keys|sort|%{$e+='-';$p+='| '[$_%5];$r+=$d.$_;$w+=' '}
@"
+$e-+ |$p |
|$r | |$w |
+$e-+ "@))[$a-lt$b]  Try it online! Less golfed: param($a,$b) ( 'NaR',$(
# {key, value} := {position, digit|minus|space}
$d=@{}$a..$b|%{$d.$_=' ' # draw a nearest left number$n=$_-$_%10
$s="$n"
$l=$s.Length-1
0..$l|%{$d[$_+$s-$l*(0-gt$s)]=$s[$_]
}
}

# edge, points, ruler, whitespaces
$d.Keys|sort|%{$e+='-'
$p+='| '[$_%5]
$r+=$d.$_$w+=' '
}

# output the multiline string
@"
+$e-+ |$p |
|$r | |$w |
+$e-+ "@ ) )[$a-ltb]  ## Python, 291 241 characters A pretty simple approach. I'm sure it can be improved quite a lot. I tried to follow the guidelines in the comments, but I don't support negative numbers (it was a joke, I hope). This is a program, prints the ruler to standard output. If your screen is wide enough, it should support pretty long rulers. import sys def p(b,a="|"):print a+b+a j="".join l=int(sys.argv[1])//10*10 if l: d=j(["%-10d"%n for n in range(0,l,10)])+"%d "%l L=len(d) h="-"*L p(h,"+") p(j(["| "[n%5] for n in range(L)])) p(d) p(" "*L) p(h,"+") else: print "NaR"  • You can golf a few more characters off of this I shaved off 12 characters here Feb 19 '12 at 19:39 • Thanks @GordonBailey, but there's already a winner anyway, which is shorter than my code and supports the full specification. Feb 20 '12 at 7:18 ## C++, 392 This is programmed using the windows console, therefore I just chose a maximum ruler size is 70, it'll just crash for anything bigger. Negative numbers( up to -70) and 0 are handled correctly. #include<ios> #define q s[2][i #define v ,memset(&s char g,o,i,n,s[5][80];int main(int a,char**b){a=atoi(b[1])v,32,400);n=0<a;for(a=abs(a)v[0][1],45,a+3)v[4][1],45,a+3);i<a+4;++i)o=i-n,!(o%5)?s[1][n?i:i+3]='|',(o%2-1?(n?q]=i/10+48,i>9?q+1]=48:0:((a-i)>9?q+2]=(a-i)/10+48,q+1]=45:0,q+3]=48)):0):0;for(;g-5;g++)for(s[g][a+4]=s[g][i=0]=g&g-4?'|':43;i-80;i++)printf(a?"%c":g+i?"":"NaR",s[g][i]);}  # Python - 208 (does not support right aligned negative numbers)  l,u=map(int,raw_input().split()) n=u-l q="+%s+\n" q=q+"|%s|\n"*3+q print q%('-'*n,(''.join("| "for i in range(n)))[:n],(''.join("{:<10d}".format(i)for i in range(l,u,10)))[:n],' '*n,'-'*n)if n>0 else"NaR"  I think my favourite trick was to generate strings that are way longer than necessary and then truncate them, for example:  ''.join("| "for i in range(n)))[:n]  I just wish there was a more concise string formatting option for left-alignment (unless there is one that I just don't know about) Perl 5.14, 198 224 chars Probably can be shortened a lot further, but here's a first second attempt (with line breaks inserted for readability): l=shift||die"NaR\n";
@n=grep!($_%10),$l>0?0..$l:$l..0;
$l=9-length$n[$#n]; @f=('-'x10,'| 'x2,'@'.'<'x9,' 'x10); @f=map$_ x@n,@f;
map$_=~s/.{$l}$//,@f; eval"format=\n+$f[0]+\n|$f[1]|\n|$f[2]|\n\@n\n|$f[3]|\n+$f[0]+\n.\n";
write


EDIT: Edited to die with "NaR" when input is 0 and to support negative range.

EDIT2: I haven't had a chance to work more on this, and I only just now noticed the right aligned for negative numbers rule, which my code doesn't support, so I think another solution should be marked as the answer if the deadline has been reached.

• @louism: My answer doesn't conform to all the rules. Another answer should be chosen if possible. Feb 18 '12 at 10:53