Bir dize sırala


29

Bir dizeyi sıralarsanız, genellikle şöyle bir şey elde edersiniz:

         ':Iaaceeefggghiiiiklllllmnnooooprrssstttttuuyyyy

Evet, sıralanan ilk cümleydi.

Gördüğünüz gibi, tekrarlanan karakterlerin bir yeri vardır, aa, eee, ttttt, 9 boşluklar vb.

128İlk kopyadaki ASCII değerine 256, ikinci, 384üçüncü ve benzeri değerlere eklersek , tekrar sıralayın ve yeni dizge çıktısını alın (aynı karakterleri geri almak için modül 128):

 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    

(Tek baştaki boşluğa ve 4 sondaki boşluğa dikkat edin).

Dize "sıralı olarak sıralanmış" dır <space>':I....uy, <space>aeg....uy, <space>egi....ty, <space>iloty, <space>lt, <space>, <space>, <space>, <space>.

İçinde rakam olan bir dize kullanırsak, bunu görselleştirmek daha kolay olabilir. Dize 111222334"kriteri" ne zaman olacak: 123412312.

Meydan okuma:

Hiç şüphe yok ki, meydan okuma yukarıdaki açıklamaya göre bir dizge sıralayan bir kod yazmaktır.

Giriş dizesinin yalnızca yazdırılabilir ASCII karakterlerini 32-126 (tilde boşluk) aralığında içereceğini varsayabilirsiniz.


Test durumları:

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

Bu , bu nedenle bayt sayılan her dilde en kısa kod ref kazanacaktır .


Başlık biraz kafa karıştırıcı, bunu düşünerek ve açıklamayı görmezden geldiğim için: tio.run/nexus/05ab1e#@1@td2jh4ZVe//… Aksi takdirde, bu konuyu özetlemek için genişletmeye çalışacağım.
Magic Octopus Urn

Bir dize yerine bir karakter listesi yazdırabilir miyiz?
Buğday Sihirbazı

Bir dize girebiliyorsanız, çıktı da bir dize olmalıdır. Bir karakter listesi, dillerinizde dize giriş ve çıkışının normal şekliyse, sorun yok. Örneğin {'S', 'g', 'i', 'n', 'r', 't'}, bunu yapmak için "normal" yol olduğundan, Python'da çıktı veremezsiniz "String".
Stewie Griffin

Yukarıdaki yorumumu düzeltirim: bir dize bir karakter listesidir , bu yüzden bir karakter listesi çıktı olarak kabul edilir. Ancak, bir dize listesi kabul edilmez. Bu, listenizdeki bir öğeye ikinci bir karakter eklemek mümkünse, kabul edilmediği anlamına gelir. Örnek olarak: {'a','b'}Eğer böyle karakterlerin her birine bir karakter ekleyebildiğinizden Matlab'ta kabul edilmez: {'aa','b'}. Giriş ve çıkışlarınız aynı formatta olmalıdır.
Stewie Griffin

@StewieGriffin Yukarıdaki açıklamaya göre sıralanmış derken. Sıralama algoritmamın ASCII değerlerini değiştirme işlemini takip etmesi mi gerekiyor yoksa sadece bu algoritma ile aynı çıktıyı üretmesi gerekiyor mu?
George Reith,

Yanıtlar:


15

Pyth, 5 bayt

s.T.g

Test odası

Çok basit: Gruplandırın ve sıralayın, dönüştürün, birleştirin.

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 yeni J olmak için her şeye sahiptir, muhteşemdir
shabunc

3
@shabunc Yeni J'yi görmek istiyorsanız, github.com/DennisMitchell/jelly
isaacg

13

Jöle , 3 bayt

ĠZị

Çevrimiçi deneyin!

Nasıl çalışır

Ah evlat, bu meydan okuma tamamen Jelly için yapıldı.

Grup atomu ( Ġ) bir dizi alır 1 dizinin aynı elemanlar karşılık gelen giriş ve gruplar endeksleri olarak. Dizin gruplarının dizisi, karşılık gelen öğelerle birlikte anahtarlar olarak sıralanır; bu tam da bu meydan okuma için gereken sıradır.

Daha sonra, zip atomu ( Z) oluşturulan (düzensiz) indeks matrisinin satırlarını ve sütunlarını iletir. Bu sadece matrisin sütunlarını okumaktan, o sütunda bulunmayan elemanları atlamaktan ibarettir. Sonuç olarak, en düşük kod noktasına sahip karakterin ilk dizinini, ardından en düşük ikinci kod koduna sahip karakterin ilk dizinini, ardından en düşük kod noktasına sahip karakterin ikinci dizinini vb. Alırız.

Son olarak, unindex atomu ( ) giriş dizisinin elemanlarını oluşturulan sırayla tüm indekslerinde alır. Sonuç, Jelly, yazdırmadan önce düzleşen bir 2D karakter dizisidir.


1 Jelly bir karakter dizisine sahip değildir , sadece karakter dizileridir.


“Ah, oğlum, bu meydan okuma tamamen Jelly için yapıldı.” -> 3 byte answer
geisterfurz007 Bu kargaşayı durdur

Dediğim gibi, neredeyse Jelly için yapılmış. :)
Dennis,

10

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

FlipTack sayesinde 2 bayt kaydedildi

7 bayt kaydedildi çünkü flornquake aptal hatamı yakaladı

Xnor sayesinde 2 bayt kaydedildi

Dennis sayesinde 10 bayt kurtarıldı

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

açıklama

Dizgimizi bir uyarıyla kullanarak bir listeye dönüştürerek ve bu listeyi değişkene kaydederek başlarız a. O zaman aboş liste olmasa da, her benzersiz üyeden geçiyoruz.a sırayla geçeriz, yazdırır ve bu karakterin bir kopyasını listeden çıkarırız.

Her yineleme yazdırır, böylece içinde bulunan her karakterin bir kopyasını yazdırır a.


1
@StewieGriffin setsıralanmamış bir settir.
FlipTack

2
@StewieGriffin basıldığında bunlar tam olarak ASCII değerlerine göre sıralanmazlar. Genellikle öyle görünüyorlar ama bir tür karma değerine göre sıralandıklarına inanıyorum.
Buğday Sihirbazı

1
fBirkaç bayt kaydetmek için liste yerine bir dize oluşturabilirsiniz .
Flornquake

1
Eğer alırsanız a=list(input()), a.remove(c)net bir tasarruf olduğunu yapabilirsiniz.
xnor

1
Python 3'e geçmek bir çok baytı kurtarır. tio.run/nexus/…
Dennis

6

Haskell, 44 bayt

import Data.List
concat.transpose.group.sort

Kullanım örneği:

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

Sıralayın, eşit karakterleri bir dizeler listesine (örneğin "aabbc"-> ["aa","bb","c"]) göre gruplayın, yeniden dönüştürün ve tek bir dizeye yassılaştırın.


6

Python 2,75 bayt

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

Çevrimiçi deneyin!


1
Geçerli olup olmadığını bilmiyorum, ancak lambda s:`[sorted((1e9+s[:i].count(c),c)for i,c in enumerate(s))]`[18::21]en çok uzunluğu olan dizeler için çalışıyor 9e9.
xnor

@ xnor, iki bayttan tasarruf etmek için bırakıp []değiştirebilirsiniz . 1817lambda s:`sorted((1e9+s[:i].count(c),c)for i,c in enumerate(s))`[17::21]
Buğday Sihirbazı

@xnor En azından, bu geçerli bir 32-bit Python golf olmalı. Kurtulmaya çalıştım zip, ama eklemenin 1e9başıma geleceğini sanmıyorum ... Teşekkürler!
Dennis

@WheatWizard İyi göz. Teşekkürler!
Dennis

Dize içinde ters eğik çizgiler varsa, bu başarısız olur.
Lynn

4

Dyalog APL , 21 karakter = 39 bayt

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

t[... ] index t (kısaca tanımlanacak) ile ...

0~⍨ sıfırdan kaldırıldı

 listelenen (düzleştirilmiş)

 aktarılmamıştır

(⊢⌸t)[... ;] anahtarlı * t , satır indeksli ...

   sıralayabilecek endeksler

   eşsiz harfleri

  t←değeri olan t

   istenen metin girişi

TryAPL çevrimiçi!


⊢⌸tSatırların (dikdörtgen bir tablo için sıfırlarla doldurulmuş) her t harfinin indeksini t olarak listeleyeceği bir tablo oluşturur .


1
Gliflerden hangisi daha pahalıdır?
ren

1
@ wptreanor , her şeyin char başına bir bayt yerine UTF-8 olmasına neden olur.
Adám

4

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

F (n) yeniden kullanılabilir yapmak için j'yi başlatmak için gereken 98 Bayta kadar yedek

Strlen yerine koyanlar kullanarak 96 Bayt'a kadar B-)

Strlen'a geri dönmek zorundaydım ama for (; i ++;) döngüsünden kurtuldum, bu yüzden şimdi 91 Byte'a düştü. Görünüşe göre koyar için man sayfa okur;

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

... ilk etapta çalıştığı için şanslıydım

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 kodu ...

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

İşte birkaç test vakası, şimdi golf oynama zamanı

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

İlk testte takip boşlukları kalıyor mu?
Stewie Griffin,

İlk test
senaryosunda

4

Mathematica, 68 60 59 bayt

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

Dize kabul eder. Bir Dize çıktılar.

Karakter listesine izin verilirse (46 bayt):

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

Sürüm kullanma Sort(40 bayt):

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

Bu sürüm benim cevabım Sortolamaz çünkü burada kullanılamaz; Sortkarakter koduna göre değil, sıraya göre sıralar.


Matematiği bilmiyorum bu yüzden bu iyi olabilir, ama bu yorumu okudunuz mu?
Stewie Griffin

@StewieGriffin Welp, hayır. Bunu düzeltebilirim, ancak bu, String vs Char [] ayrımına sahip olmayan dillere haksız bir avantaj sağlamaz mı? İlgili meta tartışma
JungHwan Min

İyi bir nokta. Bir düzeltme yaptım, orijinalin altındaki yoruma bakın. Adil? Bu, cevabınızı geçerli kılıyor mu, emin değilim.
Stewie Griffin

@StewieGriffin Mathematica, karakterlerle dizgiler arasında bir ayrım yapmaz. Bu Characterskomut bile teknik olarak bir uzunluk-1 dizge listesi verir.
JungHwan Min

1
@StewieGriffin Bunun da alakalı olduğunu düşünüyorum . Girdiyi herhangi bir makul biçimde izin vermek daha iyi olur, bir dize, uzunluk 1 dize listesi, karakter dizisi, bayt dizisi vb.
Olabilir


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}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.