Алфавитная гистограмма


33

Учитывая входное предложение, состоящее из одного или нескольких слов [a-z]+и нуля или нескольких пробелов , выведите гистограмму (гистограмму) в стиле ASCII распределения букв входного предложения.

Гистограмма должна быть расположена горизонтально, то есть с буквенным ключом вдоль основания в алфавитном порядке слева направо, с осью Y, помеченной 1-и каждые 5 единиц. Ось Y должна быть наименьшим кратным пяти, которая, по крайней мере, такая же высокая, как самая высокая полоса, и должна быть выровнена по правому краю. Ось X помечена входными буквами без пробелов между ними. Например, вход a bb ddдолжен иметь метку, abdа не ab dпропускать c. Сами столбцы могут быть сделаны из любого согласованного символа ASCII - я буду использовать Xздесь в своих примерах.

test example

5-

   X
   X   X
1-XXXXXXXX
  aelmpstx

Так как есть три e, два tи один из almsx.

Больше примеров:

the quick brown fox jumped over the lazy dogs

5-
      X         X
      X         X
     XX  X      X  X XX
1-XXXXXXXXXXXXXXXXXXXXXXXXXX
  abcdefghijklmnopqrstuvwxyz


now is the time for all good men to come to the aid of their country

10-
              X
              X
              X  X
      X       X  X
 5-   X       X  X
      X   X   X  X
      X  XX XXXX X
   XXXXX XXXXXXX X
 1-XXXXXXXXXXXXXXXXXX
   acdefghilmnorstuwy

a bb ccc dddddddddddd

15-


      X
      X
10-   X
      X
      X
      X
      X
 5-   X
      X
     XX
    XXX
 1-XXXX
   abcd

a bb ccccc

5-  X
    X
    X
   XX
1-XXX
  abc

I / O и правила

  • Входные данные могут быть приняты в любом разумном формате и любым удобным способом . Это также означает, что вы можете вводить данные в верхнем регистре, если это имеет больше смысла для вашего кода.
  • Лидирующие / завершающие символы новой строки или другие пробелы являются необязательными, при условии, что символы выстраиваются соответствующим образом.
  • Либо полная программа или функция приемлемы. Если функция, вы можете вернуть вывод, а не распечатать его.
  • Вывод может быть на консоль, возвращен в виде списка строк, возвращен в виде одной строки и т. Д.
  • Стандартные лазейки запрещены.
  • Это поэтому применяются все обычные правила игры в гольф, и выигрывает самый короткий код (в байтах).

3
Я думаю, что это будет гистограмма, а не гистограмма, так как это категориальные, а не числовые данные, но я в основном педантичен.
Джузеппе

вход гарантированно не является пустым?
Дзайма

2
Просто быть подвеской, но это не гистограмма , это гистограмма. Тем не менее, хороший вызов!
caird coinheringaahing

4
Туфтианский подход состоит в том, чтобы сделать столбцы из представленных символов и не иметь отдельной строки меток.
dmckee

2
Символ гистограммы должен быть согласованным, но для разных случаев или внутри каждого случая?
Адам

Ответы:



7

R , 239 230 байт

K=table(el(strsplit(gsub(" ","",scan(,"")),"")));m=matrix(" ",L<-sum(K|1)+1,M<-(M=max(K))+-M%%5+1);m[2:L,M]=names(K);m[1,M-g]=paste0(g<-c(1,seq(5,M,5)),"-");m[1,]=format(m[1,],j="r");for(X in 2:L)m[X,M-1:K[X-1]]=0;write(m,1,L,,"")

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

table выполняет тяжелую работу здесь, унифицируя персонажей, сортируя их и возвращая их счета.

Все остальное просто обеспечивает правильные смещения для печати, что является «настоящей» работой для ascii-art.

Спасибо @dylnan за указание на ошибку.

Спасибо @rturnbull за scanподход, сбрасывающий 2 байта.



@rturnbull После этого мне удалось сбить еще несколько байтов, спасибо!
Джузеппе

6

gnu sed -r, 516 490 278 249 + 1 байт

s/$/:ABCDEFGHIJKLMNOPQRSTUVWXYZ /
:a
s/(.)(:.*\1)/\2\1/I
ta
s/[A-Z]+/ /g
h
z
:b
s/ \w/ /g
G
s/:/&I/g
/:II{5}+ *$/M!bb
s/[a-z]/X/g
G
s/:(I{5}+|I)\b/0\1-/g
s/:I*/  /g
s/ (\w)\1*/\1/g
s/$/; 10123456789I0/
:c
s/(.)I(.*\1(I?.))|;.*/\3\2/
/\nI/s/^/ /Mg
tc

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


Я уверен, что это можно улучшить , но на данный момент, это должно быть хорошо, учитывая, что это сделано в sed, где у вас нет нативной арифметики или сортировки. Так что я солгал, этого было недостаточно, поэтому я улучшил (переписал) его еще на 212 байт, с подсказкой относительно алгоритма сортировки из кряка Корова , что дало мне идею сделать унарное преобразование в десятичное также более коротким.
Описание внутренней работы:

s/$/:ABCDEFGHIJKLMNOPQRSTUVWXYZ /
:a
s/(.)(:.*\1)/\2\1/I
ta
s/[A-Z]+/ /g
h
z

Это сортирует входные данные и разделяет группы пробелами. Это работает, сначала добавляя прописные буквы алфавита плюс пробел, разделенный двоеточием в конце. Затем он перемещает каждый символ перед двоеточием на соответствующий символ за двоеточием, используя в цикле замену без учета регистра. Затем заглавные буквы заменяются пробелами, а строка копируется в пробел.

:b
s/ \w/ /g
G
s/:/&I/g
/:II{5}+ *$/M!bb

Этот цикл работает, уменьшая размер каждой группы символов по одному, добавляя отсортированную исходную строку и увеличивая унарные счетчики после двоеточия, оставшегося от сортировки. Он зацикливается до тех пор, пока не будет достигнута пустая строка с номером 5 * n + 1 (поскольку последняя строка в конечном итоге приводит к пробелам). Пространство шаблона выглядит примерно так после цикла:

:IIIIII           
:IIIII           
:IIII           
:III  e         
:II  ee     t    
:I a eee l m p s tt x   

Затем следует форматирование:

s/[a-z]/X/g            # makes bars consistent
G                      # appends line that becomes x-axis
s/:(I{5}+|I)\b/0\1-/g  # moves zero in front of line 1 or 5-divisible
                       # lines for the decimal conversion and adds -
s/:I*/  /g             # removes numbers from other lines
s/ (\w)\1*/\1/g        # collapses groups of at least 1 into 1
                       # character, deleting the space before it
                       # so that only size-0-groups have spaces

И, наконец, остается одинарный в десятичном виде:

s/$/; 10123456789I0/
:c
s/(.)I(.*\1(I?.))|;.*/\3\2/
/\nI/s/^/ /Mg
tc

Это в основном добавляет строку, где знание преобразования. Вы можете интерпретировать это как: пробел: -> 1 и 0-> 1-> 2-> 3-> 4-> 5-> 6-> 7-> 8-> 9-> I0. Выражение подстановки s/(.)I(.*\1(I?.))|;.*/\3\2/работает подобно сортировке, заменяя символы перед символом I [ (.)I] символом, который находится рядом с символом перед символом I в строке преобразования [ (.*\1(I?.))], и если я не оставил I, он удаляет добавленная строка [ |;.*]. Подстановка [ /\nI/s/^/ /Mg] добавляет заполнение, если это необходимо.

Спасибо Корову кряку за уменьшение размера на 26 байт и за более короткий алгоритм сортировки.


Добро пожаловать в PPCG и приятного первого ответа!
Kritixi Lithos

Вы можете использовать \w(соответствует символам слова) в нескольких местах, чтобы сохранить несколько байтов. И :b ... tbможет просто стать s/\B\w/X/g. Вы можете удалить строку, которая следует за ней, s/:/:,/gизменив предыдущие замены. Вы можете посмотреть на goo.gl/JvD7Rs (сокращенная ссылка TIO на программу sed), чтобы понять, что я имею в виду.
Критиси Литос

1
Вы можете улучшить алгоритм сортировки, подсказка: попробуйте добавить zyx...cbaк входу.
Критиси Литос

Блестящий унарный в десятичный преобразователь! Ваш по крайней мере на 30 байт короче, чем тот, что
указан в Совете

5

Dyalog APL , 109 97 96 95 93 88 байт

{⊖(⍉r),⍨⍕↑(⊂'')@{1@0~⍵∊1,5×⍵}⍳≢⍉↑r←↑r,⍨⊂' -','   - '⍴⍨5×⌈5÷⍨≢1↓⍉↑r←↓{⍺,∊⍕¨0×⍵}⌸⍵[⍋⍵]∩⎕A}

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

требует ⎕IO←0

Путь слишком много байт сохранены благодаря адаму и Корове кри !


Для последнего бита, вы можете попробовать ⍵[⍋⍵]~' '(сортирует и удаляет пробелы, прежде чем проходить )
Kritixi Lithos

'X'/⍨≢∊⍕¨×
Адам

и ⍵>0×⍵
Критиси Литос

Ваша ссылка TIO имеет ненужный заголовок.
Адам

2⌷⍴≢⍉дважды
Адам

5

05AB1E , 58 47 байтов

áê©S¢Z5‰`Ā+L5*1¸ì'-«ð5×ý#À¦Áí.Bís'X×ζ‚ζJR»,®3ú,

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

-11 байт благодаря @Emigna


Может быть, это может помочь? Нет времени связывать их вместе, но, может быть, они могут дать вдохновение.
Эминья

@ Emigna Я посмотрю, определенно отличается от моего :).
Волшебная Урна Осьминога

@Emigna 57 байт после того, как я его прошил ... учитывая, что я не слишком старался оптимизировать. Попробуйте онлайн!
Волшебная Урна Осьминога

47 байт с некоторой реструктуризацией и оптимизацией.
Эминья,

Ваши письма не совпадают с X для определенных входных данных. tio.run/##AVUAqv8wNWFiMWX//…
mbomb007

3

Python 2 , 192 байта

s=input()
d={c:s.count(c)for c in s if' '<c}
h=-max(d.values())/5*-5
for y in range(h,-1,-1):print('%d-'%y*(y%5==2>>y)).rjust(len(`-h`))+''.join(('X '[y>v],k)[y<1]for k,v in sorted(d.items()))

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

объяснение

Строка 2 вычисляет значения гистограммы довольно простым способом, отбрасывая ' '.

Строка 3 использует хитрость вычислений ceil(x/5)как -(-x/5): мы округляем максимальную частоту до следующего кратного 5, используя формулу -x/5*-5. Это h.

Строка 4 - это цикл, который отсчитывает от hнуля до 0включающего, печатая каждую строку:

  • Если y%5==2>>yмы напечатаем этикетку. Это когда y∈ {1, 5, 10, 15, 20,…}

    (Эта формула может быть короче. Нам просто нужно что-то 1 или True для {1, 5, 10,…} и 0 или False или даже отрицательное целое число для всех других значений y.)

  • Мы выравниваем по правому краю метку (или пробел) в len(`-h`)пробелах: это аккуратное однобайтовое сохранение len(`h`)+1!

  • Затем мы печатаем либо Xпробелы для этой строки (если y≥ 1), либо буквы (если y= 0), пропуская пары ключ-значение dв порядке возрастания.


1
Хороший тик с '%d-'%y*(y%5==2>>y). Вы не возражаете, если я воспользуюсь этим в своем ответе?
Дилнан

-~-(y%5*~-y)тоже работает, но, к сожалению, на один байт длиннее.
Дилнан

2

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

≔E²⁷⟦⟧ηFθ⊞§η⌕βιι≔⊟ηθ≦LηP⭆β⎇§ηκιω↑↑ΦηιF÷⁺⁹⌈η⁵«≔∨×⁵ι¹ιJ±¹±ι←⮌⁺ι-

Попробуйте онлайн! Ссылка на подробную версию кода. Объяснение:

≔E²⁷⟦⟧η

Создайте список из 27 списков.

Fθ⊞§η⌕βιι

Вставьте каждый входной символ в список, соответствующий его позиции в строчном алфавите. Не строчные символы попадают в 27-й список.

≔⊟ηθ

Откажитесь от 27-го элемента списка.

≦Lη

Возьмите длины всех элементов списка.

P⭆β⎇§ηκιω

Выведите строчные буквы, соответствующие ненулевым элементам списка.

↑↑Φηι

Выведите ненулевые элементы списка вверх. Поскольку это массив целых чисел, каждое целое число печатается как (теперь вертикальная) строка, каждая в отдельном столбце.

F÷⁺⁹⌈η⁵«

Подсчитайте количество отметок на оси Y и зациклите их.

≔∨×⁵ι¹ι

Рассчитайте положение следующей отметки.

J±¹±ι

Перейти к следующей отметке.

←⮌⁺ι-

Напечатайте метку в обратном направлении и обратно, эффективно выровняв ее по правому краю.


2

Желе , 48 байт

Какое минное поле пройти!

J’⁶D;”-Ɗ%5^ỊƲ?€Uz⁶ZU
ḟ⁶ṢµĠ¬;⁶$L%5Ɗ¿€;"@Qz⁶Ç;"$ṚY

Полная программа распечатывает результат (в виде монадической ссылки она возвращает список, содержащий символы и целые числа из [0,9])

Попробуйте онлайн! Или посмотрите набор тестов

Как?

J’⁶D;”-Ɗ%5^ỊƲ?€Uz⁶ZU - Link 1, get y-axis: list of columns (including x-axis & top-spaces)
J                    - range of length  [1,2,3,4,5,6,...,height+1] (+1 for x-axis)
 ’                   - decrement        [0,1,2,3,4,5,...] (line it up with the content)
             ?€      - if for €ach...
            Ʋ        - ...condition: last four links as a monad:
        %5           -   modulo by five
           Ị         -   insignificant? (1 for 0 and 1, else 0)
          ^          -   XOR (0 for 1 or multiples of 5 greater than 0, else 0)
  ⁶                  - ...then: literal space character
       Ɗ             - ...else: last three links as a monad:
   D                 -   decimal list of the number, e.g. 10 -> [1,0]
     ”-              -   literal '-' character
    ;                -   concatenate, e.g. [1,0,'-']
               U     - upend (reverse each)
                z⁶   - transpose with a filler of space characters
                  Z  - transpose
                   U - upend (i.e. Uz⁶ZU pads the left with spaces as needed)

ḟ⁶ṢµĠ¬;⁶$L%5Ɗ¿€;"@Qz⁶Ç;"$ṚY - Main link: list of characters
ḟ⁶                          - filter out space characters
  Ṣ                         - sort
   µ                        - start a new monadic chain, call that S
    Ġ                       - group indices of S by their values
     ¬                      - logical NOT (vectorises) (getting 0 for the X "characters")
             ¿€             - while for €ach...
            Ɗ               - ...condition: last three links as a monad:
         L                  -   length
          %5                -   modulo by five
        $                   - ...do: last two links as a monad:
      ;⁶                    -   concatenate a space character
                  Q         - deduplicate S (get the x-axis)
               ;"@          - zip with (") concatenation (;) with swapped arguments (@)
                   z⁶       - transpose a with filler of space characters
                        $   - last two links as a monad:
                     Ç      -   call last link (1) as a monad (get y-axis)
                      ;"    -   zip with concatenation (complete the layout)
                         Ṛ  - reverse (otherwise it'll be upside-down)
                          Y - join with newlines
                            - implicit print


2

Рубин , 250 248 234 188 173 157 153 байта

->s{a=s.scan(/\w/).sort|[]
m=-(c=a.map{|l|s.count l}).max/5*-5
m.downto(1).map{|i|(i%5<1||i<2?"#{i}-":'').rjust(m)+c.map{|l|l<i ?' ':?X}*''}<<' '*m+a*''}

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

Благодаря:

  • Дилнан для -16 байтов с менее строгим заполнением
  • Линн за -2 байта, округляя до-x/5*-5
  • Кирилл Л. за -2 байта, получая уникальные элементы массива с|[]

2

Java (JDK 10) , 296 байт

s->{int d[]=new int[26],m=0;char a;for(int c:s.getBytes())m=c>32&&++d[c-=65]>m?(d[c]+4)/5*5:m;String r=m+"-",z=r.replaceAll("."," ");for(;m>0;r+="\n"+(--m%5<1|m==1&&m>0?z.format("%"+~-z.length()+"s-",m):z))for(a=0;a<26;a++)r+=d[a]>0?m>d[a]?" ":"x":"";for(a=64;a++<90;)r+=d[a-65]>0?a:"";return r;}

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

кредиты


@aoemica Правильно. Я починил это.
Оливье Грегуар,

1
Это немного, но вы можете сэкономить 2 байта. --m%5==0может быть --m%5<1, потому что у вас также есть &m>0чек. А m<=d[a]?"x":" "может быть m>d[a]?" ":"x".
Кевин Круйссен,

@KevinCruijssen 2 байта - это 2 байта! Я не думаю, что есть больше в гольфе, кроме другого алгоритма.
Оливье Грегуар,

1
Еще 1 байт, изменив (--m%5<1|m==1)&m>0на--m%5<1|m==1&&m>0
Кевин Круйссен

1

Pyth, 65 байт

J.tm+ed*hd\Xr8S-Qd)=+J*]d%_tlJ5_.e+?q<k2%k5.F"{:{}d}-",klQ*dhlQbJ

Попробуй здесь

объяснение

J.tm+ed*hd\Xr8S-Qd)=+J*]d%_tlJ5_.e+?q<k2%k5.F"{:{}d}-",klQ*dhlQbJ
J.tm+ed*hd\Xr8S-Qd)
     Get the bars.
                   =+J*]d%_tlJ5
     Round up the height to the next number that's 1 mod 5.
                               _.e+?q<k2%k5.F"{:{}d}-",klQ*dhlQbJ
     Stick the axis labels on.

1

JavaScript (Node.js) , 262 256 байт

* Спасибо @Shaggy за сокращение на 2 байта

a=>[...a].map(x=>x>" "&&(d=c[x]=(c[x]||x)+"X")[m]?m=d.length-1:0,c={},m=i=0)&&Object.keys(c).sort().map(x=>[...c[x].padEnd(m)].map((l,j)=>A[m-j-1]+=l),A=[...Array(m+=6-m%5)].map(x=>(++i>=m||((D=m-i)%5&&m-i^1)?"":D+"-").padStart((m+" ").length)))&&A.join`
`

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


Несколько быстрых сбережений, которые я могу заметить на своем телефоне: 1.примите ввод как массив отдельных символов, 2.замените x!=" "на x>" ".
Лохматый

3.Заменить m=0на i=m=0и map((x,i)=>с map(x=>.
Лохматый

1

Python 2 , 249 224 219 215 205 197 187 188 182 176 байт

def f(s):S=sorted(set(s)^{' '});C=map(s.count,S);P=max(C)+4;return zip(*(zip(*[('%d-'%y*(y%5==2>>y)).rjust(P)for y in range(P,0,-1)])+[(n*'#').rjust(P)for n in C]))+[[' ']*P+S]

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

Возвращает список списков символов, представляющих строки.

  • Сохранено несколько байтов, включая много лишних пробелов.
  • Было ненужное map(list,yticks)там.
  • Изменено заполнение пробела для сохранения некоторых байтов.
  • Я думал, что я сортирую, но я не был: +2 байта. Но я спас один независимо одновременно. y==1заменено на y<2.
  • -6 байт благодаря Линн , используя '%d-'%y*(y%5==2>>y)вместо (`y`+'-')*(not y%5or y<2).

Слегка разгульный

def f(s):
	S=sorted(set(s)^{' '})  # sorted list of unique letters (without ' ')
	C=map(s.count,S)        # count of each unique letter in the input
	P=max(C)+4              # used for padding and getting highest y tick
	B=[(n*'#').rjust(P)for n in C]     # create bars
	yticks = [('%d-'%y*(y%5==2>>y)).rjust(P)for y in range(P,0,-1)]  # create y ticks at 1 and multiples of 5
	yticks = zip(*yticks)                      # need y ticks as columns before combining with bars
	return zip(*(yticks+B))+[[' ']*P+S]        # zip ticks+bars then add row of sorted unique letters.

1

C # (.NET Core) , 344 340 338 + 18 байт

Включает 18 байтов для using System.Linq;

Сохранено 6 байтов благодаря @KevinCruijssen.

n=>{var l=n.Where(c=>c!=32).GroupBy(c=>c).OrderBy(c=>c.Key).ToDictionary(k=>k.Key,c=>c.Count());int h=(l.Values.Max()/5+1)*5,o=(h+"").Length+1,m=l.Keys.Count+o,t=h+1,i=0,j;var a=new string[t];for(string p,q;i<t;a[i++]=q)for(q=(p=i>0&i%5<1|i==1?i+"-":"").PadLeft(j=o);j<m;){var c=l.ElementAt(j++-o).Key;q+=i<1?c:l[c]>=i?'X':' ';}return a;}

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


У вас есть место, j< m;которое можно удалить. И int i=0,jможет быть размещен как ,i=0,jпосле других целых для всего -4 байта. Вы должны будете включить 18 байтов для using System.Linq;однако ..
Кевин Круйссен

@KevinCruijssen Спасибо, я пропустил это. И я добавил 18 байтов.
Ян Х.

+1 от меня. О, и вы можете сохранить еще 2 байта, изменив for(;i<t;){string p=i>0&i%5<1|i==1?i+"-":"",q=p.PadLeft(o);for(j=o;j<m;){...}a[i++]=q;}на for(string p,q;i<t;)for(p=i>0&i%5<1|i==1?i+"-":"",q=p.PadLeft(j=o);j<m;a[i++]=q){...}. Попробуйте онлайн.
Кевин Круйссен,

@KevinCruijssen Это действительно умно, спасибо!
Ян Х.

1

Bash + coreutils, 332 324 323 318 312 302 298 296 293 291 байт

c()(cut -d\  -f$@)
p=printf
cd `mktemp -d`
grep -o [^\ ]<<<$@|sort|uniq -c|c 7->a
sort -k2<a>b
r=$[`c 1 <a|sort -n|tail -1`+5]
s=${#r}
t()($p \ ;((i++<s))&&t;i=)
for((;--r;));{
((r%5&&r>1))&&t||$p %${s}s- $r;IFS='
'
for l in `<b`;{ ((r<=`c 1 <<<$l`))&&$p X||$p \ ;}
echo
}
t
c 2 <b|tr -d \\n

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

Аннотированный:

c()(cut -d\  -f$@)
p=printf              # saving a few bytes

cd `mktemp -d`        # for temp files

grep -o [^\ ]<<<$@    # grabs all non-space characters
    |sort|uniq -c     # get character frequency
    |c 7->a           # slightly hacky way of stripping leading spaces;
                      #     uniq -c adds 6 spaces in front of each line

sort -k2<a>b          # store frequencies sorted alphabetically in b

r=$[`                 # r = highest frequency +5:
    c 1 <a            #     get frequencies
    |sort -n|tail -1  #     get maximum frequency
    `+5]              #     +4 so at least one multiple of 5 is
                      #     labeled, +1 because r gets pre-decremented

s=${#r}                    # s = length of r as a string
t()($p \ ;((i++<s))&&t;i=) # pad line with s+1 spaces

for((;--r;));{         # while (--r != 0)
    ((r%5&&r>1))&&     # if r isn't 1 or a multiple of 5
        t||            #     then indent line 
        $p %${s}s- $r; # otherwise print right-aligned "${r}-"
        IFS='
'                      # newline field separator
    for l in `<b`;{          # for all letters and their frequencies:
        ((r<=`c 1 <<<$l`))&& #     if frequency <= current height 
            $p X||           #         then print an X
            $p \ ;}          #     otherwise print a space
    echo
}
t # indent x-axis labels
c 2 <b|tr -d \\n # print alphabetically sorted characters

Спасибо @IanM_Matrix за сохранение 3 байтов.


cat bможет быть <bсохранение 3 символов
IanM_Matrix1

0

C, 201 байт

char c[256],*p,d;main(int a,char **b){for(p=b[1];*p;p++)++c[*p|32]>d&*p>64?d++:0;for(a=(d+4)/5*5;a+1;a--){printf(!a||a%5&&a!=1?"    ":"%3i-",a);for(d=96;++d>0;c[d]?putchar(a?32|c[d]>=a:d):0);puts(p);}}

Ввод берется из командной строки (первый аргумент). Использует восклицательные знаки вместо X для дальнейшего уменьшения размера кода. Счетчик слева всегда состоит из трех символов.

Протестировано с GCC и Clang.


for(p=b[1];*p;p++)Скорее всего, возможно for(p=b[1]-1;*++p;), main(int a,char **b)может быть в гольф m(a,b)char**b;.
Джонатан Фрех

Поскольку a!=1будет логическим, a%5&&a!=1?должно быть эквивалентно a%5&a!=1?или a%5&&~-a.
Джонатан Фрех

0

Excel VBA, 316 байт

Функция анонимного непосредственного окна VBE, которая принимает данные из ячейки [A1]и выводит их в непосредственное окно VBE.

For i=1To 26:Cells(2,i)=Len(Replace([Upper(A1)],Chr(i+64),11))-[Len(A1)]:Next:m=-5*Int(-[Max(2:2)]/5):l=Len(m)+1:For i=-m To-1:?Right(Space(l) &IIf(i=-1Xor i Mod 5,"",-i &"-"),l);:For j=1To 26:?IIf(Cells(2,j),IIf(Cells(2, j) >= -i, "X", " "),"");:Next:?:Next:?Spc(l);:For i=1To 26:?IIf(Cells(2,i),Chr(i+96),"");:Next

Безголовая версия

Public Sub bar_graph()
    For i = 1 To 26
        ''  gather the count of the letter into cells
        Cells(2, i) = Len(Replace([Upper(A1)], Chr(i + 64), 11)) - [Len(A1)]
    Next
    m = -5 * Int(-[Max(2:2)] / 5)   ''  get max bar height
    l = Len(m) + 1                  ''  length of `m` + 1
    For i = -m To -1
        ''  print either a label or free space (y-axis)
        Debug.Print Right(Space(l) & IIf((i = -1) Xor i Mod 5, "", -i & "-"), l);
        For j = 1 To 26
            ''  print 'X' or ' ' IFF the count of the letter is positive
            If Cells(2, j) Then Debug.Print IIf(Cells(2, j) >= -i, "X", " ");
        Next
        Debug.Print                 ''  print a newline
    Next
    Debug.Print Spc(l);             ''  print spaces
    For i = 1 To 26
        ''  print the letters that were used (x-axis)
        Debug.Print IIf(Cells(2, i), Chr(i + 96), "");
    Next
End Sub


0

Python 3 , 177 байт

lambda s:[[list(("%d-"%i*(i%5==2>>i)).rjust(len(q)))+["* "[s.count(c)<i]for c in q]for i in range(max(map(s.count,q))+4,0,-1)]+[[" "]*len(q)+q]for q in[sorted(set(s)-{' '})]][0]

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

Возможно, это не самый эффективный байтовый подход в Python, но я действительно хотел решить эту проблему с помощью «истинной однострочной» лямбды.

Выводит список списков символов. Злоупотребляет несколькими ведущими символами новой строки и пробелами, как и все остальные. Фактически он может быть дополнительно уменьшен до 174 байтов, если допустимо перенести результат в другой список, чтобы мы могли перенести окончательную [0]индексацию в нижний колонтитул.


0

JavaScript (ES8), 200 байт

Принимает ввод как массив символов. Возвращает строку.

s=>(s.sort().join``.replace(/(\w)\1*/g,s=>a.push(s[0]+'X'.repeat(l=s.length,h=h<l?l:h)),h=a=[]),g=y=>y--?(y<2^y%5?'':y+'-').padStart(`${h}_`.length)+a.map(r=>r[y]||' ').join``+`
`+g(y):'')(h+=5-~-h%5)

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

комментарии

s => (                    // s[] = input array of characters (e.g. ['a','b','a','c','a'])
  s.sort()                // sort it in lexicographical order (--> ['a','a','a','b','c'])
  .join``                 // join it (--> 'aaabc')
  .replace(/(\w)\1*/g,    // for each run s of consecutive identical letters (e.g. 'aaa'):
    s => a.push(          //   push in a[]:
      s[0] +              //     the letter, which will appear on the X-axis
      'X'.repeat(         //     followed by 'X' repeated L times
        L = s.length,     //     where L is the length of the run (--> 'aXXX')
        h = h < L ? L : h //     keep track of h = highest value of L
    )),                   //   initialization:
    h = a = []            //     h = a = empty array (h is coerced to 0)
  ),                      // end of replace() (--> a = ['aXXX','bX','cX'] and h = 3)
  g = y =>                // g = recursive function taking y
    y-- ?                 //   decrement y; if there's still a row to process:
      (                   //     build the label for the Y-axis:
        y < 2 ^ y % 5 ?   //       if y != 1 and (y mod 5 != 0 or y = 0):
          ''              //         use an empty label
        :                 //       else:
          y + '-'         //         use a mark
      ).padStart(         //     pad the label with leading spaces,
        `${h}_`.length    //     using the length of the highest possible value of y
      ) +                 //     (padStart() is defined in ECMAScript 2017, aka ES8)
      a.map(r => r[y]     //     append the row,
                 || ' ')  //     padded with spaces when needed
      .join`` + `\n` +    //     join it and append a linefeed
      g(y)                //     append the result of a recursive call
    :                     //   else:
      ''                  //     stop recursion
)(h += 5 - ~-h % 5)       // call g() with h adjusted to the next multiple of 5 + 1
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.