Сортировать строку, вроде


29

Если вы сортируете строку, вы обычно получаете что-то вроде:

         ':Iaaceeefggghiiiiklllllmnnooooprrssstttttuuyyyy

Да, это было первое отсортированное предложение.

Как вы можете видеть, есть много повторяющихся символов, aa, eee, ttttt, 9 пространства и так далее.

Если мы добавим 128ASCII-значение первого дубликата, 256ко второму, 384третьему и т. Д., Снова отсортируем его и выведем новую строку (модуль 128 для возврата тех же символов), мы получим строку:

 ':Iacefghiklmnoprstuy aegilnorstuy egilosty iloty lt    

(Обратите внимание на один пробел и 4 пробела).

Строка "последовательно сортируются" <space>':I....uy, <space>aeg....uy, <space>egi....ty, <space>iloty, <space>lt, <space>, <space>, <space>, <space>.

Это может быть проще визуализировать, если мы используем строку с цифрами в ней. Строка 111222334будет , когда «отсортированный» быть: 123412312.

Вызов:

Неудивительно, что задача состоит в том, чтобы написать код, который сортирует строку в соответствии с описанием выше.

Можно предположить, что входная строка будет содержать только печатаемые символы ASCII в диапазоне 32-126 (от пробела до тильды).


Тестовые случаи:

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

Это , поэтому самый короткий код на каждом языке, подсчитанный в байтах, выиграет реф .


Название немного сбивает с толку, в результате чего я обдумываю это и игнорирую описание: tio.run/nexus/05ab1e#@1@td2jh4ZVe//… В противном случае я буду работать над расширением, чтобы соответствовать краткому описанию .
Волшебная Урна Осьминога

Можем ли мы вывести список символов вместо строки?
Пшеничный волшебник

Если вы можете ввести строку, то и результат должен быть строкой. Если список символов является обычным способом ввода и вывода строк на ваших языках, тогда все в порядке. Вы можете, например, не выводить {'S', 'g', 'i', 'n', 'r', 't'}в Python, так как «нормальный» способ сделать это "String".
Стьюи Гриффин

Я исправлю свой комментарий выше: строка - это список символов , поэтому список символов принят для вывода. Однако список строк не принимается. Это означает, что если возможно добавить второй символ к элементу в вашем списке, он не будет принят. В качестве примера: {'a','b'}не принимается в Matlab , так как вы можете добавить символ к каждому из персонажей , как это: {'aa','b'}. Ваш ввод и вывод должны быть в одном формате.
Стьюи Гриффин

@StewieGriffin Когда вы говорите, отсортировано в соответствии с описанием выше. Вы имеете в виду, что мой алгоритм сортировки должен следовать процессу изменения значений ASCII, или он просто должен выдавать тот же результат, что и этот алгоритм?
Джордж Райт

Ответы:


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.

У Пита есть все, чтобы стать новым J, это потрясающе
shabunc

3
@shabunc Если вы хотите увидеть новый J, посмотрите github.com/DennisMitchell/jelly
isaacg

13

Желе , 3 байта

ĠZị

Попробуйте онлайн!

Как это работает

О, мальчик, этот вызов был почти готов для Желе.

Группа атом ( Ġ) принимает массив 1 в качестве входных и групп индексов , которые соответствуют идентичным элементам массива. Массив групп индексов сортируется с соответствующими элементами в качестве ключей, что является именно тем порядком, который нам необходим для этой задачи.

Далее атом молнии (Z ) транспонирует строки и столбцы сгенерированной (рваной) матрицы индексов. Это просто состоит из чтения столбцов матрицы, пропуская элементы, которых нет в этом столбце. В результате мы получаем первый индекс символа с наименьшей кодовой точкой, за которым следует первый индекс символа с второй наименьшей кодовой точкой,… за которым следует второй индекс символа с наименьшей кодовой точкой и т. Д.

Наконец, unindex atom ( ) извлекает элементы входного массива по всем его индексам в сгенерированном порядке. В результате получается двумерный массив символов, который Jelly выравнивает перед печатью.


1 Желе не имеет строкового типа, только массивы символов.


«О, мальчик, этот вызов был почти готов для Желе». -> 3-х байтный ответ
geisterfurz007 Остановите этот хаос

Как я уже сказал, почти сделано для желе. :)
Денис

10

Python 3, 109 105 104 103 99 93 90 88 81 79 69 байт

2 байта сохранены благодаря FlipTack

7 байтов сохранено, потому что flornquake поймал мою глупую ошибку

2 байта сохранены благодаря xnor

10 байтов сохранено благодаря Денису

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

объяснение

Мы начнем с преобразования нашей строки в список с использованием знака сплат и сохранения этого списка в переменной a. Затем, пока наш aсписок не является пустым, мы просматриваем каждый уникальный элемент aв отсортированном порядке, распечатываем его и удаляем копию этого символа из списка.

Таким образом, каждая итерация печатает одну копию каждого символа, присутствующего в a.


1
@StewieGriffin set- несортированный набор.
FlipTack

2
@StewieGriffin при печати они сортируются, но не по их значениям ASCII. Часто кажется, что они есть, но я полагаю, что они отсортированы по типу хэша
Волшебник Пшеницы

1
Вы можете сделать fстроку вместо списка, чтобы сохранить несколько байтов.
землетрясение

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←т , который имеет значение

   подсказка ввода текста

Попробуй APL онлайн!


⊢⌸tсоздает таблицу, в которой строки (дополненные нулями для прямоугольной таблицы) перечисляют уникальные индексы каждой буквы в т .


1
какие из глифов дороже?
жэнь

1
@wptreanor заставляет все это быть UTF-8 вместо одного байта на символ.
Адам

4

С, 109 106 105 104 102 100 97 98 96 91 байт

Резервное копирование до 98 байт, необходимых для инициализации j, чтобы сделать f (n) повторно используемым

До 96 байт, используя вместо strlen B-)

Странно, что мне пришлось вернуться к 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

Оставлены ли пробелы в первом тестовом примере?
Стьюи Гриффин

У меня есть три пробела в первом тестовом примере ... Это потому, что я не включил пробел в строку ввода ;-)
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, так что это может быть хорошо, но вы читали этот комментарий?
Стьюи Гриффин

@ StewieGriffin Welp, нет. Я могу это исправить, но разве это не дает несправедливого преимущества языкам, которые не имеют различий между String и Char []? Связанная мета-дискуссия
JungHwan Мин

Хорошая точка зрения. Я сделал исправление, см. Комментарий ниже оригинала. Справедливый? Я не уверен, если это делает ваш ответ действительным или нет.
Стьюи Гриффин

@StewieGriffin Mathematica не делает различий между символами и строками. Даже Charactersкоманда технически выводит список строк длины 1.
JungHwan Мин

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 Спасибо, исправлено.
землетрясение

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

J , 16 15 байт

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

Это глагол, который принимает и возвращает одну строку. Попробуйте онлайн!

Майлз сохранил байт, спасибо!

объяснение

Ничего особенного: сортируйте в основном по порядку появления, а затем по значению символа.

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

Я думаю, что вы можете сохранить суммирование движений байтов вне скобок `+ / @ (= {:)`
миль

@ Майлз Да, потому что у поезда бесконечный ранг. Хорошо, спасибо!
Згарб

3

Mathematica, 55 байтов, неконкурентный

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

Edit: К сожалению, системы 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 Мин

Я отметил ваш ответ не конкурирующим, потому что он не выполняет то, что указывает вопрос (сортировка по коду символа, а не в каноническом порядке).
JungHwan Мин

@JungHwanMin исправлено в RuleDelayed. Спасибо.
космодром

2

Brainf * ck , 458 226 байт

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

Попробуйте онлайн! - BF

Numberwang , 262 226 байт

8400000087111111442111911170004000400000071114002241202271214020914070419027114170270034427171114400000091111112711170000007000400040000007111400224120227121402091407041902711417027004219190071420091171411111170007000771111117

Попробуйте онлайн! - СЗ

Я поместил оба из них здесь, потому что они идентичны код.


2

PHP, 83 байта

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

К сожалению, вы не можете иметь unsetв троице, поэтому мне нужно использовать раздражающе долго 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во внешнем цикле и значения ASCII i%128во внутреннем цикле. Включает символ cс заданным значением ASCII, если число раз, которое он появляется в строке, по крайней мере, его минимальное число.

Код использует трюк для имитации назначения, c=chr(i%128)чтобы на него можно было ссылаться в выражении (s.count(c)>i>>7)*c. Python lambdaне позволяет присваивать, потому что они принимают только выражения. Преобразование в defили полную программу все еще является чистым убытком.

Вместо этого функция передает значение chr(i%128)для следующего рекурсивного вызова в качестве необязательного ввода. Это отключено на единицу, потому iчто было увеличено, но это не имеет значения, пока строка не содержит специального символа '\x7f'(мы также можем увеличить 128 до 256). Начальная c=''безвредна.


2

V , 37 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})}

Я был немного удивлен, обнаружив, что нет встроенного способа группировки похожих элементов в списке. Вот что делает бит сквош-карты.


1
Я получаю «Этот Seq уже был повторен», если я не переименую aв @a(+2 байта). Также grep *eq$_,может быть записано grep $_,(-3 байта), поскольку строка является допустимым интеллектуальным сопоставителем.
смс

1
{[~] flat roundrobin |.comb.classify(~*){*}.sort»[*]}- Эта вариация составляет всего 54 байта.
смс

@smis Я не вижу этой ошибки. Может быть, мы используем разные версии? Я на рокудо-звезде-2016.10. В любом случае, ваше решение опозорило мое, вы должны опубликовать его как отдельный ответ.
Шон

Я использую передовой Rakudo, скомпилированный из основной ветки git-репо на этой неделе. Во всяком случае, я разместил classifyрешение на основе в качестве отдельного ответа сейчас.
смс

1

JavaScript (ES6), 77 75 байт

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

Стабильная сортировка лексикографически отсортированной строки по n- му случаю

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 байта
Джордж Райт

1

Perl 6 , 54 байта

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

Объяснение:

  • { }: Лямбда, которая принимает один аргумент - например, 21211 .
  • .comb: Разделить входной аргумент на список символов - например, (2,1,2,1,1) .
  • .classify(~*): Группировать символы, используя сравнение строк в качестве условия группировки, возвращая неупорядоченный хэш - например, { 2=>[2,2], 1=>[1,1,1] } .
  • {*}: Возвращает список всех значений хеша - например, [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подход идет к ответу Шона .)


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

10 из 15 байтов предназначены для того, чтобы обойти метод 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 # может сопоставить символ с входом, поэтому удаление сокращенного имени System.Text.Encoding.ASCII и добавление в другую карту экономит мне 20 байтов!

Возвращая массив символов вместо строки, я экономлю 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``)


Тот же bytecount, что и мой код Matlab, и точно такой же подход. Хотя я еще не пытался играть в шахту. Я, вероятно, попозже скажу позже, если вы добавите объяснение :-) (я сделал принцип из ответов на голосование без объяснений, даже если я это понимаю) :-)
Стьюи Гриффин,

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

Рубин, 59 + 1 = 60 байт

Добавляет один байт для -nфлага. Порт словарного решения @PatrickRoberts.

d={};print *$_.chars.sort_by{|c|d[c]||=0;c.ord+128*d[c]+=1}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.