Histogram alfabetu

33

Biorąc pod uwagę zdanie wejściowe składające się z jednego lub więcej słów [a-z]+i zero lub więcej spacji , wypisz histogram ASCII-art (wykres słupkowy) rozkładu liter zdania wejściowego.

Histogram musi być ułożony poziomo, tzn. Z klawiszem litery u dołu w kolejności alfabetycznej od lewej do prawej, z etykietą na osi Y 1-i co 5 jednostek. Oś Y musi być najmniejszą wielokrotnością pięciu, która jest co najmniej tak wysoka jak najwyższy pasek i musi być wyrównana do prawej. Oś X jest oznaczona literami wejściowymi, bez przerw między nimi. Na przykład dane wejściowe a bb ddpowinny mieć etykietę, abda nie ab dpomijanie c. Same słupki mogą być wykonane z dowolnego spójnego znaku ASCII - użyję Xtutaj w moich przykładach.

test example

5-

   X
   X   X
1-XXXXXXXX
  aelmpstx

Ponieważ są trzy e, dwa ti jeden z nich almsx.

Więcej przykładów:

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 i reguły

  • Dane wejściowe można przyjmować w dowolnym rozsądnym formacie i dowolną dogodną metodą . Oznacza to również, że możesz pobierać dane wielkimi literami, jeśli ma to większy sens dla twojego kodu.
  • Wiodące / końcowe znaki nowej linii lub inne białe znaki są opcjonalne, pod warunkiem, że znaki są odpowiednio ustawione.
  • Dopuszczalny jest pełny program lub funkcja. Jeśli funkcja, możesz zwrócić dane wyjściowe zamiast je drukować.
  • Dane wyjściowe mogą być wysyłane do konsoli, zwracane jako lista ciągów, zwracane jako pojedynczy ciąg itp.
  • Standardowe luki są zabronione.
  • To jest więc obowiązują wszystkie zwykłe zasady gry w golfa, a wygrywa najkrótszy kod (w bajtach).
AdmBorkBork
źródło
3
Myślę, że byłby to raczej wykres słupkowy niż histogram, ponieważ są to dane raczej kategoryczne niż liczbowe, ale głównie pedantycznie.
Giuseppe,
czy wejście jest gwarantowane jako niepuste?
dzaima,
2
Po prostu wisiorek, ale to nie jest histogram , to wykres słupkowy. Nadal jednak niezłe wyzwanie!
caird coinheringaahing
4
Podejście tuftiańskie polegałoby na wykreślaniu pasków z reprezentowanych znaków i nieposiadaniu oddzielnego wiersza etykiety.
dmckee,
2
Znak histogramu musi być spójny, ale między przypadkami czy w każdym przypadku?
Adám

Odpowiedzi:

7

R , 239 230 bajtów

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

Wypróbuj online!

table wykonuje tu ciężkie podnoszenie, jednocząc postacie, sortując je i zwracając ich liczbę.

Wszystko inne zapewnia po prostu, że offset jest odpowiedni do drukowania, co jest „prawdziwym” dziełem ascii-artowego wyzwania.

Dzięki @dylnan za wskazanie błędu.

Dzięki @rturnbull za scanpodejście, upuszczenie 2 bajtów.

Giuseppe
źródło
237 bajtów
rturnbull
@rturnbull Udało mi się potem zrzucić jeszcze kilka bajtów, dzięki!
Giuseppe,
6

gnu sed -r, 516 490 278 249 + 1 bajtów

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

Wypróbuj online!


Jestem pewien, że można to poprawić , ale na razie powinno to być dobre, biorąc pod uwagę, że jest wykonane w wersji sed, w której nie masz natywnej arytmetyki ani sortowania. Więc skłamałem, to nie było wystarczająco dobre, więc poprawiłem (przepisałem) o kolejne 212 bajtów, z wskazówką dotyczącą algorytmu sortowania z szarlatanu krów , co dało mi pomysł, aby skrócić również konwersję jednostkową do dziesiętnej.
Opis działania wewnętrznego:

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

To sortuje dane wejściowe i oddziela grupy spacjami. Działa to najpierw poprzez dodanie na końcu wielkiej litery i spacji oddzielonych dwukropkiem. Następnie przesuwa każdy znak przed dwukropkiem do pasującego znaku za dwukropkiem, używając rozróżniania wielkości liter w pętli. Wielkie litery są następnie zastępowane spacjami, a ciąg jest kopiowany do spacji.

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

Ta pętla działa poprzez zmniejszenie wielkości każdej grupy znaków o jeden, dodanie posortowanej oryginalnej linii i zwiększenie jednostkowych liczników po dwukropku, który pozostał z sortowania. Zapętla się, dopóki nie zostanie osiągnięta pusta linia o liczbie 5 * n + 1 (ponieważ ostatnia linia ostatecznie powoduje spację). Przestrzeń wzorców wygląda mniej więcej tak po pętli:

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

Następnie formatowanie wygląda następująco:

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

I na koniec, konwerter od jednych do dziesiętnych pozostaje:

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

Zasadniczo dołącza ciąg znaków, w którym jest wiedza o konwersji. Możesz to interpretować jako: spacja: -> 1 i 0-> 1-> 2-> 3-> 4-> 5-> 6-> 7-> 8-> 9-> I0. Wyrażenie podstawienia s/(.)I(.*\1(I?.))|;.*/\3\2/działa podobnie do sortującego, zastępując znaki przed I [ (.)I] znakiem, który jest obok tego z I przed ciągiem konwersji [ (.*\1(I?.))], a jeśli nie ma I, usuwa dołączony ciąg [ |;.*]. W /\nI/s/^/ /Mgrazie potrzeby podstawienie [ ] dodaje dopełnienie.

Dzięki kwakowi krowy za zmniejszenie rozmiaru o 26 bajtów i za krótszy algorytm sortowania.

Sad Sed
źródło
Witamy w PPCG i niezła pierwsza odpowiedź!
Kritixi Lithos,
Możesz użyć \w(dopasowuje znaki słów) w wielu miejscach, aby zapisać niektóre bajty. :b ... tbMoże też po prostu stać się s/\B\w/X/g. Możesz usunąć linię, która następuje po nim, s/:/:,/gmodyfikując wcześniejsze podstawienia. Możesz spojrzeć na goo.gl/JvD7Rs (skrócony link TIO do programu sed), aby zobaczyć, co mam na myśli.
Kritixi Lithos
1
Możesz poprawić algorytm sortowania, wskazówka: spróbuj dołączyć zyx...cbado danych wejściowych.
Kritixi Lithos
Genialny konwerter od jednego do dziesiętnego! Twój jest co najmniej 30 bajtów krótszy niż ten w
Poradach
5

Dyalog APL , 109 97 96 95 93 88 bajtów

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

Wypróbuj online!

Wymaga ⎕IO←0

Sposób zbyt wiele bajtów zapisywane dzięki Adam i Krowy kwak !

dzaima
źródło
Na koniec możesz spróbować ⍵[⍋⍵]~' '(sortuje i usuwa spacje przed przejściem )
Kritixi Lithos
'X'/⍨≢∊⍕¨×
Adám
i ⍵>0×⍵
Kritixi Lithos
Twój link TIO ma niepotrzebny nagłówek.
Adám
2⌷⍴≢⍉dwa razy
Adám
5

05AB1E , 58 47 bajtów

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

Wypróbuj online!

-11 bajtów dzięki @Emigna

Urna Magicznej Ośmiornicy
źródło
Może to może pomóc? Nie mam czasu ich wiązać, ale może mogą dać trochę inspiracji.
Emigna,
@Emigna Spojrzę, zdecydowanie inny niż mój :).
Magic Octopus Urn
@Emigna 57 bajtów po tym, jak go zszyłem ... biorąc pod uwagę, że nie starałem się zbytnio optymalizować. Wypróbuj online!
Magic Octopus Urn
47 bajtów z pewną restrukturyzacją i optymalizacją.
Emigna,
Twoje litery nie pokrywają się z literami X dla niektórych danych wejściowych. tio.run/##AVUAqv8wNWFiMWX//…
mbomb007
3

Python 2 , 192 bajty

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()))

Wypróbuj online!

Wyjaśnienie

Wiersz 2 oblicza wartości histogramu w dość prosty sposób, odrzucając ' '.

Wiersz 3 wykorzystuje sztuczkę obliczeniową, ceil(x/5)ponieważ -(-x/5): zaokrąglamy maksymalną częstotliwość do następnej wielokrotności 5 za pomocą wzoru -x/5*-5. Jest h.

Linia 4 to pętla odliczająca hdo 0włączającej, drukująca każdy wiersz:

  • Jeśli y%5==2>>ywydrukujemy etykietę. To wtedy y∈ {1, 5, 10, 15, 20,…}

    (Ta formuła może być krótsza. Potrzebujemy tylko wartości 1 lub True dla {1, 5, 10,…} i 0 lub False lub nawet ujemnej liczby całkowitej dla wszystkich innych wartości y.)

  • Prawidłowo uzasadniamy etykietę (lub puste miejsce) len(`-h`)spacjami: jest to oszczędny, jednobajtowy oszczędność len(`h`)+1!

  • Następnie wypisujemy albo Xwiersze i spacje dla tego wiersza (jeśli y≥ 1) lub liter (jeśli y= 0), przeglądając pary klucz-wartość dw porządku rosnącym.

Lynn
źródło
1
Ładne tworzenie kleszczy z '%d-'%y*(y%5==2>>y). Czy masz coś przeciwko, jeśli użyję tego w mojej odpowiedzi?
dylnan,
-~-(y%5*~-y)też działa, ale niestety jest to o jeden bajt dłużej.
dylnan
2

Węgiel , 62 bajty

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

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:

≔E²⁷⟦⟧η

Utwórz listę 27 list.

Fθ⊞§η⌕βιι

Wciśnij każdy znak wejściowy do listy odpowiadający jego pozycji małymi literami. Znaki inne niż małe są wypychane na 27. listę.

≔⊟ηθ

Odrzuć 27 element listy.

≦Lη

Weź długości wszystkich elementów listy.

P⭆β⎇§ηκιω

Wydrukuj małe litery odpowiadające niezerowym elementom listy.

↑↑Φηι

Wydrukuj niezerowe elementy listy w górę. Ponieważ jest to tablica liczb całkowitych, każda liczba całkowita jest drukowana jako (teraz pionowa) linia, każda w osobnej kolumnie.

F÷⁺⁹⌈η⁵«

Oblicz liczbę znaczników na osi Y i zapętl nad nimi.

≔∨×⁵ι¹ι

Oblicz pozycję następnego znaku podziałki.

J±¹±ι

Przejdź do następnego znacznika.

←⮌⁺ι-

Wydrukuj znacznik odwrócony i odwrócony do przodu, skutecznie wyrównując go do prawej.

Neil
źródło
2

Galaretka , 48 bajtów

Cóż za pole minowe do przemierzenia!

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

Pełny program wypisujący wynik (jako monadyczny link zwróciłby listę zawierającą znaki i liczby całkowite [0,9])

Wypróbuj online! Lub zobacz zestaw testowy

W jaki sposób?

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
Jonathan Allan
źródło
2

Rubinowy , 250 248 234 188 173 157 153 bajtów

->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*''}

Wypróbuj online!

Dzięki:

  • dylnan dla -16 bajtów z mniej ścisłym wypełnieniem
  • Lynn dla -2 bajtów zaokrąglając w górę-x/5*-5
  • Kirill L. przez -2 bajty, uzyskując unikalne elementy tablicy za pomocą|[]
Nnnes
źródło
2

Java (JDK 10) , 296 bajtów

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;}

Wypróbuj online!

Kredyty

Olivier Grégoire
źródło
@aoemica Prawidłowo. Naprawiłem to.
Olivier Grégoire,
1
To niewiele, ale możesz zapisać 2 bajty. --m%5==0może być --m%5<1, ponieważ masz również &m>0czek. I m<=d[a]?"x":" "może być m>d[a]?" ":"x".
Kevin Cruijssen
@KevinCruijssen 2 bajty to 2 bajty! Nie sądzę, że jest już wiele do golfa, z wyjątkiem innego algorytmu.
Olivier Grégoire,
1
1 bajt więcej, zmieniając (--m%5<1|m==1)&m>0na--m%5<1|m==1&&m>0
Jeszcze Kevin Cruijssen
1

Pyth, 65 bajtów

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

Wypróbuj tutaj

Wyjaśnienie

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.

źródło
1

JavaScript (Node.js) , 262 256 bajtów

* Dzięki @Shaggy za zmniejszenie o 2 bajty

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`
`

Wypróbuj online!

DanielIndie
źródło
Kilka szybkich oszczędności mogę plama na moim telefonie: 1.Weź wejście jako tablica pojedynczych znaków, 2.wymienić x!=" "z x>" ".
Kudłaty
3.Wymień m=0się i=m=0i map((x,i)=>z map(x=>.
Kudłaty
1

Python 2 , 249 224 219 215 205 197 187 188 182 176 bajtów

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]

Wypróbuj online!

Zwraca listę list znaków reprezentujących linie.

  • Zaoszczędzono kilka bajtów, dodając wiele dodatkowych białych znaków.
  • Miałem tam niepotrzebne map(list,yticks).
  • Zmieniono dopełnianie miejsca, aby zaoszczędzić niektóre bajty.
  • Myślałem, że sortuję, ale nie byłem: +2 bajty. Ale uratowałem jedną niezależnie w tym samym czasie. y==1zastąpiony przez y<2.
  • -6 bajtów dzięki Lynn za pomocą '%d-'%y*(y%5==2>>y)zamiast (`y`+'-')*(not y%5or y<2).

Nieznacznie nie golfista:

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.
dylnan
źródło
1

C # (.NET Core) , 344 340 338 + 18 bajtów

Obejmuje 18 bajtów dla using System.Linq;

Zaoszczędź 6 bajtów dzięki @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;}

Wypróbuj online!

Ian H.
źródło
Masz miejsce, j< m;które można usunąć. I int i=0,jmoże być umieszczony tak jak ,i=0,jpo innych liczbach całkowitych dla -4 bajtów. Będziesz jednak musiał uwzględnić 18 bajtów, using System.Linq;jednak ...
Kevin Cruijssen
@KevinCruijssen Dzięki, tęskniłem za nimi. I dodałem 18 bajtów.
Ian H.,
+1 ode mnie Aha, możesz zaoszczędzić 2 bajty, zmieniając 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;}na 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){...}. Wypróbuj online.
Kevin Cruijssen
@KevinCruijssen To naprawdę sprytne, dzięki!
Ian H.,
1

Bash + coreutils, 332 324 323 318 312 302 298 296 293 291 bajtów

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

Wypróbuj online!

Adnotacja:

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

Dzięki @IanM_Matrix za oszczędność 3 bajtów.

użytkownik9549915
źródło
cat bmoże <bzapisywać 3 znaki
IanM_Matrix1
0

C, 201 bajtów

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

Dane wejściowe są pobierane z wiersza poleceń (pierwszy argument). Używa wykrzykników zamiast X, aby dodatkowo zmniejszyć rozmiar kodu. Licznik po lewej stronie ma zawsze trzy znaki.

Testowane z GCC i clang.

Szymon, Szymek
źródło
for(p=b[1];*p;p++)najprawdopodobniej może być for(p=b[1]-1;*++p;), main(int a,char **b)prawdopodobnie można grać w golfa m(a,b)char**b;.
Jonathan Frech,
Ponieważ a!=1będzie logiczny, a%5&&a!=1?powinien być równoważny z a%5&a!=1?lub a%5&&~-a.
Jonathan Frech,
0

Excel VBA, 316 bajtów

Anonimowa funkcja bezpośredniego okna VBE, która przenosi dane wejściowe z komórki [A1]i dane wyjściowe do bezpośredniego okna 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

Wersja bez golfa

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
Taylor Scott
źródło
0

Perl 5 -n , 198 168 bajtów

s/[a-z]/$\<++${$&}?$\=${$&}:0/eg;$\++while$\%5;$;=1+length$\++;printf"%$;s".'%s'x26 .$/,$\%5&&$\-1?"":"$\-",map$$_>=$\?X:$$_&&$",a..z while--$\;say$"x$;,map$$_&&$_,a..z

Wypróbuj online!

Xcali
źródło
0

Python 3 , 177 bajtów

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]

Wypróbuj online!

To może nie być najbardziej wydajne pod względem bajtów podejście w Pythonie, ale naprawdę chciałem rozwiązać to za pomocą lambda „prawdziwie jednowarstwowego”.

Wyświetla listę list znaków. Nadużywa wielu wiodących znaków nowej linii i spacji, tak jak wszyscy inni. Można faktycznie zmniejszyć go do 174 bajtów, jeśli dopuszczalne jest zawinięcie wyniku w inną listę, abyśmy mogli przenieść ostateczne [0]indeksowanie do stopki.

Kirill L.
źródło
0

JavaScript (ES8), 200 bajtów

Pobiera dane wejściowe jako tablicę znaków. Zwraca ciąg.

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)

Wypróbuj online!

Skomentował

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
Arnauld
źródło