字母直方图


33

给定一个包含一个或多个单词[a-z]+和零个或多个空格的输入句子,输出该输入句子的字母分布的ASCII艺术直方图(条形图)。

直方图必须水平放置,即字母键沿底部从左到右按字母顺序排列,Y轴标记为1-每5个单位。Y轴必须是5的最小倍数,且至少与最高的钢筋一样高,并且必须右对齐。X轴标有输入字母,两者之间没有间隙。例如,输入a bb dd应带有标签,abd而不要带有标签ab d,跳过c。条形图本身可以由任何一致的ASCII字符组成-我将X在示例中使用它们。

test example

5-

   X
   X   X
1-XXXXXXXX
  aelmpstx

由于存在三个e,两个t和一个almsx

更多示例:

the quick brown fox jumped over the lazy dogs

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


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

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

a bb ccc dddddddddddd

15-


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

a bb ccccc

5-  X
    X
    X
   XX
1-XXX
  abc

I / O和规则

  • 输入可以采用任何合理的格式和任何方便的方法。这也意味着您可以全大写输入,如果这对您的代码更有意义。
  • 前导/尾随换行符或其他空格是可选的,只要字符正确排列即可。
  • 完整的程序或功能都是可以接受的。如果是函数,则可以返回输出而不是打印输出。
  • 输出可以发送到控制台,以字符串列表形式返回,以单个字符串形式返回,等等。
  • 禁止出现标准漏洞
  • 这是因此所有常用的高尔夫规则都适用,并且最短的代码(以字节为单位)获胜。

3
我认为这将是条形图而不是直方图,因为它是分类数据,而不是数字数据,但是我主要是脚的。
朱塞佩

输入是否保证为非空?
dzaima

2
只是一个吊坠,但这不是直方图,而是条形图。仍然是一个不错的挑战!
Caird coinheringaahing

4
Tuftian方法将使条形由所表示的字符组成,并且不具有单独的标签行。
dmckee

2
直方图字符必须一致,但是在不同情况下还是在每种情况下?
亚当

Answers:



7

R239230字节

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

在线尝试!

table 在这里进行繁重的工作,对字符进行唯一化,排序以及返回计数。

其他一切都只是确保胶印正确地适合印刷,这是ascii艺术挑战的“真实”工作。

感谢@dylnan指出错误。

感谢@rturnbull提供的scan方法,删除了2个字节。



@rturnbull之后,我设法删除了几个字节,谢谢!
朱塞佩

6

GNU sed的 -r,516 490 278 249 + 1个字节

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

在线尝试!


我敢肯定,这是可以改善的,但就目前而言,考虑到它是在sed中完成的,这应该很好,因为您没有本地算术或排序功能。所以我撒了谎,这还不够好,所以我又将其改进(改写)了212个字节,并给出了Cows quack排序算法的提示,这也使我可以简化一进制到十进制的转换。
内部工作原理说明:

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

这对输入进行排序,并用空格分隔组。这是通过首先在末尾附加一个大写字母和由冒号分隔的空格来实现的。然后,使用不区分大小写的循环替换,将冒号前面的每个字符移动到冒号后面的匹配字符。然后将大写字母替换为空格,并将字符串复制到保留空间。

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

该循环通过将每个字符组的大小减小一个,然后附加已排序的原始行,并在排序后剩余的冒号之后增加一元计数器来工作。它将循环直到达到5 * n +1的空行(因为最后一行最终导致空白)。循环后的模式空间如下所示:

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

然后,格式如下:

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

最后,一元到十进制转换器仍然是:

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

它基本上在转换知识所在的位置附加一个字符串。您可以将其解释为:space:-> 1和0-> 1-> 2-> 3-> 4-> 5-> 6-> 7-> 8-> 9-> I0。替换表达式的s/(.)I(.*\1(I?.))|;.*/\3\2/工作方式与排序表达式类似,将I的[ (.)I] 前面的字符替换为转换字符串[ (.*\1(I?.))]中I的开头附近的字符,如果没有I,它将删除附加的字符串[ |;.*]。/\nI/s/^/ /Mg如果需要,替换[ ]将添加填充。

感谢Cows quack将大小减少了26个字节,并缩短了排序算法。


欢迎使用PPCG,这是一个不错的第一答案!
Kritixi Lithos

您可以\w在许多地方使用(匹配单词字符)以节省一些字节。也:b ... tb可以简单地成为s/\B\w/X/g。您可以s/:/:,/g通过修改先前的替换来删除其后的行。您可以查看goo.gl/JvD7Rs(缩短了与sed程序的TIO链接)以了解我的意思。
Kritixi Lithos '18 -4-12

1
您可以改进排序算法,提示:尝试附加zyx...cba到输入。
Kritixi Lithos '18

辉煌的一元到十进制转换器!您的
密码

5

Dyalog APL109 97 96 95 93 88字节

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

在线尝试!

需要 ⎕IO←0

太多字节保存感谢亚当奶牛嘎嘎


对于最后一点,您可以尝试⍵[⍋⍵]~' '(在通过之前对空格进行排序和删除
Kritixi Lithos

'X'/⍨≢∊⍕¨×
亚当

⍵>0×⍵
Kritixi Lithos

您的TIO链接具有不必要的标题。
亚当

2⌷⍴≢⍉两次
亚当

5

05AB1E58 47字节

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

在线尝试!

-11个字节,感谢@Emigna


也许可以帮助?没有时间将他们联系在一起,但也许他们可以给您一些启发。
Emigna '18 -4-11

@Emigna我来看一下,绝对不同于我的:)。
魔术章鱼缸

@Emigna我将其缝合后有57个字节...鉴于我并没有尽力优化。在线尝试!
魔术章鱼缸

47个字节,并进行了一些重组和优化。
Emigna '18 -4-12

对于某些输入,您的字母不与X对齐。tio.run/##AVUAqv8wNWFiMWX//…–
mbomb007

3

Python 2,192字节

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

在线尝试!

说明

第2行以一种相当简单的方式计算直方图的值,将其丢弃' '

第三行使用的计算技巧ceil(x/5)-(-x/5):我们使用公式将最大频率向上舍入到5的下一个倍数-x/5*-5。这是h

第4行是一个循环,从h0至上依次计数,并打印每一行:

  • 如果y%5==2>>y我们打印标签。这是y∈{1,5,10,15,20,…}

    (此公式可能更短。对于{1,5,10,…},我们只需要1True,对于。的所有其他值,则需要0False甚至是负整数y。)

  • 我们将标签(或空白区域)右对齐为len(`-h`)空格:这是一个整洁的1字节节省空间len(`h`)+1

  • 然后,我们X为该行(如果y≥1)或字母(如果y= 0)打印'和'空格,并按d升序遍历键值对。


1
不错的刻度线创建'%d-'%y*(y%5==2>>y)。您介意我在回答中使用它吗?
dylnan '18

-~-(y%5*~-y)也可以工作,但不幸的是它长了一个字节。
dylnan '18

2

木炭,62字节

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

在线尝试!链接是详细版本的代码。说明:

≔E²⁷⟦⟧η

创建一个包含27个列表的列表。

Fθ⊞§η⌕βιι

将每个输入字符推入与其在小写字母中的位置相对应的列表。非小写字符将被推入第27个列表。

≔⊟ηθ

丢弃列表的第27个元素。

≦Lη

取列表中所有元素的长度。

P⭆β⎇§ηκιω

打印对应于非零列表元素的小写字母。

↑↑Φηι

向上打印非零列表元素。由于这是一个整数数组,因此每个整数都打印为一条(现在是垂直的)行,每个行都在单独的列中。

F÷⁺⁹⌈η⁵«

计算Y轴上的刻度线数量并在其上循环。

≔∨×⁵ι¹ι

计算下一个刻度线的位置。

J±¹±ι

跳到下一个刻度线。

←⮌⁺ι-

前后颠倒打印刻度线,有效地使其右对齐。


2

果冻,48 个字节

真是个雷场!

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

全程序打印结果(作为单子链接,它将返回包含的字符和整数的列表[0,9]

在线尝试!或查看测试套件

怎么样?

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

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


2

红宝石250个 248 234 188 173 157 153字节

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

在线尝试!

谢谢:

  • dylnan用于-16个字节,填充不太严格
  • 通过舍入为-2字节的Lynn-x/5*-5
  • Kirill L. --2字节,通过使用获得唯一数组元素|[]

2

Java(JDK 10),296字节

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

在线尝试!

学分


@aoemica正确。我修好了它。
奥利维尔·格雷戈雷(OlivierGrégoire),

1
数量不多,但是您可以节省2个字节。--m%5==0可以是--m%5<1,因为您也有&m>0支票。并且m<=d[a]?"x":" "可以m>d[a]?" ":"x"
凯文·克鲁伊森

@KevinCruijssen 2个字节就是2个字节!我认为高尔夫不再是什么,除了算法不同之外。
奥利维尔·格雷戈尔(OlivierGrégoire),

1
更改(--m%5<1|m==1)&m>0--m%5<1|m==1&&m>0
凯文·克鲁伊森

1

Pyth,65个字节

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

在这里尝试

说明

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

1

JavaScript(Node.js)262256字节

*感谢@Shaggy减少了2个字节

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

在线尝试!


我可以在手机上发现一些快速节省的方法:1.以单个字符数组的形式输入输入,2.替换x!=" "x>" "
Shaggy

3.更换m=0i=m=0map((x,i)=>map(x=>
Shaggy

1

Python 2中249 224 219 215 205 197个 187 188 182 176字节

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

在线尝试!

返回表示行的字符列表。

  • 通过包含许多额外的空格节省了一些字节。
  • map(list,yticks)那里没必要。
  • 更改了空格填充以节省一些字节。
  • 我以为我正在排序,但不是:+2个字节。但我同时独立保存了一个。y==1替换为y<2
  • -6个字节,要感谢Lynn使用'%d-'%y*(y%5==2>>y)而不是(`y`+'-')*(not y%5or y<2)

稍微松了一下:

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

1

C#(.NET核心)344 340 338 + 18个字节

包括18个字节 using System.Linq;

感谢@KevinCruijssen,节省了6个字节。

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

在线尝试!


您有一个j< m;可以删除的空间。并且int i=0,j可以放在,i=0,j其他int之后,总共-4字节。你必须包括为18个字节using System.Linq;但是..
凯文Cruijssen

@KevinCruijssen谢谢,我错过了这些。我添加了18个字节。
伊恩·

向我+1。哦,您可以将更改为,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;}再节省2个字节for(string p,q;i<t;)for(p=i>0&i%5<1|i==1?i+"-":"",q=p.PadLeft(j=o);j<m;a[i++]=q){...}在线尝试。
凯文·克鲁伊森

@KevinCruijssen那真的很聪明,谢谢!
伊恩·

1

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

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

在线尝试!

注释:

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

cd `mktemp -d`        # for temp files

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

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

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

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

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

感谢@IanM_Matrix节省了3个字节。


cat b可能会<b保存3个字符
IanM_Matrix1 '18年

0

C,201字节

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

输入来自命令行(第一个参数)。使用感叹号代替X来进一步减小代码大小。左侧的计数器始终为三个字符。

经过GCC和clang测试。


for(p=b[1];*p;p++)很有可能是for(p=b[1]-1;*++p;)main(int a,char **b)可能是打高尔夫球的m(a,b)char**b;
乔纳森·弗雷希

由于a!=1将为boolean,因此a%5&&a!=1?应等于a%5&a!=1?a%5&&~-a
乔纳森·弗雷希

0

Excel VBA,316个字节

匿名VBE立即窗口函数,该函数从单元格获取输入[A1]并输出到VBE立即窗口。

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

非高尔夫版本

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

0

Perl的5 -n198 168字节

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

在线尝试!


0

Python 3,177字节

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

在线尝试!

这可能不是Python中字节效率最高的方法,但我确实想用“真正的单线” lambda解决此问题。

输出字符列表的列表。像其他所有人一样,滥用多个领先的换行符和空格。如果可以将结果包装在另一个列表中,则实际上可以进一步减少到174个字节,以便我们可以将最终[0]索引转移到页脚。


0

JavaScript(ES8),200字节

将输入作为字符数组。返回一个字符串。

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

在线尝试!

已评论

s => (                    // s[] = input array of characters (e.g. ['a','b','a','c','a'])
  s.sort()                // sort it in lexicographical order (--> ['a','a','a','b','c'])
  .join``                 // join it (--> 'aaabc')
  .replace(/(\w)\1*/g,    // for each run s of consecutive identical letters (e.g. 'aaa'):
    s => a.push(          //   push in a[]:
      s[0] +              //     the letter, which will appear on the X-axis
      'X'.repeat(         //     followed by 'X' repeated L times
        L = s.length,     //     where L is the length of the run (--> 'aXXX')
        h = h < L ? L : h //     keep track of h = highest value of L
    )),                   //   initialization:
    h = a = []            //     h = a = empty array (h is coerced to 0)
  ),                      // end of replace() (--> a = ['aXXX','bX','cX'] and h = 3)
  g = y =>                // g = recursive function taking y
    y-- ?                 //   decrement y; if there's still a row to process:
      (                   //     build the label for the Y-axis:
        y < 2 ^ y % 5 ?   //       if y != 1 and (y mod 5 != 0 or y = 0):
          ''              //         use an empty label
        :                 //       else:
          y + '-'         //         use a mark
      ).padStart(         //     pad the label with leading spaces,
        `${h}_`.length    //     using the length of the highest possible value of y
      ) +                 //     (padStart() is defined in ECMAScript 2017, aka ES8)
      a.map(r => r[y]     //     append the row,
                 || ' ')  //     padded with spaces when needed
      .join`` + `\n` +    //     join it and append a linefeed
      g(y)                //     append the result of a recursive call
    :                     //   else:
      ''                  //     stop recursion
)(h += 5 - ~-h % 5)       // call g() with h adjusted to the next multiple of 5 + 1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.