Alphabet-Histogramm

33

Bei einem Eingabesatz, der aus einem oder mehreren Wörtern [a-z]+und null oder mehreren Leerzeichen besteht , wird ein ASCII-Histogramm (Balkendiagramm) der Buchstabenverteilung des Eingabesatzes ausgegeben.

Das Histogramm muss horizontal angeordnet sein, dh mit der Buchstabentaste am unteren Rand in alphabetischer Reihenfolge von links nach rechts, mit einer Y-Achse beschriftet 1-und alle 5 Einheiten. Die Y-Achse muss das kleinste Vielfache von fünf sein, das mindestens so hoch wie der höchste Balken ist, und muss rechtsbündig ausgerichtet sein. Die X-Achse ist mit den eingegebenen Buchstaben beschriftet, ohne Lücken dazwischen. Zum Beispiel a bb ddsollte die Eingabe eine Bezeichnung haben abdund nicht ab ddie c. Die Balken selbst können aus einem beliebigen konsistenten ASCII-Zeichen bestehen - ich werde dies Xhier in meinen Beispielen verwenden.

test example

5-

   X
   X   X
1-XXXXXXXX
  aelmpstx

Da gibt es drei e, zwei tund eins von almsx.

Mehr Beispiele:

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 und Regeln

  • Die Eingabe kann in jedem vernünftigen Format und mit jeder geeigneten Methode erfolgen . Dies bedeutet auch, dass Sie Eingaben in Großbuchstaben vornehmen können, wenn dies für Ihren Code sinnvoller ist.
  • Führende / nachfolgende Zeilenumbrüche oder andere Leerzeichen sind optional, sofern die Zeichen richtig ausgerichtet sind.
  • Es ist entweder ein vollständiges Programm oder eine Funktion zulässig. Bei einer Funktion können Sie die Ausgabe zurückgeben, anstatt sie zu drucken.
  • Die Ausgabe kann an die Konsole erfolgen, als Liste von Zeichenfolgen zurückgegeben werden, als einzelne Zeichenfolge zurückgegeben werden usw.
  • Standardlücken sind verboten.
  • Dies ist daher gelten alle üblichen Golfregeln, und der kürzeste Code (in Byte) gewinnt.
AdmBorkBork
quelle
3
Ich denke, dies wäre eher ein Balkendiagramm als ein Histogramm, da es eher kategoriale als numerische Daten sind, aber ich bin meistens pedantisch.
Giuseppe
Ist die Eingabe garantiert nicht leer?
Dzaima
2
Nur ein Anhänger zu sein, aber dies ist kein Histogramm , es ist ein Balkendiagramm. Trotzdem eine schöne Herausforderung!
Caird Coinheringaahing
4
Ein tuftianischer Ansatz wäre, die Balken aus den dargestellten Zeichen zu machen und keine separate Beschriftungszeile zu haben.
DMCKEE
2
Das Histogramm muss konsistent sein, aber fallübergreifend oder in jedem Fall?
Adám

Antworten:

7

R , 239 230 Bytes

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

Probieren Sie es online!

table erledigt das schwere Heben hier, macht die Charaktere einzigartig, sortiert sie und gibt ihre Zählungen zurück.

Alles andere dient nur dazu, sicherzustellen, dass die Offsets für den Druck geeignet sind.

Vielen Dank an @dylnan für den Hinweis auf einen Fehler.

Vielen Dank an @rturnbull für den scanAnsatz, 2 Bytes zu löschen .

Giuseppe
quelle
237 bytes
rturnbull
@rturnbull Ich habe danach noch ein paar Bytes geschafft, danke!
Giuseppe
6

gnu sed -r, 516 490 278 249 + 1 Byte

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

Probieren Sie es online!


Ich bin mir sicher, dass dies verbessert werden kann , aber im Moment sollte dies gut sein, wenn man bedenkt, dass es in sed erstellt wurde, wo Sie keine native Arithmetik oder Sortierung haben. Also habe ich gelogen, das war nicht gut genug, also habe ich es um weitere 212 Bytes verbessert (umgeschrieben), mit einem Tipp zum Sortieralgorithmus von Cows quack , der mir die Idee gab, die Umrechnung von Einzahl auf Dezimalzahl zu verkürzen.
Beschreibung des Innenlebens:

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

Dadurch werden die Eingaben sortiert und die Gruppen durch Leerzeichen getrennt. Dies funktioniert, indem zuerst ein Großbuchstabe und ein durch einen Doppelpunkt getrenntes Leerzeichen an das Ende angehängt werden. Anschließend wird jedes Zeichen vor dem Doppelpunkt zu einem übereinstimmenden Zeichen hinter dem Doppelpunkt verschoben, wobei die Groß- / Kleinschreibung in einer Schleife nicht berücksichtigt wird. Die Großbuchstaben werden dann durch Leerzeichen ersetzt, und die Zeichenfolge wird in das Haltezeichen kopiert.

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

In dieser Schleife wird jede Zeichengruppengröße um eins verringert, die sortierte ursprüngliche Zeile angehängt und die unären Zähler nach dem von der Sortierung verbleibenden Doppelpunkt erhöht. Es wird eine Schleife ausgeführt, bis eine leere Zeile mit der Zahl 5 * n + 1 erreicht ist (da die letzte Zeile letztendlich Leerzeichen enthält). Der Musterraum sieht nach der Schleife ungefähr so ​​aus:

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

Dann folgt die Formatierung:

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

Und schließlich bleibt der Konverter von Unär zu Dezimal:

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

Grundsätzlich wird eine Zeichenfolge angehängt, in der das Wissen über die Konvertierung vorhanden ist. Sie können es interpretieren als: Leerzeichen: -> 1 und 0-> 1-> 2-> 3-> 4-> 5-> 6-> 7-> 8-> 9-> I0. Der Ersetzungsausdruck s/(.)I(.*\1(I?.))|;.*/\3\2/funktioniert ähnlich wie der Sortierungsausdruck. Er ersetzt die Zeichen vor I [ (.)I] durch das Zeichen, das in der Konversionszeichenfolge [ (.*\1(I?.))] neben dem Zeichen vor I steht. Wenn kein I mehr vorhanden ist, wird es entfernt die angehängte Zeichenfolge [ |;.*]. Die Ersetzung [ /\nI/s/^/ /Mg] fügt bei Bedarf eine Auffüllung hinzu.

Dank Cows quack für die Reduzierung der Größe um 26 Bytes und für den kürzeren Sortieralgorithmus.

Sad Sed
quelle
Willkommen bei PPCG und schöne erste Antwort!
Kritixi Lithos
Sie können \w(entspricht Wortzeichen) an mehreren Stellen verwenden, um einige Bytes zu speichern. Auch :b ... tbkann einfach werden s/\B\w/X/g. Sie können die darauf folgende Zeile entfernen s/:/:,/g, indem Sie die früheren Ersetzungen ändern. Sie können goo.gl/JvD7Rs (verkürzter TIO-Link zum sed-Programm) ansehen, um zu sehen, was ich meine.
Kritixi Lithos
1
Sie können den Sortieralgorithmus verbessern. Tipp: Versuchen Sie, zyx...cbaan die Eingabe anzuhängen.
Kritixi Lithos
Genialer Konverter von Unär zu Dezimal! Ihre ist mindestens 30 Bytes kürzer als die in Tipps zum Golfen in sed
Kritixi Lithos
5

Dyalog APL , 109 97 96 95 93 88 Bytes

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

Probieren Sie es online!

Benötigt ⎕IO←0

Art und Weise zu viele Bytes gespeichert dank Adám und Kühe Quack !

dzaima
quelle
Für das letzte Bit können Sie versuchen ⍵[⍋⍵]~' '(sortiert und entfernt Leerzeichen, bevor Sie durch )
Kritixi Lithos
'X'/⍨≢∊⍕¨×
Adám
und ⍵>0×⍵
Kritixi Lithos
Ihr TIO-Link hat einen unnötigen Header.
Adám
2⌷⍴≢⍉zweimal
Adám
5

05AB1E , 58 47 Bytes

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

Probieren Sie es online!

-11 Bytes dank @Emigna

Magische Kraken-Urne
quelle
Vielleicht dies helfen könnte? Sie haben keine Zeit, sie zusammenzubinden, aber vielleicht können sie Inspiration geben.
Emigna
@Emigna Ich werde mal schauen, definitiv anders als meine :).
Magic Octopus Urn
@Emigna 57 Bytes nachdem ich es genäht habe ... da ich mich nicht zu sehr bemüht habe, es zu optimieren. Probieren Sie es online!
Magic Octopus Urn
47 Bytes mit einigen Umstrukturierungen und Optimierungen.
Emigna
Ihre Buchstaben stimmen bei bestimmten Eingaben nicht mit den X überein. tio.run/##AVUAqv8wNWFiMWX//…
mbomb007
3

Python 2 , 192 Bytes

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

Probieren Sie es online!

Erläuterung

Zeile 2 berechnet die Histogrammwerte relativ einfach und verwirft sie ' '.

Zeile 3 verwendet den Rechentrick ceil(x/5)als -(-x/5): Wir runden die Maximalfrequenz mit der Formel auf das nächste Vielfache von 5 auf -x/5*-5. Das ist h.

Zeile 4 ist eine Schleife, die von hunten nach 0einschließlich zählt und jede Zeile druckt:

  • Wenn y%5==2>>ywir ein Etikett drucken. Dies ist, wenn y∈ {1, 5, 10, 15, 20,…}

    (Diese Formel könnte möglicherweise kürzer sein. Für {1, 5, 10,…} brauchen wir nur 1 oder True und für alle anderen Werte von . 0 oder False oder sogar eine negative Ganzzahl y.)

  • Wir richten das Label (oder den leeren Raum) mit der rechten Maustaste in len(`-h`)Leerzeichen ein: Dies ist eine ordentliche Einsparung von einem Byte len(`h`)+1!

  • Dann drucken wir entweder die Buchstaben Xund Leerzeichen für diese Zeile (wenn y≥ 1) oder die Buchstaben (wenn y= 0) und durchlaufen die Schlüssel-Wert-Paare din aufsteigender Reihenfolge.

Lynn
quelle
1
Schöne Zeckenkreation mit '%d-'%y*(y%5==2>>y). Stört es Sie, wenn ich das in meiner Antwort verwende?
Dylnan
-~-(y%5*~-y)funktioniert auch, aber es ist leider ein Byte länger.
Dylnan
2

Holzkohle , 62 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

≔E²⁷⟦⟧η

Erstellen Sie eine Liste mit 27 Listen.

Fθ⊞§η⌕βιι

Schieben Sie jedes eingegebene Zeichen in die Liste, die seiner Position im Kleinbuchstaben entspricht. Nicht-Kleinbuchstaben werden in die 27. Liste verschoben.

≔⊟ηθ

Verwerfen Sie das 27. Element der Liste.

≦Lη

Nimm die Länge aller Elemente der Liste.

P⭆β⎇§ηκιω

Drucken Sie die Kleinbuchstaben aus, die Listenelementen ungleich Null entsprechen.

↑↑Φηι

Drucken Sie die Nicht-Null-Listenelemente nach oben. Da es sich um ein Array von Ganzzahlen handelt, wird jede Ganzzahl als (jetzt vertikale) Zeile in einer separaten Spalte ausgegeben.

F÷⁺⁹⌈η⁵«

Berechnen Sie die Anzahl der Teilstriche auf der Y-Achse und wiederholen Sie diese.

≔∨×⁵ι¹ι

Berechnen Sie die Position des nächsten Häkchens.

J±¹±ι

Zum nächsten Häkchen springen.

←⮌⁺ι-

Drucken Sie das Häkchen umgekehrt und von hinten nach vorne aus, und richten Sie es dabei richtig aus.

Neil
quelle
2

Jelly , 48 Bytes

Was für ein Minenfeld zu durchqueren!

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

Ein vollständiges Programm, das das Ergebnis druckt (als monadischer Link würde es eine Liste mit Zeichen und ganzen Zahlen von zurückgeben [0,9])

Probieren Sie es online! Oder schauen Sie sich die Testsuite an

Wie?

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
quelle
2

Ruby , 250 248 234 188 173 157 153 Bytes

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

Probieren Sie es online!

Dank an:

  • Dylnan für -16 Bytes mit weniger strenger Polsterung
  • Lynn für -2 Bytes durch Aufrunden mit-x/5*-5
  • Kirill L. für -2 Bytes durch Abrufen eindeutiger Array-Elemente mit|[]
Nnnes
quelle
2

Java (JDK 10) , 296 Byte

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

Probieren Sie es online!

Credits

Olivier Grégoire
quelle
@aoemica Richtig. Ich habe es repariert.
Olivier Grégoire
1
Es ist nicht viel, aber Sie können 2 Bytes sparen. --m%5==0kann sein --m%5<1, weil du auch den &m>0scheck hast . Und m<=d[a]?"x":" "kann sein m>d[a]?" ":"x".
Kevin Cruijssen
@ KevinCruijssen 2 Bytes sind 2 Bytes! Ich denke, es gibt nicht mehr viel zum Golfen, außer für einen anderen Algorithmus.
Olivier Grégoire
1
1 weiteres Byte durch Ändern (--m%5<1|m==1)&m>0auf--m%5<1|m==1&&m>0
Kevin Cruijssen
1

Pyth, 65 Bytes

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

Probieren Sie es hier aus

Erläuterung

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.
Gedächtnisstütze
quelle
1

JavaScript (Node.js) , 262 256 Byte

* Danke an @Shaggy für die Reduzierung um 2 Bytes

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

Probieren Sie es online!

DanielIndie
quelle
Ein paar schnelle Einsparungen, die ich auf meinem Handy feststellen kann: 1.Nehmen Sie die Eingabe als Array einzelner Zeichen entgegen, 2.Ersetzen x!=" "durch x>" ".
Shaggy
3.Ersetzen Sie m=0mit i=m=0und map((x,i)=>mit map(x=>.
Shaggy
1

Python 2 , 249 224 219 215 205 197 187 188 182 176 Bytes

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]

Probieren Sie es online!

Gibt eine Liste mit Listen von Zeichen zurück, die Zeilen darstellen.

  • Einige Bytes wurden durch das Einfügen von zusätzlichen Leerzeichen gespart.
  • Hatte ein unnötiges map(list,yticks)drin.
  • Das Auffüllen von Speicherplatz wurde geändert, um einige Bytes zu sparen.
  • Ich dachte, ich sortiere, aber ich war nicht: +2 Bytes. Aber ich speicherte eine unabhängig zur gleichen Zeit. y==1ersetzt durch y<2.
  • -6 Bytes dank Lynn mit '%d-'%y*(y%5==2>>y)anstelle von (`y`+'-')*(not y%5or y<2).

Leicht ungolfed:

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
quelle
1

C # (.NET Core) , 344 340 338 + 18 Byte

Beinhaltet 18 Bytes für using System.Linq;

6 Bytes gespart dank @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;}

Probieren Sie es online!

Ian H.
quelle
Sie haben ein Leerzeichen j< m;, das entfernt werden kann. Und int i=0,jkann wie ,i=0,jnach den anderen Ints für insgesamt -4 Bytes platziert werden. Sie müssen die 18 Bytes für die using System.Linq;jedoch enthalten ..
Kevin Cruijssen
@ KevinCruijssen Danke, ich habe diese verpasst. Und ich habe die 18 Bytes hinzugefügt.
Ian H.
+1 von mir. Oh, und Sie können durch Ändern 2 weitere Bytes speichern 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;}zu 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){...}. Probieren Sie es online aus.
Kevin Cruijssen
@ KevinCruijssen Das ist wirklich klug, danke!
Ian H.
1

Bash + Coreutils, 332 324 323 318 312 302 298 296 293 291 Bytes

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

Probieren Sie es online!

Kommentiert:

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

Vielen Dank an @IanM_Matrix für das Speichern von 3 Bytes.

user9549915
quelle
cat bkönnte <b3 Zeichen
speichern
0

C 201 Bytes

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

Die Eingabe erfolgt über die Befehlszeile (erstes Argument). Verwendet Ausrufezeichen anstelle von X, um die Codegröße weiter zu verringern. Der linke Zähler ist immer drei Zeichen lang.

Getestet mit GCC und clang.

Simon
quelle
for(p=b[1];*p;p++)kann höchstwahrscheinlich sein for(p=b[1]-1;*++p;), main(int a,char **b)könnte wahrscheinlich zu golfen sein m(a,b)char**b;.
Jonathan Frech
Da a!=1wird boolesch sein, a%5&&a!=1?sollte gleich a%5&a!=1?oder sein a%5&&~-a.
Jonathan Frech
0

Excel VBA, 316 Bytes

Eine anonyme VBE-Direktfensterfunktion, die Eingaben von der Zelle [A1]und Ausgaben in das VBE-Direktfenster übernimmt .

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

Ungolfed Version

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
quelle
0

Perl 5 -n , 198 168 Bytes

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

Probieren Sie es online!

Xcali
quelle
0

Python 3 , 177 Bytes

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]

Probieren Sie es online!

Dies ist möglicherweise nicht der byteeffizienteste Ansatz in Python, aber ich wollte dies unbedingt mit einem "echten Einzeiler" -Lambda lösen.

Gibt eine Liste von Zeichenlisten aus. Missbrauch mehrerer führender Zeilenumbrüche und Leerzeichen wie jeder andere auch. Es kann tatsächlich weiter auf 174 Bytes reduziert werden, wenn es akzeptabel ist, das Ergebnis in eine andere Liste zu setzen, damit wir die endgültige [0]Indizierung in die Fußzeile übertragen können.

Kirill L.
quelle
0

JavaScript (ES8), 200 Byte

Nimmt die Eingabe als Array von Zeichen. Gibt eine Zeichenfolge zurück.

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)

Probieren Sie es online!

Kommentiert

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
quelle