Sortieren Sie eine Zeichenfolge


29

Wenn Sie eine Zeichenfolge sortieren, erhalten Sie normalerweise Folgendes:

         ':Iaaceeefggghiiiiklllllmnnooooprrssstttttuuyyyy

Ja, das war der erste Satz sortiert.

Wie Sie sehen können, gibt es eine Menge von wiederholten Zeichen, aa, eee, ttttt, 9 Räume und so weiter.

Wenn wir 128zum ASCII-Wert des ersten Duplikats, 256zum zweiten, 384zum dritten und so weiter addieren , sortieren Sie es erneut und geben den neuen String aus (Modul 128, um die gleichen Zeichen wiederzuerlangen), erhalten wir den String:

 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    

(Beachten Sie das einzelne führende Leerzeichen und die 4 nachfolgenden Leerzeichen).

Die Zeichenfolge wird "sequentiell sortiert" <space>':I....uy, <space>aeg....uy, <space>egi....ty, <space>iloty, <space>lt, <space>, <space>, <space>, <space>.

Es könnte einfacher sein, dies zu visualisieren, wenn wir einen String mit Ziffern darin verwenden. Der String 111222334wird als „geordnet“ sein: 123412312.

Herausforderung:

Es ist keine Überraschung, dass die Herausforderung darin besteht, einen Code zu schreiben, der eine Zeichenfolge gemäß der obigen Beschreibung sortiert.

Sie können davon ausgehen, dass die Eingabezeichenfolge nur druckbare ASCII-Zeichen im Bereich 32-126 (Leerzeichen bis Tilde) enthält.


Testfälle:

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

Dies ist , so dass der kürzeste Code in jeder Sprache , der in Bytes gezählt wird, ref gewinnt .


Der Titel ist ein bisschen verwirrend, was dazu führt, dass ich das überlege und die Beschreibung ignoriere: tio.run/nexus/05ab1e#@1@td2jh4ZVe//... Schöne Herausforderung, ansonsten werde ich daran arbeiten, das zu erweitern, um den Auftrag zu erfüllen.
Magic Octopus Urn

Können wir eine Liste von Zeichen anstelle einer Zeichenkette ausgeben?
Weizen-Assistent

Wenn Sie eine Zeichenfolge eingeben können, sollte die Ausgabe auch eine Zeichenfolge sein. Wenn eine Liste von Zeichen die normale Art ist, Zeichenfolgen in Ihren Sprachen einzugeben und auszugeben, ist dies in Ordnung. Sie können zum Beispiel nicht {'S', 'g', 'i', 'n', 'r', 't'}in Python ausgeben , da dies "normal" ist "String".
Stewie Griffin

Ich werde meinen obigen Kommentar korrigieren: Eine Zeichenfolge ist eine Liste von Zeichen , daher wird eine Liste von Zeichen als Ausgabe akzeptiert. Eine Liste von Zeichenfolgen wird jedoch nicht akzeptiert. Das heißt, wenn es möglich ist, einem Element in Ihrer Liste ein zweites Zeichen hinzuzufügen, wird es nicht akzeptiert. Als Beispiel: {'a','b'}in Matlab nicht akzeptiert , da Sie ein Zeichen zu jedem der Zeichen wie diese hinzufügen: {'aa','b'}. Ihre Eingabe und Ausgabe müssen dasselbe Format haben.
Stewie Griffin

@StewieGriffin Wenn Sie nach der obigen Beschreibung sortiert sagen. Meinen Sie, mein Sortieralgorithmus muss dem Änderungsprozess von ASCII-Werten folgen oder muss nur die gleiche Ausgabe wie dieser Algorithmus erzeugen?
George Reith

Antworten:


15

Pyth, 5 Bytes

s.T.g

Testsuite

Ganz einfach: Gruppieren und sortieren, transponieren, verketten.

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 hat alles, um neu zu werden J, es ist fantastisch
Shabunc

3
@shabunc Wenn du das neue J sehen willst,
schau

13

Gelee , 3 Bytes

ĠZị

Probieren Sie es online!

Wie es funktioniert

Oh Mann, diese Herausforderung war fast wie gemacht für Jelly.

Das Gruppenatom ( Ġ) nimmt ein Array 1 als Eingabe und gruppiert Indizes, die identischen Elementen des Arrays entsprechen. Das Array der Indexgruppen wird mit den entsprechenden Elementen als Schlüssel sortiert. Dies ist genau die Reihenfolge, die wir für diese Herausforderung benötigen.

Als nächstes transponiert das zip- Atom ( Z) Zeilen und Spalten der generierten (zackigen) Matrix von Indizes. Dies besteht einfach darin, die Spalten der Matrix zu lesen und Elemente zu überspringen, die in dieser Spalte nicht vorhanden sind. Als Ergebnis erhalten wir den ersten Index des Zeichens mit dem niedrigsten Codepunkt, gefolgt vom ersten Index des Zeichens mit dem zweitniedrigsten Codepunkt, gefolgt vom zweiten Index des Zeichens mit dem niedrigsten Codepunkt usw.

Schließlich ruft das unindex atom ( ) die Elemente des Eingabearrays an allen seinen Indizes in der generierten Reihenfolge ab. Das Ergebnis ist ein 2D-Zeichenfeld, das vor dem Drucken von Jelly abgeflacht wird.


1 Jelly hat keinen String- Typ, sondern nur Arrays von Zeichen.


"Oh Junge, diese Herausforderung war alles andere als für Jelly gemacht." -> 3 byte answer
geisterfurz007 Stoppen Sie dieses Chaos am

Wie gesagt, fast wie gemacht für Jelly. :)
Dennis

10

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

2 Bytes gespart dank FlipTack

7 Bytes gespart, weil das Flornbeben meinen blöden Fehler abgefangen hat

2 Bytes gespart dank xnor

10 Bytes gespart dank Dennis

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

Erläuterung

Wir beginnen damit, unseren String mit einem Splat in eine Liste umzuwandeln und diese Liste in einer Variablen zu speichern a. Dann, während unsere aListe nicht leer ist, durchlaufen wir jedes einzelne Mitglied ain sortierter Reihenfolge, drucken es aus und entfernen eine Kopie dieses Zeichens aus der Liste.

Bei jedem Iterationsdruck wird somit eine Kopie jedes in vorhandenen Zeichens gedruckt a.


1
@StewieGriffin setist eine unsortierte Gruppe.
FlipTack

2
@StewieGriffin Beim Drucken werden sie sortiert, aber nicht exakt nach ihren ASCII-Werten. Es scheint oft so, als ob sie es sind, aber ich glaube, sie sind nach einer Art von Hash sortiert.
Weizen-Zauberer

1
Sie können fanstelle einer Liste eine Zeichenfolge erstellen, um einige Bytes zu sparen.
Flornquake

1
Wenn Sie nehmen a=list(input()), können Sie tun a.remove(c), was eine Nettoersparnis ist.
Xnor

1
Ein Wechsel zu Python 3 würde viele Bytes einsparen. tio.run/nexus/…
Dennis

6

Haskell, 44 Bytes

import Data.List
concat.transpose.group.sort

Anwendungsbeispiel:

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

Sortieren, gruppieren Sie gleiche Zeichen zu einer Liste von Zeichenfolgen (z. B. "aabbc"-> ["aa","bb","c"]), transponieren Sie und reduzieren Sie sie erneut zu einer einzelnen Zeichenfolge.


6

Python 2 , 75 Bytes

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

Probieren Sie es online!


1
Ich weiß nicht, ob es gültig ist, aber lambda s:`[sorted((1e9+s[:i].count(c),c)for i,c in enumerate(s))]`[18::21]für Zeichenfolgen mit maximaler Länge funktioniert 9e9.
Xnor

@xnor Sie können die Drop []und ändern 18zu 17zwei Bytes zu speichern. lambda s:`sorted((1e9+s[:i].count(c),c)for i,c in enumerate(s))`[17::21]
Weizen-Zauberer

@xnor Zumindest sollte dies ein gültiger 32-Bit-Python-Golf sein. Ich habe versucht, die loszuwerden zip, aber ich glaube nicht, dass mir das Hinzufügen 1e9jemals in den Sinn gekommen wäre ... Danke!
Dennis

@ WheatWizard Gutes Auge. Vielen Dank!
Dennis

This fails if the string has backslashes in it.
Lynn

4

Dyalog APL, 21 chars = 39 bytes

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

t[...] index t (to be defined shortly) with...

0~⍨ zeros removed from

 the enlisted (flattened)

 transposed

(⊢⌸t)[...;] keyed* t, row-indexed by...

   the indices which would sort

   the unique letters of

  t←t, which has the value of

   prompted text input

TryAPL online!


⊢⌸t creates a table where the rows (padded with zeros for a rectangular table) list each unique letters' indices in t.


1
which of the glyphs are more expensive?
ren

1
@wptreanor causes the entire thing to be UTF-8 instead of one byte per char.
Adám

4

C, 109 106 105 104 102 100 97 98 96 91 Bytes

Back up to 98 Bytes, needed to initialize j to make f(n) re-useable

Down to 96 Bytes using puts in place of strlen B-)

It's strange I had to back to strlen but I got rid of the for(;i++;) loop so now it's down to 91 Bytes. Apparently the man page for puts reads;

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

... I was lucky it was working in the first place

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

test code...

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

Here are a few test cases, now it's time to golf this down

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

Are the trailing spaces left out in the first test case?
Stewie Griffin

I have three trailing spaces in the first test case... That's because I didn't include the trailing space on the input string ;-)
cleblanc

4

Mathematica, 68 60 59 bytes

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

Accepts a String. Outputs a String.

If list of characters were allowed (46 bytes):

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

Version using Sort (40 bytes):

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

This version cannot be my answer because Sort cannot be used here; Sort sorts by canonical order, not by character code.


I don't know mathematica so this might be just fine, but did you read this comment?
Stewie Griffin

@StewieGriffin Welp, nope. I can fix that, but doesn't that give an unfair advantage to languages that don't have a String vs Char[] distinction? Related meta discussion
JungHwan Min

Good point. I made a correction, see the comment below the original. Fair? I'm not sure if this makes your answer valid or not.
Stewie Griffin

@StewieGriffin Mathematica doesn't have a distinction between characters and strings. Even the Characters command technically output a list of length-1 strings.
JungHwan Min

1
@StewieGriffin I think this is also relevant. I think it's better to allow the input in any reasonable format, be it a string, list of length 1 strings, array of characters, array of bytes, etc.
ngenisis

3

Python 2, 77 76 bytes

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

Takes a quoted string as input from stdin.

Try it online!


I think this isn't allowed because functions have to be re-usable. You could make it a program.
xnor

I really like this method, sorting with a function that mutates. The nesting of tuples is clever too.
xnor

@xnor Thanks, fixed.
flornquake

3

JavaScript (ES6), 79 bytes

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>

Works by extracting the set of unique characters, sorting it, removing them from the original string, and recursively calculating the sort of the rest of the string. 81 byte solution that I found interesting:

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

3

J, 16 15 bytes

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

This is a verb that takes and returns one string. Try it online!

Miles saved a byte, thanks!

Explanation

Nothing too fancy here: sort primarily by order of occurrence, secondarily by char value.

/:+/@(={:)\;"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.

I think you can save a byte moving summation to the outside of the parentheses `+/@(={:)`
miles

@Miles Oh yeah, because a train has infinite rank. Nice, thanks!
Zgarb

3

Mathematica, 55 bytes, non-competing

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

Edit: Unfortunately, Mathematica's sort is not by character codes, but by alphabetical order, where uppercase immediatly follows lowercase (ie Hi There is sorted to { , e, e, h, H, i, r, T}).

This works using patterns:

//.{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
One minor thing: Rule (->) should be RuleDelayed (:>) (no change in byte count) because both sides of Rule has variables. Rule can cause conflicts with pre-existing definitions. For instance: a=3;5/.{a_->a} returns 3, not 5. (a_->a evaluates to a_->3 -- if you use a_:>a, it stays that way and a=3;5/.{a_:>a} returns 5).
JungHwan Min

I marked your answer non-competing because it does not do what the question specifies (sort by character code, not in canonical order).
JungHwan Min

@JungHwanMin fixed to RuleDelayed. thanks.
spacemit

2

Brainf*ck, 458 226 bytes

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

Try it online! - BF

Numberwang, 262 226 bytes

8400000087111111442111911170004000400000071114002241202271214020914070419027114170270034427171114400000091111112711170000007000400040000007111400224120227121402091407041902711417027004219190071420091171411111170007000771111117

Try it online! - NW

I put both of these here because they are identical code.


2

PHP, 83 bytes

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

Unfortunately you can't have unset in a ternary so I need to use the annoyingly long array_filter.
Use like:

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 bytes

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

Try it online

This is very inefficient. The test link changes the i>>7 to i>>5 and sets the recursion limit to 10000. Assumes the inputs only has ASCII values up to 126.

Uses the div-mod trick to iterate through two loops: minimum counts i/128 in the outer loop and ASCII values i%128 in the inner loop. Includes a character c with the given ASCII value if the number of times it appears in the string is at least its minimum count.

The code uses a trick to simulate the assignment c=chr(i%128) so that it can be referenced in the expression (s.count(c)>i>>7)*c. Python lambdas do not allow assignment because they only take expressions. Converting to a def or full program is still a net loss here.

Instead, the function pushes forward the value chr(i%128) to the next recursive call as an optional input. This is off by one because i has been incremented, but doesn't matter as long as the string doesn't contain special character '\x7f' (we could also raise 128 to 256). The initial c='' is harmless.


2

V, 37 36 bytes

Thanks @DJMcMayhem for the byte!

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

Try it online!

Not sure I like the regex at the end, but I needed to make the ò break somehow.

Explain

Í./&ò                    #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

Íî (or :%s/\n//g) is shorter than VGgJ
DJMcMayhem

1

Perl 6, 68 bytes

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

I was a little surprised to find that there's no built-in way to group like elements in a list. That's what the squish-map bit does.


1
I get "This Seq has already been iterated" unless I rename a to @a (+2 bytes). Also, grep *eq$_, can be written grep $_, (-3 bytes) since a string is a valid smart-matcher.
smls

1
{[~] flat roundrobin |.comb.classify(~*){*}.sort»[*]} -- This variation is only 54 bytes.
smls

@smis I don't see that error. Maybe we're using different versions? I'm on rakudo-star-2016.10. Anyway, your solution puts mine to shame, you should post it as a separate answer.
Sean

I'm using a bleeding-edge Rakudo compiled from the main branch of the git repo this week. Anyway, I posted the classify-based solution as a separate answer now.
smls

1

JavaScript (ES6), 77 75 bytes

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

Stable sorts the lexicographically sorted string by nth 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+~~ is the same as -~.
Neil

@Neil Awesome thanks -2 bytes
George Reith

1

Perl 6, 54 bytes

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

Explanation:

  • { }: A lambda that takes one argument -- e.g. 21211.
  • .comb: Split the input argument into a list of characters -- e.g. (2,1,2,1,1).
  • .classify(~*): Group the characters using string comparison as the grouping condition, returning an unordered Hash -- e.g. { 2=>[2,2], 1=>[1,1,1] }.
  • {*}: Return a list of all values of the Hash -- e.g. [2,2], [1,1,1].
  • .sort: Sort it -- e.g. [1,1,1], [2,2].
  • »[*]: Strip the item containers the arrays were wrapped in due to being in the hash, so that they won't be considered as a single item in the following step -- e.g. (1,1,1), (2,2).
  • roundrobin |: Zip the sub-lists until all are exhausted -- e.g. (1,2), (1,2), (1).
  • flat: Flatten the result -- e.g. 1, 2, 1, 2, 1.
  • [~]: Concatenate it to get a string again -- e.g. 12121.

(Credit for the roundrobin approach goes to Sean's answer.)


1

05AB1E, 15 bytes

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

Try it online! or as a Test suite

Explanation

{                # 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

10 of the 15 bytes are for getting around 05AB1E's way of handling zipping strings of different length.


1

FSharp, 194 190 170 140 133 bytes

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

Using Seq instead of Array saves a couple of bytes

Defining a shorter name, and using another maps to avoid a (fun ->) block

It turns out F# can map a char to an in, so removing the shortened name of System.Text.Encoding.ASCII, and adding in another map saves me 20 bytes!

Returning a char array instead of a string, saves me 30 bytes!

I no longer need to make sure it's a string, saves me 7 bytes


0

JavaScript (ES6), 114 bytes

Separated with newline for clarity, not part of byte count:

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

Demo

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


The same bytecount as my Matlab code, and the exact same approach. Haven't attempted to golf mine yet though. I'll probably upvote later if you add an explanation :-) (I've made a principle out of not upvoting answers without explanations, even when I understand it) :-)
Stewie Griffin

0

Clojure, 79 bytes

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

An anonymous function, returns a sequence of characters. Supports up-to 10^9 repetitions of any characters, which should be plenty.



0

Ruby, 59+1 = 60 bytes

Adds one byte for the -n flag. Port of @PatrickRoberts' dictionary solution.

d={};print *$_.chars.sort_by{|c|d[c]||=0;c.ord+128*d[c]+=1}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.