Given a decimal in the form of <float>, <precision>, you draw the graphical representation of the decimal part (i.e. fraction) of the float. Examples:

  1. Input: 6.75, 4, output:

    6||| 7

    6.75 (first number from the input) is the number to explain, 4 (the second number from the input) is the number of dashes below the pipes. 6 is the floored 6.75, 7 is the ceiled 6.75. The number of pipes is the decimal part of first input number * second input number.

  2. Input: 10.5, 6, output:

    10|||   11
  3. Input: 20.16, 12, output

    20||          21

    .16 actually takes 1.92 pipes, but since I can't draw 1.92 pipes, I ceil it to 2.

  4. Input: 1.1, 12, output:

    1|           2

    .1 is 1.2 pipes in this case, so it's floored to 1 pipe.

  5. Also, an edge case. Input: 5, 4 (i.e. the number is an integer), output:

    5    6

  • The number to explain is the positive float, limited only by your language abilities.
  • The precision number is an even integer, greater than 2 (i.e. minimal required precision is 4). It can be arbitrary large too.
  • >= n.5 pipes are rounded up, to n+1 (i.e 1.5 is rounded to 2 and 2.5 is rounded to 3). < n.5 pipes are rounded to n (i.e. 1.4 is rounded to 1 and 2.4 is rounded to 2).
  • If it would be more convenient for your language, you can take the input as an array, e.g. [6.75, 4]. If you take the input in the reversed order, i.e. [4, 6.75], please specify it in your answer.
  • \$\begingroup\$ Can you be more specific about exactly what the desired output format is? \$\endgroup\$
    – isaacg
    Jan 1 '16 at 11:47
  • \$\begingroup\$ @isaacg I've shown four example outputs. What's unclear? \$\endgroup\$
    – nicael
    Jan 1 '16 at 11:52
  • \$\begingroup\$ There seem to be a few corner cases uncovered. E.g. input 5.0 4: does it draw from 5 to 6 or from 4 to 5, or is either acceptable? Input 1.25 2: does it have 0 or 1 |s, and why (i.e. what's the rounding rule)? Does the first number in the input have to be positive? What's its maximum precision and magnitude? Does the second number in the input have to be positive? If it's negative, do we draw backwards? \$\endgroup\$ Jan 1 '16 at 12:19
  • \$\begingroup\$ @Peter Clarified. \$\endgroup\$
    – nicael
    Jan 1 '16 at 12:26
  • \$\begingroup\$ I don't think you've covered the rounding rule. \$\endgroup\$ Jan 1 '16 at 13:05

12 Answers 12


CJam, 32 bytes


Takes the precision first and the decimal second, separated by a space.

Run all test cases.


l~   e# Read input and evaluate, pushing precision and decimal on the stack.
1md  e# Divmod 1, separating the decimal into integer and fractional part.
@:X  e# Pull up precision, store in X.
*mo  e# Multiply precision by fractional part and round.
'|*  e# Push that many vertical bars.
XSe] e# Pad with length X with spaces.
1$)  e# Copy integer part and increment.
N    e# Push linefeed.
W$   e# Copy integer part.
s,   e# Get number of digits as length of string representation.
S*   e# Push that many spaces, to indent the hyphens correctly.
'-X* e# Push X hyphens.
  • \$\begingroup\$ Yep, seems to work fine. \$\endgroup\$
    – nicael
    Jan 1 '16 at 14:33

Mathematica, 119 bytes

a=ToString;b=Array;a[c=Floor@#]<>{b["|"&,d=Round[#2#~Mod~1]],b[" "&,#2-d],a[c+1],"
"," "&~b~IntegerLength@c,"-"&~b~#2}&

I tried... Testing:

In[1]:= a=ToString;b=Array;f=a[c=Floor@#]<>{b["|"&,d=Round[#2#~Mod~1]],b[" "&,#2-d],a[c+1],"\n"," "&~b~IntegerLength@c,"-"&~b~#2}&;

In[2]:= f[6.75, 4]

Out[2]= 6||| 7

In[3]:= f[10.5, 6]

Out[3]= 10|||   11

In[4]:= f[20.16, 12]

Out[4]= 20||          21

In[5]:= f[1.1, 12]

Out[5]= 1|           2

In[6]:= f[5, 4]

Out[6]= 5    6
  • \$\begingroup\$ Could you maybe provide a working demo, or it's not possible? \$\endgroup\$
    – nicael
    Jan 1 '16 at 13:09

Japt, 47 46 bytes

Uf +'|pA=ºU-Uf)*V c)+SpV-A +Uc +R+SpUk l)+'-pV

Just a bunch of adding and repeating.

Try it online

  • \$\begingroup\$ (U-Uf) is the same as U%1, saving two bytes. \$\endgroup\$ Jan 1 '16 at 20:16

Java, 253 206 181 bytes

Saved 47 bytes thanks to @Kenney by inlining conditions and variables used once, and sorting out redundant variables.

Saved 25 bytes again thanks to @Kenney by inlining 2 loops with ternary operators.

Pure String Manipulation:

Inlined loops version (181 bytes):

String m(float f,int p){int g=(int)f,i=0;String h="",q=""+g;int c=q.length();for(;i<c+p;)h+=i++<c?" ":"-";for(i=c;i<p+c;)q+=i++<c+Math.round((f-g)*p)?"|":" ";return q+(g+1)+"\n"+h;}

4 loops version (206 bytes):

String m(float f,int p){int g=(int)f,i=0;String h="",q=""+g;int c=q.length();for(;i++<c;)h+=" ";for(;i<=c+p;i++)h+="-";for(i=c;i<c+Math.round((f-g)*p);i++)q+="|";for(;i++<p+c;)q+=" ";return q+(g+1)+"\n"+h;}

Ungolfed version:

String m(float f,int p){
//initialize some useful values, d is the number of pipes needed
int g=(int)f,d=Math.round((f-g)*p),i=0;
String h="",q=""+g;//append the floored value to the pipe string first
int c=q.length();
for(;i<c;i++)h+=" ";//pad hyphen string with spaces for alignment
for(++i;i<=c+p;i++)h+="-";//append hyphens
for(i=c;i<c+d;i++)q+="|";//append pipes
for(;i<p+c;i++)q+=" ";//append spaces for padding
return q+(g+1)+"\n"+h;}//concatenate the strings in order, separating the strings with a UNIX newline, and return it.

Working example here at ideone.com. The full program accepts STDIN input as <float>,<precision>.

NOTE: Java's Math.round(float) rounds using RoundingMode.HALF_UPas the default, which is the OP's required behaviour.

The output of the test cases provided was diff-matched to what the OP provided.

  • \$\begingroup\$ I hope you don't mind! You forgot to remove a (never used), setting you at 233. You could save another 23 to get at 210 bytes: replacing q.length() with b saves 13: int g=(int)f, b=(""+g).length(), c=b, i=0;. Incrementing the iterator in the condition of the for saves 6, and inlining d (used once) saves 4: int c = b; for(;i++<b;)h+=" "; for(;i++<=b+p;)h+="-"; for(i=c;i<c+Math.round((f-g)*p);i++)q+="|"; for(;i++<p+b;)q+=" ";. \$\endgroup\$
    – Kenney
    Jan 1 '16 at 21:09
  • \$\begingroup\$ Also, someone suggested using an actual newline instead of the escape sequence, but since I'm on Windows, that's a CRLF, 2 bytes anyway given the \n \$\endgroup\$ Jan 2 '16 at 4:10
  • \$\begingroup\$ Nice - yes, b became obsolete aswell ;-) You can still save 1 byte in the 2nd for: for(;i++<=c+p;). You could save the file with unix line endings on windows, but unfortunately Java doesn't allow multiline strings.. \$\endgroup\$
    – Kenney
    Jan 2 '16 at 14:31
  • \$\begingroup\$ @Kenney, no. I tried that. It leads to misaligned hyphens. Java is not the right man for the job, anyway. \$\endgroup\$ Jan 2 '16 at 14:32
  • \$\begingroup\$ I got it down to 181 bytes by using only 2 for loops: for(;i<c+p;)h+=i++<c?" ":"-";for(i=c;i<p+c;)q+=i++<c+Math.round((f-g)*p)?"|":" "; \$\endgroup\$
    – Kenney
    Jan 2 '16 at 14:41

Javascript ES6, 105 104 bytes

(f,p)=>(i=f|0)+("|".repeat(j=(f-i)*p+.5|0)+" ".repeat(p-j))+(i+1)+(`
`+i).replace(/\d/g," ")+"-".repeat(p)

Saved 1 byte thanks to, um, how do you type ՊՓԼՃՐՊՃՈԲՍԼ anyway?

  • \$\begingroup\$ Sorry, I didn't realise the dashes were part of the output, I thought they were just there to visualise the spaces. \$\endgroup\$
    – Neil
    Jan 1 '16 at 22:49
  • \$\begingroup\$ (f,p)=>(i=f|0)+("|"[r="repeat"](j=(f-i)*p+.5|0)+" "[r](p-j))+(i+1)+("\n"+i).replace(/\d/g," ")+"-"[r](p) \$\endgroup\$ Jan 2 '16 at 0:29
  • \$\begingroup\$ Oh yeah, replace \n with an actual newline. And make sure to wrap it in template strings. \$\endgroup\$ Jan 2 '16 at 0:31

Haskell, 113 bytes

x!y|(n,m)<-properFraction x=[s n,(y*m)%'|',(y-y*m)%' ',s$n+1,"\n",s n>>" ",y%'-']>>=id

Usage example:

*Main> putStrLn $ 20.16 ! 12
20||          21

properFraction splits the decimal into it's integer and fraction part. The output is a list of the parts (initial number, bars, spaces, ...) which is concatenated into a single string (via >>=id).

  • \$\begingroup\$ Is it possible to see an online demo of this? \$\endgroup\$
    – nicael
    Jan 1 '16 at 17:22
  • \$\begingroup\$ @nicael: demo (with a main wrapper for a full program). \$\endgroup\$
    – nimi
    Jan 1 '16 at 17:25
  • \$\begingroup\$ Looks like everything's okay (btw: tested there, think that it's a more convenient compiler). \$\endgroup\$
    – nicael
    Jan 1 '16 at 17:31

MATL, 49 bytes


Uses release 6.0.0 of the language/compiler. Runs on Matlab or Octave.

Takes numbers in the same order as in the challenge.


>> matl
 > 2#1\tYUbiXK*Yo'|'1bX"tnKw-Z"hb1+YUhht4Y2m13*_45+c
> 20.16
> 12
20||          21

>> matl
 > 2#1\tYUbiXK*Yo'|'1bX"tnKw-Z"hb1+YUhht4Y2m13*_45+c
> 5
> 4
5    6


2#1\       % implicit input 1st number. Separate decimal and integer part
tYU        % duplicate integer part and convert to string
biXK*Yo    % input 2nd number. Copy it. Multiply by decimal part of 1st number and round
'|'1bX"    % row vector of as many '|' as needed
tnKw-Z"    % row vector of as many spaces as needed
h          % concat horiontally
b1+YUhh    % integer part of 1st number plus 1. Convert to string. Concat twice
t4Y2m      % detect numbers in this string
13*_45+c   % transform numbers into spaces, and non-numbers into '|'
           % implicitly display both strings
  • \$\begingroup\$ Do you have an online interpreter? \$\endgroup\$
    – nicael
    Jan 1 '16 at 17:36
  • \$\begingroup\$ Not yet :-( Runs on Matlab or Octave \$\endgroup\$
    – Luis Mendo
    Jan 1 '16 at 17:37

Perl, 90 bytes

print$f,"|"x($d=.5+($b=pop)*(($a=pop)-($f=0|$a))),$"x(1+$b-$d),$f+1,$/,$"x length$f,"-"x$b

Expects input as commandline arguments. Save in a file (say 90.pl) and run as perl 90.pl 6.75 4

With comments

print $f,                        # floored input (initialized below due to expr nesting)
      "|" x ($d=.5+              # rounded pipe count (`x` operator casts to int)
             +($b=pop)           # second argument  (executed first)
             *( ($a=pop)         # first argument   (executed second)
               -($f=0|$a) )      # minus floored first argument = fractional part
      $"x(1+$b-$d),              # spaces
      $f+1,                      # floored + 1
      $/,                        # newline
      $"  x length $f,           # 2nd line alignment
      "-" x $b                   # the 'ruler'

Stackgoat, 31 27 bytes


Similar to most of the other answers. I'll see if I can golf more. The input can be comma separated, space separated, or almost anything separated.

Non competing because Stackgoat was made after this challenge


CF   // Input, floored, push to stack
v1%  // Decimal part
C*   // Times second part
D    // Duplicate that result
'|^  // Repeat | by previous number
w    // Second input
1P   // Move # of |'s to the top of stack
-    // Subtract
Y^   // Repeat " " by above number
vH   // Ceil first input
X    // Newline
Z+   // Add to 
N    // Get length of first #
Y^   // Repeat by spaces
w'-  // Repeat - second input times

Lua, 157 bytes

Long, but can't find a shorter solution

function f(d,n)r=""a=math.floor(d)d,s=d-a,a..r for i=1,#s do r=r.." "end for i=1,n do s,r=s..(i-.5>n*d and" "or"|"),r.."-"end s=s..a+1 return s.."\n"..r end


function g(d,n)
  d,s=d-a,a..r                         -- d now contains its decimal part
  for i=1,#s do r=r.." "end            -- padding the hyphens
  for i=1,n
    s,r=s..(i-.5>n*d and" "or"|"),r.."-"
    -- s is concatenated with a "|" if i-.5>n*d, a space otherwise
  return s.."\n"..r

You can test lua online, the following test cases could be useful :)

function f(d,n)r=""a=math.floor(d)d,s=d-a,a..r for i=1,#s do r=r.." "end for i=1,n do s,r=s..(i-.5>n*d and" "or"|"),r.."-"end s=s..a+1 return s.."\n"..r end

C, 233 231 bytes

#include <stdlib.h>
#include <math.h>
i,n,l;main(c,v)char**v;{double m;l=atol(v[2]);n=(int)(modf(atof(v[1]),&m)*l+0.5);c=printf("%.f",m);for(;i++<l;)putchar(i>n?32:'|');printf("%.f\n",m+1);printf("%*s",c,"");for(;--i;)putchar(45);}


#include <stdlib.h>
#include <math.h>

    double m;
    l=atol(v[2]); /* Get length from command line */
    n=(int)(modf(atof(v[1]),&m)*l+0.5); /* Get number of pipes and lower limit */
    c=printf("%.f",m); /* print lower limit */

    /* print pipes and spaces */

    /* print upper limit */

    /* print spaces before dashes */

    /* print dashes */

Python 3, 116 108 bytes

def f(F,P):l=int(F);h,p=str(l+1),int((F-l)*P+.5);l=str(l);print(l+"|"*p+" "*(P-p)+h);print(" "*len(l)+"-"*P)

trinket.io link

Thank you to Seeq for saving a few characters.

First version:

def f(F,P):
 h,s,p=str(l+1)," ",int((F-l)*P+.5)

Ungolfed version:

def frac(F,P):
        low = int(F)
        high = low+1
        pipes = int((F-low)*P+.5)
        print(str(low)+"|"*pipes+" "*(P-pipes)+str(high))
        print(" "*len(str(low))+"-"*P)
  • \$\begingroup\$ Could you please provide a working demo? \$\endgroup\$
    – nicael
    Jan 2 '16 at 19:17
  • \$\begingroup\$ This trinket.io link should work: trinket.io/python/409b1488f8 \$\endgroup\$ Jan 2 '16 at 19:24
  • \$\begingroup\$ It actually takes less characters to just use the space literal than store it. You can also just join all the lines with ;. You only use h once, so you should inline it, too. Ought to save some chars. \$\endgroup\$
    – seequ
    Jan 3 '16 at 8:49
  • \$\begingroup\$ @Seeq Good catch on the space literal. Early on I was printing the white space padding at the end of the second line; after I realize that was unnecessary, I didn't double check the code for savings. The h is trickier. For the concatenation and len function in the last two rows to work, l has to be a string, so h would need to be replaced with str(int(l)+1). Setting h before converting l saves a few characters. \$\endgroup\$ Jan 6 '16 at 16:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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