排序字符串


29

如果对字符串进行排序,通常会得到类似以下内容的信息:

         ':Iaaceeefggghiiiiklllllmnnooooprrssstttttuuyyyy

是的,那是第一句话。

正如你所看到的,有很多重复的字符,aaeeettttt,9位等。

如果我们将128第一个重复项的ASCII值相加,256将第二个重复项的ASCII值相加384,依此类推,依此类推,再次对其进行排序并输出新的字符串(取模128以返回相同的字符),我们将得到以下字符串:

 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    

(请注意单个前导空格和四个尾随空格)。

该字符串“依次排序” <space>':I....uy<space>aeg....uy<space>egi....ty<space>iloty<space>lt<space><space><space><space>

如果我们使用带数字的字符串,可能会更容易形象化。该字符串111222334在“排序”后将为:123412312

挑战:

毫不奇怪,挑战在于编写根据以上描述对字符串进行排序的代码。

您可以假定输入字符串将仅包含32-126(空格到波浪号)范围内的可打印ASCII字符。


测试用例:

**Test cases:**
 *:Tacest*es*s*

If you sort a string you'll typically get something like:
 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    

Hello, World!
 !,HWdelorlol

#MATLAB, 114 bytes
 #,14ABLMTbesty 1A

f=@(s)[mod(sort(cell2mat(cellfun(@(c)c+128*(0:nnz(c)-1),mat2cell(sort(s),1,histc(s,unique(s))),'un',0))),128),''];
'()*+,-0128:;=@[]acdefhilmnoqrstuz'(),0128@acefilmnorstu'(),12celmnostu'(),12celnstu(),clnst(),cls(),cs(),()()()()

这是,因此每种语言中以字节数计的最短代码将赢得ref


标题有点混乱,导致我思考了这个问题,而忽略了以下描述:tio.run/nexus/05ab1e#@1@td2jh4ZVe//…很好的挑战,否则,我将继续进行扩展以满足简要说明。
魔术章鱼缸

我们可以输出字符列表而不是字符串吗?
小麦巫师

如果可以输入字符串,则输出也应该是字符串。如果字符列表是使用您的语言输入和输出字符串的正常方式,那就可以了。例如,您不能{'S', 'g', 'i', 'n', 'r', 't'}在Python中输出,因为“正常”的方式是"String"
Stewie Griffin

我将在上面纠正我的评论:字符串是一个字符列表,因此可接受输出字符列表。但是,不接受字符串列表。这意味着,如果可以在列表中的元素上添加第二个字符,则该字符不会被接受。例如:{'a','b'}Matlab不接受:,因为您可以向每个字符添加一个字符,如下所示:{'aa','b'}。您的输入和输出必须使用相同的格式。
Stewie Griffin

@StewieGriffin当你说按照上面的描述排序。您是说我的排序算法必须遵循修改ASCII值的过程,还是只需要产生与该算法相同的输出?
乔治·瑞斯

Answers:


15

Pyth,5个字节

s.T.g

测试套件

非常简单:分组和排序,转置,连接。

s.T.g
s.T.gkQ    Implicit variables
   .gkQ    Group the input input lists of elements whose values match when the
           identity function is applied, sorted by the output value.
 .T        Transpose, skipping empty values. This puts all first characters into
           a list, then all second, etc.
s          Concatenate.

Pyth拥有一切成为新J的能力,太棒了
shabunc

3
@shabunc如果您想查看新的J,请查看github.com/DennisMitchell/jelly
isaacg

13

果冻,3个字节

ĠZị

在线尝试!

怎么运行的

噢,男孩,这个挑战几乎是果冻带来的。

原子(Ġ)带有一个数组1为对应于所述阵列的相同的元件输入和组索引。索引组的数组以对应的元素作为键进行排序,这正是我们要求此挑战的顺序。

接下来,zip原子(Z)转置已生成(参差不齐的)索引矩阵的行和列。这仅包括读取矩阵的列,跳过该列中不存在的元素。结果,我们得到了具有最低代码点的字符的第一个索引,然后得到了具有第二最低代码点的字符的第一个索引,…之后是具有最低代码点的字符的第二个索引,依此类推。

最后,unindex原子()按照生成的顺序在其所有索引处检索输入数组的元素。结果是2D字符数组,Jelly在打印之前将其展平。


1 Jelly没有字符串类型,只有字符数组。


“哦,男孩,这个挑战几乎是对果冻造成的。” -> 3个字节的答案
geisterfurz007停止这场混乱,将于

正如我所说,几乎是果冻制成的。:)
丹尼斯

10

Python 3,109 105 104 103 99 93 90 88 81 79 69字节

多亏了FlipTack,节省了2个字节

由于flornquake捕获了我的愚蠢错误,因此节省了7个字节

xnor节省了2个字节

丹尼斯(Dennis)节省了10个字节

a=[*input()]
while a:
    for c in sorted({*a}):print(end=c);a.remove(c)

说明

我们首先使用splat将字符串转换为列表,然后将该列表存储在变量中a。然后,尽管我们a不是空列表,但我们a将按排序顺序遍历每个唯一成员,将其打印并从列表中删除该字符的副本。

因此,每次迭代打印都会打印出中每个字符的一个副本a


1
@StewieGriffin set是一个未分类的集合。
FlipTack

2
@StewieGriffin在打印时会进行排序,但不会完全按照其ASCII值排序。通常看起来它们是,但我相信它们是按某种哈希排序的。
小麦巫师

1
您可以f使用字符串而不是列表来节省一些字节。
flornquake

1
如果您选择a=list(input()),则可以这样做a.remove(c),这是节省的净额。
xnor

1
切换到Python 3将节省大量字节。tio.run/nexus/…–
丹尼斯,

6

Haskell,44个字节

import Data.List
concat.transpose.group.sort

用法示例:

Prelude Data.List> concat.transpose.group.sort $ "If you sort a string you'll typically get something like:"
" ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    "

将相等的字符排序,分组为字符串列表(例如"aabbc"-> ["aa","bb","c"]),再转置并展平为单个字符串。


6

Python 2,75个字节

lambda s:`zip(*sorted((s[:i].count(c),c)for i,c in enumerate(s)))[1]`[2::5]

在线尝试!


1
不知道它是否有效,但lambda s:`[sorted((1e9+s[:i].count(c),c)for i,c in enumerate(s))]`[18::21]适用于最大长度的字符串9e9
xnor

@xnor你可以删除[]和更改18,以17挽救两个字节。 lambda s:`sorted((1e9+s[:i].count(c),c)for i,c in enumerate(s))`[17::21]
小麦巫师

@xnor至少,这应该是有效的32位Python高尔夫。我试图摆脱zip,但是我认为添加1e9不会发生在我身上……谢谢!
丹尼斯,

@WheatWizard好眼睛。谢谢!
丹尼斯,

如果字符串中包含反斜杠,则失败。
林恩

4

Dyalog APL,21个字符= 39 个字节

t[0~⍨∊⍉(⊢⌸t)[⍋∪t←⍞;]]

t[... ] 索引t(不久将定义)与...

0~⍨ 从中删除零

 征募(扁平化)

 转置

(⊢⌸t)[... ;] 键控* t,行索引由...

   将排序的索引

   的独特字母

  t←t,其值为

   提示文字输入

在线尝试APL!


⊢⌸t创建一个表,其中的行(对于矩形表用零填充)列出t中每个唯一字母的索引。


1
哪一个字形更昂贵?

1
@wptreanor 导致整个内容为UTF-8,而不是每个字符一个字节。
亚当

4

C,109 106 105 104 102 100 97 98 96 91个字节

备份至98字节,需要初始化j以使f(n)可重用

使用puts代替strlen B-减少到96个字节

奇怪的是我不得不回到strlen,但是我摆脱了for(; i ++;)循环,所以现在它降至91字节。显然,看跌期权手册页;

"RETURNS
   If successful, the result is a nonnegative integer; otherwise, the result is `EOF'."

...我很幸运,它最初是有效的

char*c,i,j;f(m){for(j=strlen(m);j;++i)for(c=m;*c;c++)if(*c==i){*c=7,putchar(i),j--;break;}}

测试代码...

main(c,v)char**v;
{
    char test[] = "If you sort a string you'll typically get something like: ";
    char test2[] = "Hello, World!";

    f(test);puts("");    
    f(test2);puts("");    
}

这是一些测试案例,现在是时候开始打高尔夫了

C:\eng\golf>a.exe
 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt
 !,HWdelorlo

在第一个测试用例中是否保留了尾随空格?
Stewie Griffin

在第一个测试用例中,我有三个尾随空格...这是因为我没有在输入字符串中包括尾随空格;-)
cleblanc

4

Mathematica,68 60 59字节

Split[Characters@#~SortBy~ToCharacterCode]~Flatten~{2}<>""&

接受一个字符串。输出一个字符串。

如果允许使用字符列表(46个字节):

Split[#~SortBy~ToCharacterCode]~Flatten~{2,1}&

版本使用Sort(40字节):

Split@Sort@Characters@#~Flatten~{2}<>""&

这个版本不能作为我的答案,因为Sort不能在这里使用。Sort按规范顺序排序,而不按字符代码排序。


我不知道mathematica,所以可能还不错,但是您读过评论吗?
Stewie Griffin

@StewieGriffin Welp,不。我可以解决这个问题,但是这对没有String与Char []区别的语言是否具有不公平的优势呢?相关meta讨论
JungHwan Min

好点子。我进行了更正,请参阅原始内容下方的评论。公平?我不确定这是否会使您的答案有效。
Stewie Griffin

@StewieGriffin Mathematica在字符和字符串之间没有区别。甚至该Characters命令在技术上也输出长度为1的字符串列表。
JungHwan Min

1
@StewieGriffin 我认为这也很重要。我认为这是更好的,允许在任何合理的格式输入,无论是字符串,长度为1个的字符串列表,字符数组,字节数组,等等
ngenisis

3

Python 2,77 76字节

d={}
def f(c):d[c]=r=d.get(c,c),;return r
print`sorted(input(),key=f)`[2::5]

将带引号的字符串作为标准输入的输入。

在线尝试!


我认为这是不允许的,因为功能必须是可重用的。您可以将其设置为程序。
xnor

我真的很喜欢这种方法,并使用一个可变的函数进行排序。元组的嵌套也很聪明。
xnor

@xnor谢谢,已修复。
flornquake

3

JavaScript(ES6),79个字节

f=s=>s&&(a=[...new Set(s)]).sort().join``+f(a.reduce((s,e)=>s.replace(e,``),s))
<input oninput=o.textContent=f(this.value)><pre id=o>

通过提取唯一字符集,对其进行排序,从原始字符串中删除它们,然后递归计算其余字符串的排序来工作。我发现有趣的81字节解决方案:

f=s=>s&&(s=[...s].sort().join``).replace(r=/(.)(\1*)/g,"$1")+f(s.replace(r,"$2"))

3

J16 15字节

/:+/@(={:)\;"0]

这是一个接受并返回一个字符串的动词。 在线尝试!

迈尔斯节省了一个字节,谢谢!

说明

这里没什么花哨的:主要根据出现的顺序排序,其次按char值排序。

/:+/@(={:)\;"0]  Input is y.
          \      Map over prefixes:
  +/              Sum
    @(   )        of
      =           bit-array of equality
       {:         with last element.
                 This gives an array of integers whose i'th element is k
                 if index i is the k'th occurrence of y[i].
           ;     Pair this array
            "0   element-wise
              ]  with y
/:               and sort y using it as key.

我认为您可以将移动总和保存到括号“ + / @(= {:)`”的外部
英里

@Miles哦,是的,因为火车的等级是无限的。很好,谢谢!
Zgarb

3

Mathematica,55字节,无竞争

(Sort@Characters@#//.{a___,b_,b_,c___}:>{a,b,c,b})<>""&

编辑:不幸的是,Mathematica的sort通过字符代码,而是由字母顺序,其中大写立刻如下小写(即Hi There排序到{ , e, e, h, H, i, r, T})。

这适用于以下模式:

//.{a___,b_,b_,c___}:>{a,b,c,b}
    a___       c___              (Three _) a zero or more members, named a and c
         b_,b_                   exactly one member, repeated twice (since they have the same name)
                    :>           Delayed Rule (replace left hand side with right hand side.)
                                 Delayed Rule evaluate on each substitution, avoiding conflicts with predefined variables
                      {a,b,c,b}  put one of the b-named member after all other sequences
//.                              repeat until no change (aka Replace Repeated)

1
一件小事:Rule (->)应该是RuleDelayed (:>)(字节数没有变化),因为的两端Rule都有变量。Rule可能会导致与现有定义冲突。例如:a=3;5/.{a_->a}返回3,而不是5。(a_->a评估为a_->3-如果您使用a_:>a,它将保持这种方式并a=3;5/.{a_:>a}返回5)。
JungHwan Min

我将您的答案标记为不竞争,因为它不执行问题所指定的内容(按字符代码排序,而不是按规范的顺序排序)。
JungHwan Min

@JungHwanMin固定为RuleDelayed。谢谢。
spacemit

2

Brainf * CK458个 226字节

,[>>>>>>,]<<<<<<[[-<<<+<<<]>>>[>>>[>>>>>>]<<<[>>--[<->--]<-<[>->+<[>]>[<+>-]<<[<]>-]>>.[[-]<]<<<[[>>>>>>+<<<<<<-]<<<]>>>>>>]>>>[>>>[>>>>>>]<<<[>>--[<->--]<-<[>->+<[>]>[<+>-]<<[<]>-]>>[-<+<+>>]<[->>+<<]<[<<<<<<]>>>]>>>]]<<<<<<]

在线尝试!-高炉

Numberwang262个 226字节

8400000087111111442111911170004000400000071114002241202271214020914070419027114170270034427171114400000091111112711170000007000400040000007111400224120227121402091407041902711417027004219190071420091171411111170007000771111117

在线尝试!-西北

我将它们都放在这里,因为它们是相同的代码。


2

PHP,83字节

for($s=count_chars($argv[1]);$s=array_filter($s);$c%=128)echo$s[++$c]--?chr($c):'';

不幸的是你不能unset三元组,所以我需要使用烦人的long array_filter
使用方式如下:

php -r "for($s=count_chars($argv[1]);$s=array_filter($s);$c%=128)echo$s[++$c]--?chr($c):'';" "If you sort a string you'll typically get something like:"

2

Python 2,70个字节

f=lambda s,i=0,c='':s[i>>7:]and(s.count(c)>i>>7)*c+f(s,i+1,chr(i%128))

在线尝试

这是非常低效的。测试链接将更i>>7改为i>>5,并将递归限制设置为10000。假设输入的ASCII值最多为126。

使用div-mod技巧迭代两个循环:i/128外循环中的最小计数和i%128内循环中的ASCII值。如果字符c出现在字符串中的次数至少是其最小计数,则包含具有给定ASCII值的字符。

该代码使用技巧来模拟分配,c=chr(i%128)以便可以在表达式中对其进行引用(s.count(c)>i>>7)*c。Python lambda不允许赋值,因为它们仅接受表达式。转换为def完整程序仍然是一个净损失。

取而代之的是,该函数将值chr(i%128)作为可选输入推入下一个递归调用。这是因为i增加了一个,所以没有关系,只要字符串不包含特殊字符'\x7f'(我们也可以将128提升为256)就没有关系。最初c=''是无害的。


2

V37 36字节

感谢@DJMcMayhem的字节!

Í./&ò
dd:sor
Íî
òͨ.©¨±«©±À!¨.«©/±³²

在线尝试!

不确定我最后是否喜欢正则表达式,但是我需要以ò某种方式打破常规。

说明

Í./&ò                    #All chars on their own line
dd:sor                   #Delete empty line, sort chars
Íî                       #Join all lines together s/\n//
òͨ.©¨±«©±À!¨.«©/±³² #until breaking s/\v(.)(\1+)\1@!(.+)/\3\2\1

Íî(或:%s/\n//g)短于VGgJ
DJMcMayhem

1

Perl 6、68个字节

{my \a=.comb.sort;[~] flat roundrobin |a.squish.map({grep *eq$_,a})}

我惊讶地发现没有内置的方式可以将列表中的类似元素分组。那就是squish-map位的功能。


1
除非重命名a@a(+2字节),否则我将得到“此Seq已经被迭代” 。另外,由于字符串是有效的智能匹配器,grep *eq$_,因此可以写入grep $_,(-3字节)。
smls

1
{[~] flat roundrobin |.comb.classify(~*){*}.sort»[*]}-这种变化只有54个字节。
smss

@smis我看不到该错误。也许我们使用的是其他版本?我在rakudo-star-2016.10。无论如何,您的解决方案使我感到羞耻,您应该将其发布为单独的答案。
肖恩

我正在使用本周从git repo主分支编译的尖端Rakudo。无论如何,我现在将classify基于解决方案的问题作为单独的答案发布。
smss

1

JavaScript(ES6),77 75字节

s=>(a=[],x={},[...s].sort().map(c=>a[x[c]=n=-~x[c]]=(a[n]||'')+c),a).join``

稳定的N按字典序排序串 occurence

F=s=>(a=[],x={},[...s].sort().map(c=>a[x[c]=n=-~x[c]]=(a[n]||'')+c),a).join``

const update = () => {
  console.clear();
  console.log(F(input.value));
};
input.oninput = update;
update();
#input {
  width: 100%;
  box-sizing: border-box;
}
<input id="input" type="text" value="         ':Iaaceeefggghiiiiklllllmnnooooprrssstttttuuyyyy" length=99/>
<div id="output"></div>


1+~~与相同-~
尼尔

@Neil很棒,谢谢-2个字节
George Reith,

1

Perl 6、54个字节

{[~] flat roundrobin |.comb.classify(~*){*}.sort»[*]}

说明:

  • { }:一个带有一个参数的lambda-例如21211
  • .comb:将输入参数分成字符列表-例如(2,1,2,1,1)
  • .classify(~*):使用字符串比较作为分组条件来对字符进行分组,并返回无序哈希(例如){ 2=>[2,2], 1=>[1,1,1] }
  • {*}:返回Hash所有值的列表-例如[2,2], [1,1,1]
  • .sort:排序-例如[1,1,1], [2,2]
  • »[*]:剥离由于散列而被包裹在其中的项目容器,因此在接下来的步骤中它们将不被视为单个项目-例如(1,1,1), (2,2)
  • roundrobin |:压缩子列表,直到所有列表都用尽-例如(1,2), (1,2), (1)
  • flat:将结果展平-例如1, 2, 1, 2, 1
  • [~]:连接它再次得到一个字符串-例如12121

(该roundrobin方法的信用由Sean回答。)


1

05AB1E,15个字节

{.¡"ä"©¹g׫øJ®K

在线尝试! 或作为 测试套件

说明

{                # sort input
 .¡              # group by equal elements
   "ä"©          # push "ä" and store a copy in the register
       ¹g×       # repeat the "ä" input-nr times
          «      # concatenate the result to each string in the grouped input
           ø     # zip
            J    # join to string
             ®K  # remove all instances of "ä" in the string

15个字节中的10个用于绕过05AB1E处理不同长度的拉链字符串的方式。


1

FSharp,194个 190 170 140 133字节的

let f=Seq.map
let(@)=(>>)
f int@Seq.groupBy id@f(snd@Seq.mapi((*)128@(+)))@Seq.concat@Seq.sort@f((%)@(|>)128@byte)@Array.ofSeq@f char

使用Seq代替Array可节省几个字节

定义一个较短的名称,并使用另一个映射来避免(fun ->)阻塞

事实证明F#可以将char映射到in中,因此删除System.Text.Encoding.ASCII的缩写名称,然后添加另一个映射可以节省20个字节!

返回一个char数组而不是一个字符串,可以节省30个字节!

我不再需要确保它是一个字符串,为我节省了7个字节


0

JavaScript(ES6),114个字节

为了清楚起见,用换行符分隔,而不是字节计数的一部分:

s=>[...s].map(a=>(m[a]=-~m[a])*128+a.charCodeAt(),m={})
.sort((a,b)=>a-b).map(a=>String.fromCharCode(a%128)).join``

演示版

`**Test cases:**
 *:Tacest*es*s*

If you sort a string you'll typically get something like:
 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    

Hello, World!
 !,HWdelorlol

#MATLAB, 114 bytes
 #,14ABLMTbesty 1A

f=@(s)[mod(sort(cell2mat(cellfun(@(c)c+128*(0:nnz(c)-1),mat2cell(sort(s),1,histc(s,unique(s))),'un',0))),128),''];
'()*+,-0128:;=@[]acdefhilmnoqrstuz'(),0128@acefilmnorstu'(),12celmnostu'(),12celnstu(),clnst(),cls(),cs(),()()()()`.split`\n\n`.map(s=>(p=s.split`\n`,console.log(`${p[0]}\n\n${r=f(p[0])}\n\nmatch: ${r==p[1]}`)),
f=s=>[...s].map(a=>(m[a]=-~m[a])*128+a.charCodeAt(),m={}).sort((a,b)=>a-b).map(a=>String.fromCharCode(a%128)).join``)


与我的Matlab代码相同的字节数,并且使用完全相同的方法。还没有尝试打高尔夫。如果您添加一个解释,我可能会稍后投票:
Stewie Griffin

0

Clojure,79个字节

#(for[V[(group-by(fn[s]s)%)]i(range 1e9)k(sort(keys V))c[(get(V k)i)]:when c]c)

匿名函数,返回一个字符序列。支持最多10 ^ 9个任意字符的重复,这应该足够了。



0

Ruby,59 + 1 = 60字节

-n标志添加一个字节。@PatrickRoberts的字典解决方案的端口。

d={};print *$_.chars.sort_by{|c|d[c]||=0;c.ord+128*d[c]+=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.