Гистограмма с десятью рядами

13

Это Hole-1 с осеннего турнира APL CodeGolf . Я являюсь первоначальным автором этой проблемы, и поэтому мне разрешено повторно публиковать ее здесь.


Учитывая список чисел, создайте горизонтальную гистограмму #символов для того, сколько чисел вписывается в каждую из десяти групп одинакового размера. Например, если данные колеблются от 0 до 100, диапазоны будут 0–9,9, 10–19,9,…, 90–100. (Формально, [0,10), [10,20),…, [90,100].). Вы можете предположить, что будет как минимум два числа и что не все числа будут одинаковыми.

Примеры:

[1,0,0,0,0,0,0,0,0,0] дает:

#########








#        

[0,1,2,3,4,5,6,7,8,9] дает:

#
#
#
#
#
#
#
#
#
#

[0,1,2,3,4,5,6,7,8,9,10] дает:

#
#
#
#
#
#
#
#
#
##

[0,1,2,3,4,5,6,7,8,9,10,11] дает:

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

[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] дает:

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

[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] дает:

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


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

[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] дает:

#############             
######################    
##########################
######################### 
######################### 
#                         
########                  
################          
########################  
##########################
Адам
источник
3
Итак, последняя группа немного больше? Как и в первом примере, это будет [0.9,1](и нет [0.9,1))?
Феликс Пальмен
@FelixPalmen Вид. Это только больше на бесконечно маленькое количество.
Адам
Хорошо, важно знать, что это действительно последняя группа , которая должна включать в себя обе конечные точки, спасибо
Феликс Palmen
@FelixPalmen Ах, я вижу, что это было не совсем ясно в ОП. Я отредактирую это.
Адам
1
@ Adám Должен ли он быть наоборот? Верхний ряд [0,1)содержит только в 0то время как нижний ряд [9,10]содержит и 9и 10.
user202729

Ответы:

4

Python 2 , 107 95 байт

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

Попробуйте онлайн!

овс
источник
Я откатил ваше редактирование с моим предложением, потому *.1что не работает вместо /10.самого последнего контрольного примера. TBH Я не знаю, почему это не работает.
г-н Xcoder
4

R , 77 81 байт

+4 байта для исправления некоторых тестовых случаев

for(i in hist(x<-scan(),seq(min(x),max(x),,11),r=F)$c)cat(rep('#',i),'\n',sep='')

Попробуйте онлайн!

Ссылка на версию кода, которая принимает ввод через запятую; эта версия занимает пробел

Читает из стандартного ввода, печатает на стандартный вывод.

R является статистическим языком программирования, который делает все возможное, чтобы давать высококачественные результаты, что иногда расстраивает:

histобъединяет входные данные в гистограмму со breaksвторым аргументом. Обычно можно ожидать, что вы можете указать, что количество разрывов равно 10. Действительно, это так:

breaks

один из:

  • вектор, дающий точки останова между ячейками гистограммы,
  • функция для вычисления вектора точек останова,
  • одно число, дающее количество ячеек для гистограммы,
  • символьная строка с именем алгоритма для вычисления количества ячеек (см. «Детали»),
  • функция для вычисления количества клеток.

(выделение добавлено).

Однако в следующем предложении говорится:

В последних трех случаях число является только предположением; поскольку для точек останова будут заданы prettyзначения, число будет ограничено 1e6(с предупреждением, если оно больше).

Итак, я посмотрел на документацию, prettyи она просто не работает для нашей ситуации, потому что она таким образом выбирает точки останова:

Вычислить последовательность примерно n+1одинаково расположенных круглых значений, которые охватывают диапазон значений в x. Значения выбираются так, чтобы они в 1, 2 или 5 раз превышали степень 10.

Который просто не будет делать.

Таким образом, seq(min(x),max(x),,11)указывается 11 точек с равным интервалом, как breaks, hist(x,breaks,r=F)$cдает счет, r=Fгарантирует, что срезы имеют правильные интервалы, а forостальная часть позаботится о цикле.

Giuseppe
источник
3

C (gcc) , 241 байт

#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)}

Попробуйте онлайн!

Феликс Палмен
источник
Я думаю, что вы можете сделать kкак глобальный, (+ 1 байт), однако он инициализируется в 0, таким образом сохранить 3 байта из k=0.
user202729
Также вы можете переключиться doubleна floatи, lfчтобы fсохранить еще 2 байта. (по крайней мере, это работает на
TIO
@ user202729 для вашего первого комментария: нет, эта инициализация необходима во внешнем цикле несколько раз. floatможет работать, я не использовал его, потому что это не «стандартный» тип с плавающей точкой в ​​C и снижает точность, поэтому не уверен, что это разрешено ...
Феликс Палмен
234 байта
floorcat
3

Mathematica, 152 байта

(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<=#&]]])&


Попробуйте онлайн!

J42161217
источник
Как это должно работать? TIO имеют только текстовый вывод. (ответ на часть «Деннис это исправит»)
user202729
1
@ user202729 Вы действительно верите, что я не знаю об этом? или ...
J42161217
2
Не обидеть вас, но вы упоминаете, Range[0,9]пока я говорю Range[0,10]без причины. Но это на самом деле не для Range[0,10]: TIO .
user202729
4
Вы использовали <=на обоих концах, что правильно на последнем сегменте, но не 9 других.
user202729
3
@ user202729 эй! это помогло мне так же, как и твоя предыдущая информация, что Range [0, n] = {0, .. n}. +1 за отличный совет. В любом случае код теперь работает нормально
J42161217
3

JavaScript (ES6), 99 байт

Редактировать 2 байта сохранить thx @JustinMariner

Функция, возвращающая массив строк

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

Меньше гольфа

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
}

Тестовое задание

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>

edc65
источник
Вы должны быть в состоянии сохранить пару байтов, переместив присваивание для iв скобки массива, за которыми следует запятая, что позволит вам удалить скобки вокруг тела функции карты: попробуйте онлайн!
Джастин Маринер
@JustinMariner верно,
спасибо
На самом деле вы можете сохранить еще один байт, если избавитесь от него iи будете использовать Math.minснова, используя псевдоним: попробуйте онлайн!
Джастин Маринер
2

Желе , 21 байт

Монадическая ссылка возвращает список строк.

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

Попробуйте онлайн!

user202729
источник
Хотя возврат списка строк разрешен, отображаемый результат никак не разделен. Я не знаю, действительно ли это.
user202729
Это разрешено, поскольку Jelly обрабатывает списки строк. Вы можете добавить ÇŒṘили ÇYв нижний колонтитул, чтобы визуализировать результат. Кроме того, вместо полной программы вы можете сказать, что ваша отправка представляет собой монадическую ссылку, которая возвращает, а не печатает, что делает ее автоматически действительной.
г-н Xcoder
2

Pyth ,  32  31 байт

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

Попробуй это здесь! или Проверьте все контрольные примеры. (с использованием симпатичной печатиj)

Как это работает

Это полная программа, которая принимает данные от STDIN. Это для 32-байтовой версии. Я скоро обновлю.

* R \ #_ M. ++ msmgk + hSQ * dc-eSQhSQTQTZ ~ Полная программа.

         m T ~ Отображение над [0, 10) с помощью var d.
           m Q ~ Отображение ввода с помощью var k.
            г ~ выше или равно?
             k ~ Текущий элемент ввода, k.
              + hSQ * dc-eSQhSQT ~ Разобьем это на части:
               hSQ ~ Самый низкий элемент списка ввода.
              + ~ Плюс:
                  * dc-eSQhSQT ~ Мы разберем это на несколько частей:
                  * ~ Умножение.
                   d ~ Текущий элемент [0, 10), d.
                    c T ~ Поплавковое деление на 10 из:
                     -eSQhSQ ~ Разница между максимумом и минимумом
                                        из списка ввода.
          сумма Посчитайте количество правдивых результатов.
        + Z ~ Добавить 0.
      . + ~ Получить дельты.
    _M ~ Получает -delta для каждой дельты в списке выше.
  \ # ~ Буквенный символ "#".
* R ~ Векторизация умножения. При желании вы можете
                                    используйте j, чтобы присоединиться к новым строкам (как это делает ссылка).
                                  ~ Вывод неявно.
Мистер Xcoder
источник
2

Древесный уголь , 31 байт

≔I⪪S,θEχ×#ΣEθ⁼ι⌊⟦⁹⌊×χ∕⁻λ⌊θ⁻⌈θ⌊θ

Попробуйте онлайн! Ссылка на подробную версию кода. Ввод списков переменной длины кажется немного неудобным в Charcoal, поэтому мне пришлось обернуть список в массив, содержащий строку. Объяснение:

   S                            Input string
  ⪪ ,                           Split on commas
 I                              Cast elements to integer
≔    θ                          Assign to variable q
      Eχ                        Map from 0 to 9
           Eθ                   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
Нил
источник
2

Фортран 2003, 263 байта

Я написал его на GNU gfortran 5.4.0 и скомпилировал без каких-либо дополнительных флагов.

Он читает из STDIN по одному значению за раз и печатает в STDOUT.

Здесь это идет:

программа h; реальная, размещаемая :: a (:); символ f * 9; allocate (a (0)); do; read (*, *, end = 8) r; a = [a, r]; enddo; 9 формат ("(", i0, "(" "#" "))")
8 a = (a-minval (a)) + эпсилон (1.); A = потолок (10 * a / maxval (a)); do i = 1,10; j = количество (a == i); если (J == 0) печать *, если (J == 0) цикл; записи (е, 9) J;
печать f; enddo; конец

Нецензурное объяснение: (Я не знаю, может ли «гольф» применяться к фортрану, но в любом случае: P)

программа h
реальный, выделяемый :: a (:)! Создайте выделяемый массив, чтобы мы могли динамически перераспределять
символ f * 9! Массив символов для форматирования вывода
выделить (а (0))! Сначала выделите «а»
делать
  читать (*, *, end = 8) r! Читайте из STDIN. Если EOF, идет к 8, в противном случае
  a = [a, r]! Добавляется к "а"
ENDDO
9 формат ("(", i0, "(" "#" "))")! Метка формата
8 a = (a-minval (a)) + эпсилон (1.)! (8) Нормализует (добавляет эпсилон, чтобы избежать индексации нуля)
a = потолок (10 * a / maxval (a))! Нормализация и умножение на количество бинов
сделать я = 1,10! Цикл на всех бункерах
  j = считать (a == i)! Подсчет количества вхождений
  если (j == 0) напечатать *! Если нет, печатает пустую строку
  если (j == 0) цикл! И пропускает остаток цикла
  написать (е, 9) j! В противном случае записывает количество (j) для печати этикетки
  печать F! И печатает на STDOUT
ENDDO
конец

Интересный факт: я сделал похожий код только вчера, чтобы проверить мою реализацию генератора случайных чисел Вейбулла, так что для этого потребовалась лишь небольшая адаптация :)

Фелипе Олейник
источник
1

Perl 5, 102 байта

$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);
Денис Ибаев
источник
1

q / kdb +, 52 байта

Решение:

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

Попробуйте онлайн! (Обратите внимание, что канал TIO - это 44-байтовый порт K (oK) этого решения, поскольку для q / kdb + нет TIO).

Примеры:

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
,"#"
"####"
"#########"
"############"
"######"
"#########################"
""
""
"###########"
,"#"

Объяснение:

Большая часть кода используется для создания сегментов, в которые binпомещаются входные данные.

{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)
streetster
источник
0

Желе , 19 байт

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

Попробуйте онлайн!

Это основано на моем ответе APL на исходную проблему, который я опубликую после завершения этого конкурса.

Как? (Я не умею объяснять вещи)

_Ṃµ÷Ṁ×⁵Ḟ«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
Zachary
источник