# Ten-row bar chart

This is Hole-1 from The Autumn Tournament of APL CodeGolf. I am the original author of the problem there, and thus allowed to re-post it here.

Given a list of numbers, produce a horizontal bar chart of # characters for how many numbers fit into each of ten equal-sized groups. For example, if the data ranges from 0-100, the ranges will be 0–9.9, 10–19.9, …, 90–100. (Formally, [0,10), [10,20), …, [90,100].). You may assume that there will be at least two numbers and that not all numbers will be the same.

### Examples:

[1,0,0,0,0,0,0,0,0,0] gives:

#########

#


[0,1,2,3,4,5,6,7,8,9] gives:

#
#
#
#
#
#
#
#
#
#


[0,1,2,3,4,5,6,7,8,9,10] gives:

#
#
#
#
#
#
#
#
#
##


[0,1,2,3,4,5,6,7,8,9,10,11] gives:

##
#
#
#
#
#
#
#
#
##


[0,-0.5,-1,-1.5,-2,-2.5,-3,-3.5,-4,-4.5,0.5,0,-0.5,-1,-1.5,-2,-2.5,-3,-3.5,-4,1,0.5,0,-0.5,-1,-1.5,-2,-2.5,-3,-3.5,1.5,1,0.5,0,-0.5,-1,-1.5,-2,-2.5,-3,2,1.5,1,0.5,0,-0.5,-1,-1.5,-2,-2.5,2.5,2,1.5,1,0.5,0,-0.5,-1,-1.5,-2,3,2.5,2,1.5,1,0.5,0,-0.5,-1,-1.5,3.5,3,2.5,2,1.5,1,0.5,0,-0.5,-1,4,3.5,3,2.5,2,1.5,1,0.5,0,-0.5,4.5,4,3.5,3,2.5,2,1.5,1,0.5,0] gives:

###
#######
###########
###############
#########
###################
###############
###########
#######
###


[9014,9082,9077,9068,8866,8710,9049,8364,8867,9015,9064,9023,9024,8804,8805,8800,8744,8743,8714,9076,8593,8595,9075,9675,8968,8970,8711,8728,8834,8835,8745,8746,8869,8868,9073,9074,9042,9035,9033,9021,8854,9055,9017,9045,9038,9067,9066,8801,8802,9496,9488,9484,9492,9532,9472,9500,9508,9524,9516,9474,8739,9079,8900,8592,8594,9053,9109,9054,9059] gives:

#
####
#########
############
######
#########################

###########
#


[0,8,10,13,32,12,6,7,27,9,37,39,95,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,1,2,175,46,48,49,50,51,52,53,54,55,56,57,3,165,36,163,162,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,4,5,253,183,127,193,194,195,199,200,202,203,204,205,206,207,208,210,211,212,213,217,218,219,221,254,227,236,240,242,245,123,125,168,192,196,197,198,201,209,214,216,220,223,224,225,226,228,229,230,231,232,233,234,235,237,238,239,241,91,47,92,60,61,62,45,43,247,215,63,126,42,40,124,59,44,33,243,244,246,248,34,35,30,38,180,64,249,250,251,94,252,96,182,58,191,161,41,93,31,160,167] gives:

#############
######################
##########################
#########################
#########################
#
########
################
########################
##########################

• So, the final group is a tiny bit larger? Like in the first example, it would be [0.9,1] (and not [0.9,1))? Oct 17, 2017 at 8:37
• @FelixPalmen Kind of. It is only larger by an infinitely small amount.
Oct 17, 2017 at 8:48
• Ok, important thing to know was that it's indeed the last group that should include both endpoints, thanks Oct 17, 2017 at 8:51
• @FelixPalmen Ah, I see that that wasn't entirely clear in the OP. I'll edit it in.
Oct 17, 2017 at 9:00
• @Adám Should it be reverse instead? The top row is [0,1) containing only 0 while the bottom row is [9,10] contains both 9 and 10. Oct 18, 2017 at 10:56

# Python 2, 96 bytes

l=input()
m=min(l)
w=max(l)-m
for i in range(10):print"#"*sum(w*i<=(x-m)*10<w*-~i+i/9for x in l)


Try it online!

# Python 2, 107 95 bytes

l=input();m=min(l);s=(max(l)-m)/10.;c=0
exec'print"#"*sum(m<=v-c*s<m+s+c/9for v in l);c+=1;'*10


Try it online!

• Oct 17, 2017 at 10:01
• I rolled back your edit with my suggestion, because *.1 does not work instead of /10. for the very last test case. TBH I don't know why it does not work. Oct 17, 2017 at 11:04

# R, 77 81 bytes

+4 bytes to fix some test cases

for(i in hist(x<-scan(),seq(min(x),max(x),,11),r=F)$c)cat(rep('#',i),'\n',sep='')  Try it online! Link is to a version of the code that takes comma-separated input; this version takes space-separated. Reads from stdin, prints to stdout. R is a statistical programming language that does its best to give high-quality results, which is sometimes frustrating: hist bins the inputs into a histogram with breaks as its second argument. Normally, one would expect that you could specify that the number of breaks to be 10. Indeed, this is the case: breaks one of: • a vector giving the breakpoints between histogram cells, • a function to compute the vector of breakpoints, • a single number giving the number of cells for the histogram, • a character string naming an algorithm to compute the number of cells (see ‘Details’), • a function to compute the number of cells. (emphasis added). The next sentence, however, says: In the last three cases the number is a suggestion only; as the breakpoints will be set to pretty values, the number is limited to 1e6 (with a warning if it was larger). So I looked at the documentation of pretty and it just doesn't work for our situation, because it picks break points thusly: Compute a sequence of about n+1 equally spaced ‘round’ values which cover the range of the values in x. The values are chosen so that they are 1, 2 or 5 times a power of 10. Which simply won't do. So the seq(min(x),max(x),,11) specifies 11 equally-spaced points as the breaks, hist(x,breaks,r=F)$c gives the counts, r=F ensures that the bins are right-open intervals, and the for loop takes care of the rest.

# C (gcc), 241 bytes

#define P(x)for(;x--;putchar('#'));puts("");
double a[999],u,l,x;i,j,n[9];main(k){for(;scanf("%lf",&x)>0;u=u>x?u:x,l=l<x?l:x,a[i++]=x);for(;j<i;++j)for(k=0;k<9;)if(a[j]<l+(++k)*(u-l)/10){n[k-1]++;break;}for(k=0;k<9;++k){i-=n[k];P(n[k])}P(i)}


Try it online!

• I think you can make k as a global, (+1byte) however it is initialized to 0, thus save 3 bytes from k=0. Oct 17, 2017 at 10:34
• Also you can switch double to float and lf to f, save another 2 bytes. (at least that works on TIO) Oct 17, 2017 at 10:58
• @user202729 for your first comment: no, this initialization is needed inside the outer loop multiple times. float might work, I didn't use it because it is not the "standard" floating-point type in C and reduces precision, so not sure this is allowed ... Oct 17, 2017 at 11:06
• 234 bytes Nov 20, 2019 at 22:13

# Mathematica, 152 bytes

(Do[Print[""<>Table["#",Length@Select[s=#,Min@s+(t=#2-#&@@MinMax@s/10)(i-1)<=#<Min@s+t*i&]]],{i,9}];Print[""<>Table["#",Length@Select[s,Max@s-t<=#&]]])&

• How should it work? TIO only have text output. (reply to the part "Dennis will fix it") Oct 17, 2017 at 9:06
• @user202729 Do you really believe that I'm not aware of this? or... Oct 17, 2017 at 9:32
• Not to offend you, but you mention Range[0,9] while I'm talking about Range[0,10] for no reason. But it actually fail for Range[0,10]: TIO. Oct 17, 2017 at 9:35
• You used <= on both ends, which is correct on the last segment but not the 9 other ones. Oct 17, 2017 at 9:43
• @user202729 hey!this one helped me as much as your previous info that Range[0,n]={0,..n}. +1 for great advice. anyways the code works fine now Oct 17, 2017 at 13:20

# JavaScript (ES6), 99 bytes

Edit 2 bytes save thx @JustinMariner

A function returning an array of strings

l=>l.map(v=>o[i=(v-n)/(Math.max(...l)-n)*10|0,i>9?9:i]+='#',o=Array(10).fill,n=Math.min(...l))&&o


Less golfed

list => {
var max = Math.max(...list),
min = Math.min(...list),
output = Array(10).fill(''),
index;

list.forEach( value => (
index = (value - min) / (max - min) * 10 | 0,
output [index > 9 ? 9 : index] += '#'
) )
return output
}


Test

var F=
l=>l.map(v=>o[i=(v-n)/(Math.max(...l)-n)*10|0,i>9?9:i]+='#',o=Array(10).fill,n=Math.min(...l))&&o

var test=[
[1,0,0,0,0,0,0,0,0,0],
[0,1,2,3,4,5,6,7,8,9],
[0,-0.5,-1,-1.5,-2,-2.5,-3,-3.5,-4,-4.5,0.5,0,-0.5,-1,-1.5,-2,-2.5,-3,-3.5,-4,1,0.5,0,-0.5,-1,-1.5,-2,-2.5,-3,-3.5,1.5,1,0.5,0,-0.5,-1,-1.5,-2,-2.5,-3,2,1.5,1,0.5,0,-0.5,-1,-1.5,-2,-2.5,2.5,2,1.5,1,0.5,0,-0.5,-1,-1.5,-2,3,2.5,2,1.5,1,0.5,0,-0.5,-1,-1.5,3.5,3,2.5,2,1.5,1,0.5,0,-0.5,-1,4,3.5,3,2.5,2,1.5,1,0.5,0,-0.5,4.5,4,3.5,3,2.5,2,1.5,1,0.5,0],
[0,8,10,13,32,12,6,7,27,9,37,39,95,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,1,2,175,46,48,49,50,51,52,53,54,55,56,57,3,165,36,163,162,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,4,5,253,183,127,193,194,195,199,200,202,203,204,205,206,207,208,210,211,212,213,217,218,219,221,254,227,236,240,242,245,123,125,168,192,196,197,198,201,209,214,216,220,223,224,225,226,228,229,230,231,232,233,234,235,237,238,239,241,91,47,92,60,61,62,45,43,247,215,63,126,42,40,124,59,44,33,243,244,246,248,34,35,30,38,180,64,249,250,251,94,252,96,182,58,191,161,41,93,31,160,167],
[9014,9082,9077,9068,8866,8710,9049,8364,8867,9015,9064,9023,9024,8804,8805,8800,8744,8743,8714,9076,8593,8595,9075,9675,8968,8970,8711,8728,8834,8835,8745,8746,8869,8868,9073,9074,9042,9035,9033,9021,8854,9055,9017,9045,9038,9067,9066,8801,8802,9496,9488,9484,9492,9532,9472,9500,9508,9524,9516,9474,8739,9079,8900,8592,8594,9053,9109,9054,9059]];

output=x=>O.textContent+=x+'\n\n'

test.forEach(t=>output(t+'\n'+F(t).join\n))
<pre id=O></pre>

• You should be able to save a couple bytes by moving the assignment for i into the array brackets followed by a comma, allowing you to remove the parentheses around the body of the map function: Try it online! Oct 17, 2017 at 16:53
• @JustinMariner right, thx Oct 17, 2017 at 18:35
• You can actually save one more byte if you get rid of i and use Math.min again, with an alias: Try it online! Oct 22, 2017 at 19:30

# Python 2, 126 121 bytes

def f(a):
m=min(a);r=range(10);A=[sum(x>=m+i*(max(a)-m)/10.for x in a)for i in r]+[0]
for i in r:print'#'*(A[i]-A[i+1])


Try it online!

# Jelly, 21 bytes

_Ṃµ÷Ṁ×⁵Ḟµ<⁵+ċÐ€⁵R¤”#ẋ


Try it online!

• Although return a list of lines is permitted, the displayed result is not separated in any way. I don't know whether that is valid. Oct 17, 2017 at 10:01
• It is allowed, since that's how Jelly treats lists of string. You can add ÇŒṘ or ÇY in your footer in order to visualize the result. Also instead of full program, you can say that your submission is a monadic link, that returns rather than printing, making it automatically valid. Oct 17, 2017 at 10:03

# Pyth,  32  31 bytes

*R\#_M.++msmgk+JhSQ*dc-eSQJTQTZ


Try it here! or Verify all the test cases. (with pretty-print using j)

# How this works

This is a full program that takes input from STDIN. This is for the 32-byte version. I'll update it soon.

*R\#_M.++msmgk+hSQ*dc-eSQhSQTQTZ  ~ Full program.

m                    T   ~ Map over [0, 10) with var d.
m                 Q    ~ Map over the input with var k.
g                     ~ Is higher than or equal to?
k                    ~ The current element of the input, k.
+hSQ*dc-eSQhSQT     ~ We'll break this down into pieces:
hSQ                  ~ The lowest element of the input list.
+                     ~ Plus:
*dc-eSQhSQT       ~ We'll break this down into more pieces:
*                   ~ Multiplication.
d                  ~ The current element of [0, 10), d.
c       T         ~ Float division by 10 of:
-eSQhSQ          ~ The difference between the maximum and minium
of the input list.
s                       ~ Sum. Count the number of truthy results.
+                      Z  ~ Append a 0.
.+                          ~ Get the deltas.
_M                            ~ Gets -delta for each delta in the list above.
\#                              ~ The literal character "#".
*R                                ~ Vectorized multiplication. Optionally, you can
use j to join by newlines (as the link does).
~ Output implicitly.


# Charcoal, 31 bytes

≔Ｉ⪪Ｓ,θＥχ×#ΣＥθ⁼ι⌊⟦⁹⌊×χ∕⁻λ⌊θ⁻⌈θ⌊θ


Try it online! Link is to verbose version of code. Input of variable-length lists seems to a little awkward in Charcoal, so I've had to wrap the list in an array containing a string. Explanation:

   Ｓ                            Input string
⪪ ,                           Split on commas
Ｉ                              Cast elements to integer
≔    θ                          Assign to variable q
Ｅχ                        Map from 0 to 9
Ｅθ                   Map over the list
⁻λ⌊θ      Subtract the minimum from the current
⁻⌈θ⌊θ Subtract the minimum from the maximum
∕          Divide
×χ           Multiply by 10
⌊             Floor
⌊⟦⁹              Take minimum with 9
⁼ι                 Compare to outer map variable
Σ                     Take the sum
×#                      Repeat # that many times
Implicitly print on separate lines


# Fortran 2003, 263 bytes

I wrote it on GNU gfortran 5.4.0, and compiled without any additional flags.

It reads from STDIN, one value at a time, and prints to STDOUT.

Here it goes:

program h;real,allocatable::a(:);character f*9;allocate(a(0));do;read(*,*,end=8)r;a=[a,r];enddo;9 format("(",i0,"(""#""))")
8 a=(a-minval(a))+epsilon(1.);a=ceiling(10*a/maxval(a));do i=1,10;j=count(a==i);if(j==0)print*;if(j==0)cycle;write(f,9)j;
print f;enddo;end


Ungolfed explanation: (I don't know if "golfed" can be applied to fortran but either way :P)

program h
real,allocatable::a(:)       ! Create an allocatable array so we can reallocate dynamically
character f*9                ! A character array to format the output
allocate(a(0))               ! Allocate "a" empty at first
do
a=[a,r]                    ! Appends to "a"
enddo
9 format("(",i0,"(""#""))")  ! A format label
8 a=(a-minval(a))+epsilon(1.)! (8) Normalizes a (adds epsilon to avoid zero-indexing)
a=ceiling(10*a/maxval(a))    ! Normalizing and multiplying by the number of bins
do i=1,10                    ! Looping on all the bins
j=count(a==i)              ! Counting the number of occurrences
if(j==0)print*             ! If none, prints empty line
if(j==0)cycle              ! And skips the rest of the loop
write(f,9)j                ! Otherwise writes the count(j) to the print label
print f                    ! And prints to STDOUT
enddo
end


Fun fact: I made a similar code just yesterday to test my implementation of a Weibull random number generator, so it only needed a little adaptation :)

# Perl 5, 85 + 1 (-a) = 86 bytes

@F=sort{$a<=>$b}@F;map$r[($_-$F[0])/($F[-1]-$F[0])*10].='#',@F;$r[9].=pop@r;say for@r


Try it online!

$s=-($m=min@_=@ARGV)+max@_;$a[($_-$m)*10/$s]++for@_;$a[9]+=pop@a;print"#"x$_,$/for@a  Try It Online # Perl 5, 102 bytes $l=(@n=sort{$a<=>$b}<>)[-1]-($f=$n[0]);$m=$f+$l*$_/10,say'#'x(@n-(@n=grep$_>=$m,@n))for 1..9;say'#'x@n


Ungolfed:

my @n = sort { $a <=>$b } <>;
my $f =$n[0];
my $l =$n[-1] - $n[0]; for (1 .. 9) { my$m = $f +$l * ($_ / 10); my$c = scalar @n;
@n = grep { $_ >=$m } @n;
say('#' x (\$c - scalar @n));
}
say('#' x scalar @n);


# Java (OpenJDK 8), 246221209207206163162161 157 bytes

l->{String x="";double b=l[0],m=b,q,i;for(double d:l){b=d<b?d:b;m=d>m?d:m;}for(i=(m-b)/10,q=b;q<m;q+=i,x+="\n")for(double d:l)x+=d>=q&d<q+i?"#":"";return x;}


Try it online!

# q/kdb+, 52 bytes

Solution:

{sum[t=/:bin[m+.1*(t:(!)10)*max[x]-m:min x;x]]#'"#"}


Try it online! (Note the TIO link is a 44 byte K (oK) port of this solution as there is no TIO for q/kdb+).

Examples:

q){sum[t=/:bin[m+.1*(t:(!)10)*max[x]-m:min x;x]]#'"#"}1 0 0 0 0 0 0 0 0 0f
"#########"
""
""
""
""
""
""
""
""
,"#

q){sum[t=/:bin[m+.1*(t:(!)10)*max[x]-m:min x;x]]#'"#"}9014 9082 9077 9068 8866 8710 9049 8364 8867 9015 9064 9023 9024 8804 8805 8800 8744 8743 8714 9076 8593 8595 9075 9675 8968 8970 8711 8728 8834 8835 8745 8746 8869 8868 9073 9074 9042 9035 9033 9021 8854 9055 9017 9045 9038 9067 9066 8801 8802 9496 9488 9484 9492 9532 9472 9500 9508 9524 9516 9474 8739 9079 8900 8592 8594 9053 9109 9054 9059f
,"#"
"####"
"#########"
"############"
"######"
"#########################"
""
""
"###########"
,"#"


Explanation:

Most of the code is used creating the buckets that bin buckets the input into.

{sum[t=/:bin[m+.1*(t:til 10)*max[x]-m:min x;x]]#'"#"} / ungolfed solution
{                                                   } / lambda function with implicit x as parameter
#'"#"  / take (#) each-both "#", 1 2 3#'"#" => "#","##","###"
sum[                                         ]       / sum up everything inside the brackets
bin[                              ;x]        / binary search each x in list (first parameter)
m:min x           / store minimum of list x in variable m
max[x]-                  / subtract from the maximum of list x
(t:til 10)*                         / range 0..9 vectorised multiplication against max delta of list
.1*                                    / multiply by 0.1 (aka divide by 10)
m+                                       / minimum of list vectorised addition against list
t=/:                                             / match each-right against range 0..9 (buckets)


# Jelly, 19 bytes

_Ṃµ÷Ṁ×⁵Ḟ«9ċÐ€⁵Ḷ¤”#ẋ


Try it online!

This is based upon my APL answer for the original problem, which I will post after that competition is over.

## How? (I'm not good at explaining things)

_Ṃµ÷Ṁ×⁵Ḟ«9ċÐ€⁵Ḷ¤”#ẋ
_Ṃ                  = subtract the minimum
µ                 = Sort of like a reverse-order compose
÷Ṁ               = divide by the max
×⁵             = Multiply by 10
Ḟ            = Take the floor
«9          = x => min(x,9)
ċÐ€⁵Ḷ¤    = count occurrences of [0,...,9]
”#ẋ = create the list