Alfabet Histogram

33

Diberikan kalimat input yang terdiri dari satu kata atau lebih [a-z]+dan nol atau lebih spasi , menghasilkan histogram ASCII-art (grafik batang) dari distribusi huruf dari kalimat input.

Histogram harus ditata secara horizontal, yaitu dengan tombol huruf di bagian bawah dalam urutan abjad dari kiri ke kanan, dengan sumbu Y berlabel 1-dan setiap 5 unit. Sumbu Y harus merupakan kelipatan terkecil dari lima yang setidaknya setinggi bilah tertinggi, dan harus sejajar kanan. Sumbu X dilabeli dengan huruf input, tanpa ada celah di antara keduanya. Misalnya, input a bb ddharus memiliki label abddan tidak ab d, melewatkan c. Bilah sendiri dapat dibuat dari karakter ASCII yang konsisten - Saya akan menggunakan Xdi sini dalam contoh saya.

test example

5-

   X
   X   X
1-XXXXXXXX
  aelmpstx

Karena ada tiga e, dua t, dan satu almsx.

Lebih banyak contoh:

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 dan Aturan

  • Input dapat diambil dalam format apa pun yang masuk akal dan dengan metode apa pun yang praktis . Ini juga berarti Anda dapat mengambil input dalam huruf besar semua, jika itu lebih masuk akal untuk kode Anda.
  • Leading / trailing newlines atau spasi putih lainnya adalah opsional, asalkan karakternya berbaris dengan tepat.
  • Program lengkap atau fungsi dapat diterima. Jika suatu fungsi, Anda dapat mengembalikan output daripada mencetaknya.
  • Output bisa ke konsol, dikembalikan sebagai daftar string, dikembalikan sebagai string tunggal, dll.
  • Celah standar dilarang.
  • Ini adalah sehingga semua aturan golf biasa berlaku, dan kode terpendek (dalam byte) menang.
AdmBorkBork
sumber
3
Saya pikir ini akan menjadi grafik batang daripada histogram, karena ini adalah data kategorikal dan bukan numerik, tapi saya lebih suka pedantic.
Giuseppe
apakah input dijamin tidak kosong?
dzaima
2
Hanya menjadi liontin, tapi ini bukan histogram , ini bagan batang. Masih merupakan tantangan yang menyenangkan!
caird coinheringaahing
4
Pendekatan Tuftian akan membuat bar keluar dari karakter yang diwakili dan tidak memiliki baris label terpisah.
dmckee
2
Karakter histogram harus konsisten, tetapi di seluruh kasus atau dalam setiap kasus?
Adám

Jawaban:

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

Cobalah online!

table melakukan pengangkatan berat di sini, menyatukan karakter, menyortirnya, dan mengembalikan jumlah mereka.

Segala sesuatu yang lain hanya memastikan offset yang tepat untuk dicetak, yang merupakan karya "nyata" dari tantangan ascii-art.

Terima kasih kepada @dylnan karena menunjukkan bug.

Terima kasih kepada @rturnbull untuk scanpendekatannya, menjatuhkan 2 byte.

Giuseppe
sumber
237 byte
rturnbull
@rturnbull Saya berhasil merobohkan beberapa byte lagi setelah itu, terima kasih!
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

Cobalah online!


Saya yakin ini dapat ditingkatkan , tetapi untuk saat ini, ini harus bagus mengingat dibuat di sed, di mana Anda tidak memiliki aritmatika atau penyortiran asli. Jadi saya berbohong, ini tidak cukup baik, jadi saya meningkatkan (menulis ulang) dengan 212 byte, dengan tip mengenai algoritma pengurutan dari sapi dukun , yang memberi saya ide untuk membuat konversi unary ke desimal lebih pendek juga.
Deskripsi pekerjaan dalam:

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

Ini mengurutkan input dan memisahkan grup dengan spasi. Ini bekerja dengan terlebih dahulu menambahkan alfabet huruf besar ditambah ruang yang dipisahkan oleh titik dua hingga akhir. Kemudian memindahkan setiap karakter di depan titik dua ke karakter yang cocok di belakang titik dua menggunakan substitusi case-insensitive dalam satu lingkaran. Huruf besar kemudian diganti dengan spasi dan string disalin ke ruang penyimpanan.

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

Loop ini berfungsi dengan mengurangi setiap ukuran grup karakter satu per satu, menambahkan garis asli yang diurutkan dan menambah penghitung unary setelah titik dua yang tersisa dari pengurutan. Itu loop sampai garis kosong dengan jumlah 5 * n + 1 tercapai (karena baris terakhir akhirnya menghasilkan spasi putih). Ruang pola terlihat seperti ini setelah loop:

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

Kemudian formatnya sebagai berikut:

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

Dan akhirnya, konverter unary ke desimal tetap:

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

Ini pada dasarnya menambahkan string di mana pengetahuan konversi. Anda dapat menafsirkannya sebagai: spasi: -> 1 dan 0-> 1-> 2-> 3-> 4-> 5-> 6-> 7-> 8-> 9-> I0. Ekspresi substitusi s/(.)I(.*\1(I?.))|;.*/\3\2/bekerja mirip dengan yang menyortir, mengganti karakter di depan saya [ (.)I] dengan karakter yang di sebelah yang dari depan saya di string konversi [ (.*\1(I?.))] dan jika tidak ada saya pergi, itu menghilangkan string yang ditambahkan [ |;.*]. Substitusi [ /\nI/s/^/ /Mg] menambahkan padding jika diperlukan.

Terima kasih kepada Sapi dukun untuk mengurangi ukuran oleh 26 byte dan untuk algoritma penyortiran yang lebih pendek.

Sed Sedih
sumber
Selamat datang di PPCG, dan jawaban pertama yang bagus!
Kritixi Lithos
Anda dapat menggunakan \w(mencocokkan karakter kata) di sejumlah tempat untuk menyimpan beberapa byte. Juga :b ... tbbisa dengan mudah menjadi s/\B\w/X/g. Anda dapat menghapus baris yang mengikutinya s/:/:,/g,, dengan memodifikasi substitusi sebelumnya. Anda dapat melihat goo.gl/JvD7Rs (disingkat tautan TIO ke program sed) untuk melihat apa yang saya maksud.
Kritixi Lithos
1
Anda dapat meningkatkan pada algoritma pengurutan, petunjuk: coba tambahkan zyx...cbake input.
Kritixi Lithos
Konverter unary ke desimal yang brilian! Hormat Anda setidaknya 30 byte lebih pendek dari yang ada di Tips untuk bermain golf di 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}

Cobalah online!

Membutuhkan ⎕IO←0

Cara terlalu banyak byte diselamatkan berkat Adam dan Sapi dukun !

dzaima
sumber
Untuk bagian terakhir, Anda dapat mencoba ⍵[⍋⍵]~' '(mengurutkan dan menghapus spasi sebelum melewati )
Kritixi Lithos
'X'/⍨≢∊⍕¨×
Adám
dan ⍵>0×⍵
Kritixi Lithos
TIO Anda memiliki Header yang tidak perlu.
Adám
2⌷⍴≢⍉dua kali
Adám
5

05AB1E , 58 47 byte

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

Cobalah online!

-11 byte terima kasih kepada @Emigna

Guci Gurita Ajaib
sumber
Mungkin ini bisa membantu? Tidak punya waktu untuk mengikat mereka tapi mungkin mereka bisa memberi inspirasi.
Emigna
@ Emigna saya akan melihat, pasti berbeda dari milik saya :).
Magic Gurita Guci
@Emigna 57 byte setelah saya menjahitnya ... mengingat saya tidak berusaha terlalu keras untuk mengoptimalkan. Cobalah online!
Magic Gurita Guci
47 byte dengan beberapa restrukturisasi dan optimalisasi.
Emigna
Surat-surat Anda tidak sejajar dengan X untuk input tertentu. 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()))

Cobalah online!

Penjelasan

Baris 2 menghitung nilai histogram dengan cara yang cukup mudah, membuang ' '.

Baris 3 menggunakan trik komputasi ceil(x/5)sebagai -(-x/5): kita membulatkan frekuensi maksimal hingga kelipatan 5 berikutnya menggunakan rumus -x/5*-5. Ini h.

Baris 4 adalah loop yang dihitung dari hbawah hingga 0inklusif, mencetak setiap baris:

  • Jika y%5==2>>ykami mencetak label. Inilah saatnya y∈ {1, 5, 10, 15, 20,…}

    (Rumus ini mungkin bisa lebih pendek. Kami hanya memerlukan sesuatu yang 1 atau Benar untuk {1, 5, 10, ...}, dan 0 atau Salah atau bahkan bilangan bulat negatif untuk semua nilai lainnya dari y.)

  • Kami membenarkan label (atau ruang kosong) menjadi len(`-h`)spasi: ini adalah penghematan satu byte yang rapi len(`h`)+1!

  • Kemudian, kita mencetak Xspasi dan spasi untuk baris ini (jika y≥ 1) atau huruf (jika y= 0), berjalan melalui pasangan nilai kunci ddalam urutan menaik.

Lynn
sumber
1
Kutu centang yang bagus dengan '%d-'%y*(y%5==2>>y). Apakah Anda keberatan jika saya menggunakannya dalam jawaban saya?
dylnan
-~-(y%5*~-y)berfungsi juga tetapi sayangnya itu satu byte lebih lama.
dylnan
2

Arang , 62 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Penjelasan:

≔E²⁷⟦⟧η

Buat daftar 27 daftar.

Fθ⊞§η⌕βιι

Dorong setiap karakter input ke daftar yang sesuai dengan posisinya dalam alfabet huruf kecil. Karakter non-huruf kecil didorong ke daftar ke-27.

≔⊟ηθ

Buang elemen ke-27 dari daftar.

≦Lη

Ambillah panjang semua elemen daftar.

P⭆β⎇§ηκιω

Cetak huruf kecil sesuai dengan elemen daftar bukan nol.

↑↑Φηι

Cetak elemen daftar yang bukan nol ke atas. Karena ini adalah array bilangan bulat, setiap bilangan bulat dicetak sebagai (sekarang vertikal), masing-masing dalam kolom terpisah.

F÷⁺⁹⌈η⁵«

Hitung jumlah tanda centang pada sumbu Y dan lewati.

≔∨×⁵ι¹ι

Hitung posisi tanda centang berikutnya.

J±¹±ι

Lompat ke tanda centang berikutnya.

←⮌⁺ι-

Cetak tanda centang terbalik dan kembali ke depan, secara efektif meluruskannya.

Neil
sumber
2

Jelly , 48 byte

Apa ladang ranjau yang harus dilalui!

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

Program lengkap yang mencetak hasilnya (sebagai tautan monadik akan menghasilkan daftar berisi karakter dan bilangan bulat dari [0,9])

Cobalah online! Atau lihat test-suite

Bagaimana?

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

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

Cobalah online!

Terimakasih untuk:

  • dylnan untuk -16 byte dengan padding yang kurang ketat
  • Lynn untuk -2 byte dengan mengumpulkan-x/5*-5
  • Kirill L. untuk -2 byte dengan mendapatkan elemen array unik dengan|[]
Nnnes
sumber
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;}

Cobalah online!

Kredit

Olivier Grégoire
sumber
@aoemica Benar. Aku telah memperbaikinya.
Olivier Grégoire
1
Tidak banyak, tetapi Anda dapat menghemat 2 byte. --m%5==0bisa jadi --m%5<1, karena Anda juga punya &m>0cek. Dan m<=d[a]?"x":" "bisa jadi m>d[a]?" ":"x".
Kevin Cruijssen
@KevinCruijssen 2 byte adalah 2 byte! Saya tidak berpikir ada banyak golf lagi, kecuali untuk algoritma yang berbeda.
Olivier Grégoire
1
1 byte lebih banyak dengan mengubah (--m%5<1|m==1)&m>0ke--m%5<1|m==1&&m>0
Kevin Cruijssen
1

Pyth, 65 byte

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

Coba di sini

Penjelasan

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.

sumber
1

JavaScript (Node.js) , 262 256 byte

* Terima kasih kepada @Shaggy karena mengurangi 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`
`

Cobalah online!

DanielIndie
sumber
Beberapa penghematan cepat yang dapat saya temukan di ponsel saya: 1.Ambil input sebagai array karakter individual, 2.Ganti x!=" "dengan x>" ".
Shaggy
3.Ganti m=0dengan i=m=0dan map((x,i)=>dengan map(x=>.
Shaggy
1

Python 2 , 249 224 219 215 205 197 187 188 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]

Cobalah online!

Mengembalikan daftar daftar karakter yang mewakili garis.

  • Menyimpan beberapa byte dengan menyertakan banyak spasi tambahan.
  • Punya yang tidak perlu map(list,yticks)di sana.
  • Ruang ganti diganti untuk menyimpan beberapa byte.
  • Saya pikir saya sedang menyortir tetapi saya tidak: +2 byte. Tetapi saya menyelamatkan satu secara mandiri pada saat yang sama. y==1diganti oleh y<2.
  • -6 byte terima kasih kepada Lynn dengan menggunakan '%d-'%y*(y%5==2>>y)alih-alih (`y`+'-')*(not y%5or y<2).

Sedikit tidak berbulu:

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

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

Termasuk 18 byte untuk using System.Linq;

Disimpan 6 byte berkat @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;}

Cobalah online!

Ian H.
sumber
Anda memiliki ruang j< m;yang dapat dihapus. Dan int i=0,jdapat ditempatkan seperti ,i=0,jsetelah int lainnya untuk total -4 byte. Anda harus memasukkan 18 byte untuk using System.Linq;...
Kevin Cruijssen
@KevinCruijssen Terima kasih, saya melewatkan ini. Dan saya menambahkan 18 byte.
Ian H.
+1 dari saya. Oh, dan Anda dapat menyimpan 2 byte lebih banyak dengan mengubah 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;}ke 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){...}. Cobalah online.
Kevin Cruijssen
@KevinCruijssen Itu benar-benar pintar, terima kasih!
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

Cobalah online!

Beranotasi:

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

Terima kasih kepada @IanM_Matrix karena telah menghemat 3 byte.

pengguna9549915
sumber
cat bdapat <bmenyimpan 3 karakter
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);}}

Input diambil dari baris perintah (argumen pertama). Menggunakan tanda seru alih-alih X untuk mengurangi ukuran kode lebih lanjut. Penghitung di sebelah kiri selalu tiga karakter.

Diuji dengan GCC dan dentang.

Simon
sumber
for(p=b[1];*p;p++)kemungkinan besar bisa for(p=b[1]-1;*++p;), main(int a,char **b)mungkin bisa golf m(a,b)char**b;.
Jonathan Frech
Karena a!=1akan menjadi boolean, a%5&&a!=1?harus setara dengan a%5&a!=1?atau a%5&&~-a.
Jonathan Frech
0

Excel VBA, 316 byte

Fungsi jendela langsung VBE Anonim yang mengambil input dari sel [A1]dan output ke jendela langsung 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

Versi Tidak Serigala

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

Cobalah online!

Xcali
sumber
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]

Cobalah online!

Ini mungkin bukan pendekatan byte-efisien di Python, tapi saya benar-benar ingin menyelesaikan ini dengan lambda "true one-liner".

Mengeluarkan daftar daftar karakter. Menyalahgunakan banyak baris dan spasi baru seperti halnya orang lain. Ini sebenarnya dapat dikurangi menjadi 174 byte jika dapat diterima untuk membungkus hasilnya di daftar lain, sehingga kami dapat mentransfer [0]pengindeksan terakhir ke footer.

Kirill L.
sumber
0

JavaScript (ES8), 200 byte

Mengambil input sebagai array karakter. Mengembalikan string.

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)

Cobalah online!

Berkomentar

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
sumber