# create an ascii progress bar

well, it's something similar to this question but with a little differences. you have to write a program to ask for width of progress bar and how much work is done. and then draw a progress bar with following features:

• width indicates how many characters you have to use to draw progress bar

• progress is given via a floating point value between 0..1.

• first and last character in progress bar should be something different from all other character, for example "[" and "]"

• your program should use two different characters to how much progress passed since the start

• you have to write how much work is done right in the middle of progress bar, using a decimal number + "%" sign.

bonus point for handling extreme inputs, such as 150% or -5% work done.

scoring number of characters * (1 without bonus or 0.75 width bonus)

some examples of valid outputs

79 0.15
[||||||||||||                         15%                                     ]


25 0.76
[##########76%#####.....]


39 -0.12
[                 -12%                 ]


25 7.6
[##########760%#########]

• How is input taken? Command line? Stdin? Any of the above? – lochok Apr 2 '12 at 3:33
• @lochok I guess stdin would be a better choice. – Ali1S232 Apr 2 '12 at 3:38

## PHP 84 x 0.75 = 63

Edit: A less 'pretty' version, but it should be valid according to the rules:

[<?=str_pad(!fscanf(STDIN,~Ú›Ú™,$a,$b),$a*min(1,$b),~ß)|str_pad(100*$b.~Ú,$a,_,2)?>]


Output:

$echo 79 0.15 | php progress-bar.php [⌂⌂⌂⌂⌂⌂⌂⌂⌂⌂⌂___________________________15%______________________________________]$ echo 25 0.76 | php progress-bar.php
[⌂⌂⌂⌂⌂⌂⌂⌂⌂⌂⌂76%⌂⌂⌂⌂⌂______]
$echo 39 -0.12 | php progress-bar.php [_________________-12%__________________]$ echo 25 7.6 | php progress-bar.php
[⌂⌂⌂⌂⌂⌂⌂⌂⌂⌂760%⌂⌂⌂⌂⌂⌂⌂⌂⌂⌂⌂]


### Original (98 x 0.75 = 73.5)

[<?=strtr(str_pad(!fscanf(STDIN,~Ú›Ú™,$a,$b),$a*min(1,$b),~ß)|str_pad(100*$b.~Ú,$a,~ü,2),~ü,~ß)?>]


Output:

$echo 79 0.15 | php progress-bar.php [########### 15% ]$ echo 25 0.76 | php progress-bar.php
[###########76%#####      ]
$echo 39 -0.12 | php progress-bar.php [ -12% ]$ echo 25 7.6 | php progress-bar.php
[##########760%###########]

• I'm wondering how can I run your code. – Ali1S232 May 9 '12 at 8:36
• Save it as a php file. Send it the two paramaters as a space separated string as STDIN. For example: [windows/linux command prompt] echo 79 0.15 | php progress-bar.php You will need to have the php-cli (command line interface) installed. Most php installers for windows should have it included (or optional), linux with apt-get install php5-cli – primo May 9 '12 at 13:07
• I've selected this answer since as far as I tested this one always worked as expected, while one that ephemient provided sometimes doesn't print the number exactly in the middle. – Ali1S232 May 9 '12 at 20:35

# J, 78×0.75 = 58.5

'w p'=:_".1!:1]3
1!:2&4('%',~":100*p)(i.@[-<.@-:@-)&#}'[]'0 _1}' |'{~(w*p)>i.w

$echo -n 79 0.15 | jconsole test.ijs [||||||||||| 15% ]$ echo -n 25 0.76 | jconsole test.ijs
[||||||||||76%|||||     ]
$echo -n 39 -0.12 [ _12% ]$ echo -n 25 7.6 | jconsole test.ijs
[|||||||||760%||||||||||]


(Negative numbers in J are prefixed by _, not -. Luckily, dyadic ". can parse both formats.)

• Does this exclude the space taken by the percentage when it calculates the number of bars to display? Cause it seems to get different results from mine. – grc Apr 3 '12 at 0:41
• @grc With 100 columns, each percent is a single bar (even if hidden by other elements such as the brackets or number/percent). – ephemient Apr 3 '12 at 1:49
• Okay I get it now. Good job :) – grc Apr 3 '12 at 2:04
• @ephemient now I've noticed in -0.12 case, you are printing 18 spaces at left part and 16 at right part. it means _12% is not exactly in the middle. – Ali1S232 Apr 25 '12 at 18:09

# Perl, 96×¾ = 72

#!/usr/bin/perl -ap
formline'[@'.'|'x($F[0]-3).']',100*$F[1].'%';
$_=$^A;s# |(.)#$1//($-[0]<$F[0]*$F[1]?'|':$&)#eg  That's by traditional Perl golf rules (#! line not counted, except for the - and switches if any). $ echo 79 0.15 | perl test.pl
[|||||||||||                          15%                                     ]
$echo 25 0.76 | perl test.pl [||||||||||76%||||| ]$ echo 39 -0.12 | perl test.pl
[                -12%                 ]
$echo 25 7.6 | perl test.pl [|||||||||760%||||||||||]  ### Ruby - score 93 (124 characters) w=gets.to_i-2 f=$_[/ .+/].to_f
e=f<0?0:f>1?w:(f*w).to_i
b='#'*e+' '*(w-e)
b[(w-l=(s='%d%'%(100*f)).size)/2,l]=s
puts"[#{b}]"


Yet another ruby implementation. Reads input from STDIN in the form described above. You may exchange characters '#', ' ' and '[', ']' directly in the code.

45 0.88
[####################88%##############      ]

60 1.22
[###########################122%###########################]

• this is alway two chars too wide – Patrick Oscity Apr 26 '12 at 8:07
• @padde Why do you think it's two chars too wide? There is a -2 in the first line. – Howard Apr 27 '12 at 0:25

## Python - 158155148143 138 characters (score of 103.5)

x,y=raw_input().split()
x=int(x)-2
y=float(y)
p=int(y*100)+"%"
b="|"*int(x*y+.5)+" "*x
print"["+b[:(x-len(p))/2]+p+b[(x+len(p))/2:x]+"]"


It could be 30 characters shorter if the input was separated by a comma.

• why didn't you use r=p.length()? – Ali1S232 Apr 2 '12 at 7:09
• what do you mean? – grc Apr 3 '12 at 0:17
• nothing my bad, I just misunderstood you code. – Ali1S232 Apr 3 '12 at 0:24
• but your code doesn't seem to handle -12% case. – Ali1S232 Apr 3 '12 at 0:25
• What is it meant to do? At the moment it just prints an empty bar with the percentage. – grc Apr 3 '12 at 0:27

# Q,90 chars, no bonus

{-1 @[x#" ";(1+(!)(_)x*y;0;((_)x%2)+(!)(#)($)a;x-1);:;("|";"[";a:,[;"%"]($)(100*y);"]")];}


usage

q){-1 @[x#" ";(1+(!)(_)x*y;0;((_)x%2)+(!)(#)($)a;x-1);:;("|";"[";a:,[;"%"]($)(100*y);"]")];}[50;0.15]
[|||||||                 15%                     ]

q){-1 @[x#" ";(1+(!)(_)x*y;0;((_)x%2)+(!)(#)($)a;x-1);:;("|";"[";a:,[;"%"]($)(100*y);"]")];}[30;0.35]
[||||||||||    35%           ]

q){-1 @[x#" ";(1+(!)(_)x*y;0;((_)x%2)+(!)(#)($)a;x-1);:;("|";"[";a:,[;"%"]($)(100*y);"]")];}[40;0.85]
[|||||||||||||||||||85%||||||||||||    ]


### Scala 149:

val w=readInt
println(("["+"|"*(p*w).toInt+" "*((w-p*w).toInt)+"]").replaceAll("(^.{"+(w/2-3)+"}).{5}","$1 "+(p*100).toInt+("% ")))  ungolfed: def progressbar (width: Int, pos: Double) { println (( "["+ "|"*(pos*width).toInt+ " "*((width-pos*width).toInt)+ "]"). replaceAll ("(^.{" + (width/2-3) + "}).{5}", "$1 " + (p * 100).toInt + ("% ")))}
}


I decided, for readability, you really need a space around the progress number:

(44 to 54).map (x => b (100, x/100.0))
[||||||||||||||||||||||||||||||||||||||||||||   44%                                                  ]
[|||||||||||||||||||||||||||||||||||||||||||||  45%                                                  ]
[|||||||||||||||||||||||||||||||||||||||||||||| 46%                                                  ]
[|||||||||||||||||||||||||||||||||||||||||||||| 47%                                                  ]
[|||||||||||||||||||||||||||||||||||||||||||||| 48%                                                  ]
[|||||||||||||||||||||||||||||||||||||||||||||| 49%                                                  ]
[|||||||||||||||||||||||||||||||||||||||||||||| 50%                                                  ]
[|||||||||||||||||||||||||||||||||||||||||||||| 51%                                                  ]
[|||||||||||||||||||||||||||||||||||||||||||||| 52% |                                                ]
[|||||||||||||||||||||||||||||||||||||||||||||| 53% ||                                               ]
[|||||||||||||||||||||||||||||||||||||||||||||| 54% |||                                              ]


## C, 145 characters, score = 108.75

float p;s;m;char x[99];main(){scanf("%d%f",&s,&p);sprintf(x+s/2-1,"%.0f%%",p*100);for(;m<s;)x[++m]||(x[m]=m<p*s?35:32);x[s-1]=93;*x=91;puts(x);}

• though I really liked your idea of sprintf, but it generates a minor problem, check your program with 20 1 inputs it will generate output of [#######100%######] in this case there are 7 sharps left of number and 5 sharps at right, so the number printed is not exactly in the middle. – Ali1S232 Apr 4 '12 at 23:12

node.js: 135chars, *0.75 for bonus points, so 101.25chars.

a=process.argv,i=a[2],p=a[3],o=i/2|0,f=i-i*p,x=['['];for(;i--;){x.push((i<f?' ':'|')+(i-o?'':p*100+'%'));}console.log(x.join('')+']');


ungolfed:

a = process.argv, // console inputs
i = a[2], // input 1 -> width
p = a[3], // input 2 -> percent complete
o = i / 2 | 0, // half of i, without any decimal places
f = i - i * p, // how far along the bar to draw spaces
x = ['[']; // start an array
while(i--){ // while i > 0
x.push( // add to the array
(i < f ? ' ' : '|') // a space, or | depending on how far along the bar we are
+ (i - o ? '' : p * 100 + '%')); // and if we're halfway, add the percentage complete
}
console.log(x.join('') + ']'); // then write out the array as a string, with a trailing ]


output:

D:\mercurial\golf\ascii>node progressBar.js 25 7.6
[|||||||||||||760%||||||||||||]

D:\mercurial\golf\ascii>node progressBar.js 39 -0.12
[                    -12%                   ]

D:\mercurial\golf\ascii>node progressBar.js 79 0.15
[|||||||||||                             15%                                       ]


## PHP-128x0.75=>96

<?fscanf(STDIN,'%d%d',$w,$p);$v='[';for($i=1;$i<$w-1;)$v.=($i++==$w/2-1)?$p*($i+=2)/$i.'%':(($i<$w*$p/100)?'|':' ');echo"$v]";?>


<?fscanf(STDIN,'%d%f',$w,$p);$v='[';for($i=1;$i<$w-1;)$v.=($i++==$w/2-1)?$p*100*($i+=2)/$i.'%':(($i<$w*$p)?'|':' ');echo"$v]";?>


## C, 149*0.75=111.75

main(w,i){float p;for(i=printf("[",scanf("%d%f",&w,&p));i<w-1;)(i++==w/2-1)?printf("%.0f%%",p*100*(i+=2)/i):printf("%c",i<=(p*w)?'|':' ');puts("]");}


Output:

80
0.75
[||||||||||||||||||||||||||||||||||||||75%||||||||||||||||||                   ]

80
7.60
[||||||||||||||||||||||||||||||||||||||760%|||||||||||||||||||||||||||||||||||||]

80
-0.12
[                                      -12%                                     ]

• p should be a floating point value, between 0..1 – Ali1S232 Apr 11 '12 at 14:21
• @Gajet thanks for bringing to notice. Has been rectified :) – l0n3sh4rk Apr 11 '12 at 19:26

## JavaScript 127 125, no bonus

l=9,p="0.99",f=l*p|0,m=l/2|0,x=["]"];for(;l--;)x.unshift(l>=f?"-":"+");x[m++]=p[2],x[m++]=p[3],x[m]="%";alert("["+x.join(""))
//[+++99%++-]


Usage: Change l=9 with other length and/or change p="0.99" with other percent

Note: end with zero 0.X0 instead of 0.X

# MATL, score 35.25 (47 * 0.75)

qqtl&O61bti*Xl:(HG100*V37hyn2/kyny+q&:(91w93v!c


Try it online!

### Explanation:

         % implicit input, say w = 79
qq       % decrement input by 2 (to allow brackets on either side)
tl&O     % duplicate and create array with that many zeros
61       % Push '=' character
b        % bubble up w-2 from below
ti*      % duplicate and multiply by second input, say p = 0.15
%  stack: [[0;0;0;...;0], 61, 77, 11.55]
Xl       % take minimum of (w-2) and (w-2)*p
%  (used when p > 1, makes eligible for bonus)
:        % create range 1 to that value
%  stack: [[0;0;0;...;0], 61, [1 2 3 4 5 ... 11]]
(        % assign into the first array the value 61 ('=') at the
%  indices denoted by the third array
HG       % push second input again
100*V    % multiply by 100 and convert to string
37h      % append the '%' symbol to it
yn2/k    % compute half of the length of the output array
yny+q    % copy of that + length of the 'N%' string - 1
% stack: [[61;61;61;...;0;0;0], '15%', 38, 40]
&:       % make a range from the first to the second (38 to 40)
(        % assign the 'N%' string at those places into the output array
91w93    % surround by '[' (ASCII 91) and ']' (93) characters
v!       % combine into a single array, make it horizontal for display,
c        % change it to character type (implicitly displayed)


# Excel VBA, 108*.75 = 81 bytes

A function that takes input from [A1] and [B1] and outputs to the console

s=""&[MID(IFERROR(REPT("",A1*B1),"")&REPT("",A1),2,A1-2)]&"":n=100*[B1]:Mid(s,([A1]-len(n))/2)=n &"%":?s


### Output

with input [A1]=25 and [B1]=.76

76%


With input [A1:B1].Resize(1,2)=Split("32 -.5")

-50%


With input [A1:B1].Resize(1,2)=Split("40 10.01")

1001%