Десятирядкова гістограма


13

Це отвір-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.
користувач202729

Відповіді:



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='')

Спробуйте в Інтернеті!

Посилання - на версію коду, яка приймає розділений комою вхід; ця версія займає пробіл.

Читає від stdin, друкує до stdout.

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петля піклується про інше.


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.
користувач202729

Крім того, ви можете переключитися doubleна floatі lfна f, зберегти ще 2 байта. (принаймні, це працює на TIO)
користувач202729

@ user202729 для вашого першого коментаря: ні, ця ініціалізація потрібна всередині зовнішнього циклу кілька разів. floatМоже спрацювати, я не використовував його, оскільки це не "стандартний" тип з плаваючою комою в С і знижує точність, тому не впевнений, що це дозволено ...
Фелікс Палмен


3

Математика, 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<=#&]]])&


Спробуйте в Інтернеті!


Як це має працювати? TIO мають лише вихід тексту. (відповідь на частину "Денніс це виправить")
користувач202729

1
@ user202729 Ви справді вірите, що я про це не знаю? або ...
J42161217

2
Щоб вас не образити, але ви згадуєте, Range[0,9]поки я про це Range[0,10]безнадійно. Але це насправді не вдається Range[0,10]: TIO .
користувач202729

4
Ви використовували <=обидва кінці, що є правильним для останнього сегмента, але не для інших 9.
користувач202729

3
@ user202729 Гей! цей допоміг мені так само, як і ваша попередня інформація, що Діапазон [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>


Ви повинні бути в змозі зберегти пару байтів, перемістивши завдання iв дужки масиву, а потім - кома, що дозволяє видалити дужки навколо тіла функції карти: Спробуйте в Інтернеті!
Джастін Марінер

@JustinMariner справа, thx
edc65

Насправді ви можете зберегти ще один байт, якщо ви позбудетесь iта Math.minзнову використаєте його з псевдонімом: Спробуйте в Інтернеті!
Джастін Марінер


2

Желе , 21 байт

Монадічне посилання повертає список рядків.

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

Спробуйте в Інтернеті!


Хоча повернення списку рядків дозволено, відображений результат ні в якому разі не відокремлюється. Я не знаю, чи справедливо це.
користувач202729

Це дозволено, оскільки саме так 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.
            g ~ Вищий чи дорівнює?
             k ~ Поточний елемент входу, k.
              + hSQ * dc-eSQhSQT ~ Розбимо це на частини:
               hSQ ~ Найнижчий елемент вхідного списку.
              + ~ Плюс:
                  * dc-eSQhSQT ~ Ми розділимо це на кілька частин:
                  * ~ Множення.
                   d ~ Поточний елемент [0, 10), d.
                    c T ~ Поплавковий поділ на 10:
                     -eSQhSQ ~ Різниця між максимумом і мінімумом
                                        списку введення
          s ~ Сума. Підраховуйте кількість результатів, що надійні.
        + Z ~ Додайте 0.
      . + ~ Отримайте дельти.
    _M ~ Отримує -дельта для кожної дельти у списку вище.
  \ # ~ Буквальний символ "#".
* R ~ Векторизоване множення. За бажанням можна
                                    використовуйте j для приєднання нових рядків (як це робить посилання).
                                  ~ Висновок неявно.

2

Вугілля деревне , 31 байт

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Введення списків змінної довжини у вугільному вугіллі здається трохи незручним, тому мені довелося загортати список у масив, що містить рядок. Пояснення:

   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

Fortran 2003, 263 байти

Я написав це на GNU gfortran 5.4.0 і компілював без додаткових прапорів.

Він читає з STDIN, по одному значенню, і друкує до STDOUT.

Ось це іде:

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

Пояснення без гольфу: (Я не знаю, чи можна застосувати "гольф" до фортран, але в будь-якому випадку: P)

програма h
справжній, виділяється :: a (:)! Створіть виділений масив, щоб ми могли динамічно перерозподілятись
символ f * 9! Символьний масив для форматування виводу
виділити (a (0))! Виділіть спочатку "а" порожнім
робити
  читати (*, *, кінець = 8) r! Читайте з STDIN. Якщо EOF, переходить до 8, інакше
  a = [a, r]! Додається до "a"
ендодо
9 формат ("(", i0, "(" "#" "))")! Мітка формату
8 a = (a-minval (a)) + epsilon (1.)! (8) Нормалізує (додає епсилон, щоб уникнути нульової індексації)
a = стеля (10 * a / maxval (a))! Нормалізація та множення на кількість бункерів
чи я = 1,10! Цикл на всіх бункерах
  j = підрахунок (a == i)! Підрахунок кількості подій
  якщо (j == 0) друкувати *! Якщо немає, друкує порожній рядок
  якщо (j == 0) цикл! І пропускає решту петлі
  написати (f, 9) j! В іншому випадку записує кількість (j) на етикетку для друку
  друк f! І друкує до STDOUT
ендодо
кінець

Забавний факт: я зробив подібний код лише вчора, щоб перевірити свою реалізацію генератора випадкових чисел Weibull, тому для цього потрібна була лише невелика адаптація :)




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

Спробуйте в Інтернеті .

Безголівки:

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 - це порт байта K (oK) 44 байти, оскільки немає TIO для q / kdb +).

Приклади:

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)

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.