Istogramma Alfabeto


33

Data una frase di input composta da una o più parole [a-z]+e zero o più spazi , genera un istogramma di arte ASCII (grafico a barre) della distribuzione delle lettere della frase di input.

L'istogramma deve essere disposto orizzontalmente, cioè con il tasto lettera lungo il fondo in ordine alfabetico da sinistra a destra, con un asse Y etichettato 1-e ogni 5 unità. L'asse Y deve essere il più piccolo multiplo di cinque che è alto almeno quanto la barra più alta e deve essere allineato a destra. L'asse X è etichettato con le lettere di input, senza spazi vuoti tra. Ad esempio, l'input a bb dddovrebbe avere un'etichetta abde non ab dsaltare la c. Le barre stesse possono essere costituite da qualsiasi carattere ASCII coerente: userò Xqui nei miei esempi.

test example

5-

   X
   X   X
1-XXXXXXXX
  aelmpstx

Dal momento che ci sono tre e, due te uno di almsx.

Altri esempi:

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 e regole

  • L'input può essere preso in qualsiasi formato ragionevole e con qualsiasi metodo conveniente . Questo significa anche che puoi prendere l'input in maiuscolo, se questo ha più senso per il tuo codice.
  • Le linee guida iniziali / finali o altri spazi bianchi sono opzionali, a condizione che i caratteri siano allineati in modo appropriato.
  • È accettabile un programma completo o una funzione. Se una funzione, è possibile restituire l'output anziché stamparlo.
  • L'output può essere sulla console, restituito come un elenco di stringhe, restituito come singola stringa, ecc.
  • Sono vietate le scappatoie standard .
  • Si tratta di quindi si applicano tutte le normali regole del golf e vince il codice più breve (in byte).

3
Penso che questo sarebbe un grafico a barre piuttosto che un istogramma, dato che sono dati categorici piuttosto che numerici, ma per lo più sono pedante.
Giuseppe,

l'ingresso è garantito come non vuoto?
dzaima,

2
Essere solo un ciondolo, ma questo non è un istogramma , è un grafico a barre. Comunque una bella sfida!
caird coinheringaahing l'

4
Un approccio tuftiano sarebbe quello di rendere le barre dei personaggi rappresentati e non avere una riga di etichetta separata.
dmckee,

2
Il carattere dell'istogramma deve essere coerente, ma tra i casi o all'interno di ciascun caso?
Adám,

Risposte:



7

R , 239 230 byte

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

Provalo online!

table fa il sollevamento pesante qui, unificando i personaggi, ordinandoli e restituendo i loro conteggi.

Tutto il resto è semplicemente garantire che gli offset siano adatti alla stampa, che è il lavoro "reale" di una sfida di arte ascii.

Grazie a @dylnan per aver segnalato un bug.

Grazie a @rturnbull per l' scanapproccio, facendo cadere 2 byte.



@rturnbull Sono riuscito a chiudere qualche altro byte dopo, grazie!
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

Provalo online!


Sono sicuro che questo può essere migliorato , ma per ora, questo dovrebbe essere buono considerando che è fatto in sed, dove non hai aritmetica o ordinamento nativo. Quindi ho mentito, questo non era abbastanza buono, quindi l'ho migliorato (riscritto) di altri 212 byte, con un suggerimento riguardante l'algoritmo di ordinamento dal ciarlatano di Cows , che mi ha dato l'idea di rendere più breve anche la conversione da unario a decimale.
Descrizione dei meccanismi interni:

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

Questo ordina l'input e separa i gruppi con spazi. Funziona aggiungendo prima un alfabeto maiuscolo più lo spazio separato da due punti alla fine. Quindi sposta ogni personaggio davanti ai due punti in un personaggio corrispondente dietro i due punti usando una sostituzione senza distinzione tra maiuscole e minuscole in un ciclo. Le lettere maiuscole vengono quindi sostituite da spazi e la stringa viene copiata nello spazio di trattenimento.

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

Questo ciclo funziona riducendo di uno la dimensione di ciascun gruppo di caratteri, aggiungendo la linea originale ordinata e incrementando i contatori unari dopo i due punti rimasti dall'ordinamento. Fa un ciclo fino a quando non viene raggiunta una riga vuota con un numero di 5 * n + 1 (poiché l'ultima riga alla fine risulta in uno spazio bianco). Lo spazio del modello è simile al seguente dopo il ciclo:

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

Quindi la formattazione segue:

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

E infine, il convertitore da unario a decimale rimane:

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

In sostanza aggiunge una stringa in cui si trova la conoscenza della conversione. Puoi interpretarlo come: spazio: -> 1 e 0-> 1-> 2-> 3-> 4-> 5-> 6-> 7-> 8-> 9-> I0. L'espressione di sostituzione s/(.)I(.*\1(I?.))|;.*/\3\2/funziona in modo simile a quella di ordinamento, sostituendo i caratteri di fronte a I [ (.)I] con il carattere che si trova accanto a quello dalla parte anteriore di I nella stringa di conversione [ (.*\1(I?.))] e se non è rimasto alcun I, rimuove la stringa aggiunta [ |;.*]. La sostituzione [ /\nI/s/^/ /Mg] aggiunge il riempimento, se necessario.

Grazie al ciarlatano Cows per la riduzione delle dimensioni di 26 byte e per l'algoritmo di ordinamento più breve.


Benvenuto in PPCG e bella prima risposta!
Kritixi Lithos,

È possibile utilizzare \w(corrisponde a caratteri di parole) in un numero di posizioni per salvare alcuni byte. Inoltre :b ... tbpuò semplicemente diventare s/\B\w/X/g. Puoi rimuovere la linea che la segue s/:/:,/g, modificando le sostituzioni precedenti. Puoi guardare goo.gl/JvD7Rs (collegamento TIO abbreviato al programma sed) per vedere cosa intendo.
Kritixi Lithos,

1
Puoi migliorare l'algoritmo di ordinamento, suggerimento: prova ad aggiungere zyx...cbal'input.
Kritixi Lithos,

Convertitore unario a decimale brillante! Il tuo è più breve di almeno 30 byte rispetto a quello di Consigli per giocare a golf a sed
Kritixi Lithos,

5

Dyalog APL , 109 97 96 95 93 88 byte

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

Provalo online!

Richiede ⎕IO←0

Way troppi byte salvato grazie a Adám e mucche ciarlatano !


Per l'ultimo bit, puoi provare ⍵[⍋⍵]~' '(ordina e rimuove gli spazi prima di passare )
Kritixi Lithos,

'X'/⍨≢∊⍕¨×
Adám,

e ⍵>0×⍵
Kritixi Lithos l'

Il tuo collegamento TIO ha un'intestazione non necessaria.
Adám,

2⌷⍴≢⍉due volte
Adám,

5

05AB1E , 58 47 byte

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

Provalo online!

-11 byte grazie a @Emigna


Forse questo potrebbe aiutare? Non ho tempo di legarli insieme, ma forse possono dare qualche ispirazione.
Emigna,

@Emigna darò un'occhiata, decisamente diversa dalla mia :).
Magic Octopus Urn l'

@Emigna 57 byte dopo averlo ricucito ... dato che non ho provato troppo a ottimizzare. Provalo online!
Magic Octopus Urn l'

47 byte con qualche ristrutturazione e ottimizzazione.
Emigna,

Le tue lettere non si allineano con le X per determinati input. tio.run/##AVUAqv8wNWFiMWX//…
mbomb007

3

Python 2 , 192 byte

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

Provalo online!

Spiegazione

La riga 2 calcola i valori dell'istogramma in modo abbastanza semplice, scartando ' '.

La linea 3 usa il trucco del calcolo ceil(x/5)come -(-x/5): arrotondiamo la frequenza massima al multiplo successivo di 5 usando la formula -x/5*-5. Questo è h.

La riga 4 è un conteggio in sequenza dal hbasso 0all'inclusione, che stampa ogni riga:

  • Se y%5==2>>ystampiamo un'etichetta. Questo è quando y∈ {1, 5, 10, 15, 20, ...}

    (Questa formula potrebbe essere più breve. Abbiamo solo bisogno di qualcosa che sia 1 o True per {1, 5, 10, ...} e 0 o False o anche un numero intero negativo per tutti gli altri valori di y.)

  • Giustifichiamo a destra l'etichetta (o spazio vuoto) in len(`-h`)spazi: questo è un bel risparmio di un byte len(`h`)+1!

  • Quindi, stampiamo o Xgli spazi per questa riga (se y≥ 1) o le lettere (se y= 0), scorrendo le coppie chiave-valore din ordine crescente.


1
Bella creazione di tick con '%d-'%y*(y%5==2>>y). Ti dispiace se lo uso nella mia risposta?
dylnan,

-~-(y%5*~-y)funziona anche ma sfortunatamente è un byte più lungo.
dylnan,

2

Carbone , 62 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Spiegazione:

≔E²⁷⟦⟧η

Crea un elenco di 27 elenchi.

Fθ⊞§η⌕βιι

Spingere ciascun carattere di input nell'elenco corrispondente alla sua posizione nell'alfabeto minuscolo. I caratteri non minuscoli vengono inseriti nell'elenco 27.

≔⊟ηθ

Elimina il 27 ° elemento dell'elenco.

≦Lη

Prendi le lunghezze di tutti gli elementi dell'elenco.

P⭆β⎇§ηκιω

Stampa le lettere minuscole corrispondenti agli elementi di elenco diversi da zero.

↑↑Φηι

Stampa gli elementi dell'elenco diversi da zero verso l'alto. Poiché si tratta di una matrice di numeri interi, ogni numero intero viene stampato come una linea (ora verticale), ciascuno in una colonna separata.

F÷⁺⁹⌈η⁵«

Calcola il numero di segni di spunta sull'asse Y e passaci sopra.

≔∨×⁵ι¹ι

Calcola la posizione del segno di spunta successivo.

J±¹±ι

Passa al segno di spunta successivo.

←⮌⁺ι-

Stampa il segno di spunta invertito e dalla parte anteriore a quella anteriore, allineandolo efficacemente a destra.


2

Gelatina , 48 byte

Che campo minato da attraversare!

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

Un programma completo che stampa il risultato (come collegamento monadico restituirebbe un elenco contenente caratteri e numeri interi da [0,9])

Provalo online! Oppure vedi la suite di test

Come?

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

Rubino , 250 248 234 188 173 157 153 byte

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

Provalo online!

Grazie a:

  • dylnan per -16 byte con imbottitura meno rigida
  • Lynn per -2 byte arrotondando con-x/5*-5
  • Kirill L. per -2 byte ottenendo elementi di matrice univoci con|[]

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

Provalo online!

Crediti


@aoemica Correct. L'ho riparato.
Olivier Grégoire,

1
Non è molto, ma puoi risparmiare 2 byte. --m%5==0può essere --m%5<1, perché hai anche il &m>0controllo. E m<=d[a]?"x":" "può essere m>d[a]?" ":"x".
Kevin Cruijssen,

@KevinCruijssen 2 byte sono 2 byte! Non credo che ci sia più molto da giocare a golf, tranne per un algoritmo diverso.
Olivier Grégoire,

1
1 byte in più cambiando (--m%5<1|m==1)&m>0in--m%5<1|m==1&&m>0
Kevin Cruijssen il

1

Pyth, 65 byte

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

Provalo qui

Spiegazione

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 byte

* Grazie a @Shaggy per la riduzione di 2 byte

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

Provalo online!


Un paio di rapidi risparmi che posso individuare sul mio telefono: 1.accetta input come una serie di singoli personaggi, 2.sostituisci x!=" "con x>" ".
Shaggy,

3.Sostituisci m=0con i=m=0e map((x,i)=>con map(x=>.
Shaggy,

1

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

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]

Provalo online!

Restituisce un elenco di elenchi di caratteri che rappresentano le linee.

  • Ho salvato alcuni byte includendo molto spazio bianco extra.
  • Aveva un inutile map(list,yticks)lì dentro.
  • Riempimento dello spazio modificato per salvare alcuni byte.
  • Pensavo di essere in ordine ma non lo ero: +2 byte. Ma ne ho salvato uno indipendentemente allo stesso tempo. y==1sostituito da y<2.
  • -6 byte grazie a Lynn usando '%d-'%y*(y%5==2>>y)invece di (`y`+'-')*(not y%5or y<2).

Leggermente non golfato:

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 byte

Include 18 byte per using System.Linq;

6 byte salvati grazie a @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;}

Provalo online!


Hai uno spazio j< m;che può essere rimosso. E int i=0,jpuò essere posizionato come ,i=0,jdopo gli altri ints per -4 byte in totale. Dovrai includere i 18 byte per using System.Linq;comunque ..
Kevin Cruijssen,

@KevinCruijssen Grazie, mi sono perso questi. E ho aggiunto i 18 byte.
Ian H.

+1 da me. Oh, e puoi salvare altri 2 byte cambiando 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;}in 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){...}. Provalo online.
Kevin Cruijssen,

@KevinCruijssen Questo è davvero intelligente, grazie!
Ian H.

1

Bash + coreutils, 332 324 323 318 312 302 298 296 293 291 byte

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

Provalo online!

commentata:

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

Grazie a @IanM_Matrix per il salvataggio di 3 byte.


cat bpotrebbe <bsalvare 3 caratteri
IanM_Matrix1

0

C, 201 byte

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

L'input viene preso dalla riga di comando (primo argomento). Utilizza punti esclamativi anziché X per ridurre ulteriormente le dimensioni del codice. Il contatore a sinistra è sempre lungo tre caratteri.

Testato con GCC e clang.


for(p=b[1];*p;p++)molto probabilmente può essere for(p=b[1]-1;*++p;), main(int a,char **b)potrebbe essere giocato a golf m(a,b)char**b;.
Jonathan Frech,

Poiché a!=1sarà booleano, a%5&&a!=1?dovrebbe essere equivalente a a%5&a!=1?o a%5&&~-a.
Jonathan Frech,

0

Excel VBA, 316 byte

Una funzione di finestra immediata VBE anonima che accetta input dalla cella [A1]e li invia alla finestra immediata di 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

Versione Ungolfed

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

Perl 5 -n , 198 168 byte

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

Provalo online!


0

Python 3 , 177 byte

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]

Provalo online!

Questo potrebbe non essere l'approccio più efficiente in byte in Python, ma volevo davvero risolverlo con un lambda "true one-liner".

Emette un elenco di elenchi di caratteri. Abusa di nuove linee e spazi principali come tutti gli altri. In realtà potrebbe essere ulteriormente ridotto a 174 byte se è accettabile racchiudere il risultato in un altro elenco, in modo da poter trasferire l' [0]indicizzazione finale nel piè di pagina.


0

JavaScript (ES8), 200 byte

Accetta input come una matrice di caratteri. Restituisce una stringa.

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)

Provalo online!

Commentate

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.