ETAOIN SHRDLU гольф


43

Краткое и приятное описание задачи: на
основе ETAOIN SHRDLU ваша задача - написать самую короткую программу или функцию на любом языке, которая выводит 26 букв английского алфавита в зависимости от их частоты во входных данных.

Действительно длинная, сухая и тщательная спецификация:

  • Ваша программа / функция получит в качестве входных данных строку текста, которая будет содержать одну или несколько заглавных и / или строчных букв, а также может содержать знаки препинания, цифры, символы и другие не алфавитные символы.
  • Программа / функция должна выводить только 26 букв в верхнем регистре английского алфавита, в том числе те, которые не отображаются на входе, упорядоченные от наиболее частых к наименее частым в зависимости от того, сколько раз они появляются на входе.
  • Редактировать: частота рассчитывается без учета регистра, но выходные данные должны быть в верхнем регистре.
  • Если две или более буквы имеют одинаковую частоту, они могут быть в любом порядке.
  • Другие выходные данные, такие как пробелы, не допускаются.
  • Редактировать 01.07.2014: На основании отзывов я изменяю это правило. Единственный другой вывод, который допустим, это необязательный начальный и / или завершающий пробел, такой как конечный перевод строки. Другие выходные данные не допускаются.
  • Неопределенное поведение допускается для ввода, который не содержит никаких букв.

Победитель будет выбран через 7 дней, так что наберите эти пальцы!


Пример ввода:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vitae erat velit. Mauris gravida euismod libero ut tincidunt. Phasellus elit dui, consectetur et egestas in, aliquam vitae diam. Donec eget varius ante. Vestibulum cursus diam aliquet, egestas orci quis, placerat dolor. Proin vel nisi lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aliquam erat volutpat. Etiam libero tortor, ornare id dui eget, posuere dignissim libero. Pellentesque commodo consequat volutpat. Integer hendrerit sapien libero, vel viverra augue facilisis sit amet. Quisque consectetur eget nisl quis dignissim. Ut lacinia pretium quam a placerat.
Morbi sed interdum risus, nec pretium lectus. Morbi imperdiet est id accumsan molestie. Duis sed fermentum nisl. Nunc vitae augue mattis, dictum lectus vel, accumsan nisl. Sed ultricies adipiscing rhoncus. Vivamus eu lacus a enim venenatis eleifend. Praesent consectetur tortor non eleifend ultricies. Mauris et odio posuere, auctor erat at, fringilla est. Proin in vestibulum erat. Maecenas congue commodo ante vel varius. Sed tempus mi ut metus gravida, nec dictum libero dapibus. Morbi quis viverra elit. Ut pharetra neque eget lacus tincidunt dictum. Fusce scelerisque viverra tellus et pretium.
Fusce varius adipiscing odio. Nulla imperdiet faucibus sem, at rhoncus ipsum adipiscing vitae. Phasellus imperdiet congue lacus et mollis. Nullam egestas mauris magna, et mollis lectus varius ut. Sed sollicitudin adipiscing dolor, vel elementum elit laoreet molestie. Aliquam nec nulla vel sem ultrices ullamcorper. Nullam nec felis magna. Duis sodales orci non justo aliquam tempus. Integer mi diam, tempor sed vulputate et, varius et nunc. Vestibulum sodales ipsum id mi pharetra, ut convallis mi accumsan. Sed dictum volutpat vestibulum.
Quisque ac dolor sagittis, aliquam libero at, euismod enim. Nulla ullamcorper posuere nulla vitae varius. Nam at dolor non libero elementum pellentesque in in lorem. Fusce porttitor turpis in quam placerat varius. Donec lorem orci, condimentum eu sapien sit amet, aliquet commodo magna. Quisque sed lectus sit amet arcu euismod accumsan et non nunc. Phasellus placerat congue metus, feugiat posuere leo dictum quis. Sed ultricies feugiat eros dignissim bibendum.
Mauris scelerisque consectetur libero eget varius. Aenean neque nunc, ullamcorper vitae orci in, auctor ornare sapien. Nam lacinia molestie imperdiet. Nam vitae mattis nibh. Vestibulum consequat tellus ac nisi sagittis pulvinar. Nullam mollis ornare quam, et venenatis leo porttitor sit amet. Nulla urna neque, dignissim non orci ut, volutpat ultrices erat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque vestibulum tellus nec eros faucibus porta.

Пример вывода:

EITUSALNROMCDPVGQBFHJKWXYZ

Примечание: между KWXYZэтими входами есть 5 связей .

Редактировать:

Конкурс окончен! Спасибо всем, кто принимал участие. А теперь для победителя (ей!): Ответы Дениса CJam и Исаака Pyth пришли с колоссальными 19 символами. (Извините, но я не собираюсь принимать ни один из ответов, потому что я думаю, что это было бы несправедливо по отношению к другому.) Редактировать: Принимая совет Денниса, я отмечу его ответ как принятый, потому что он первым достичь 19 символов. Поощрительные премии идут на третье место Golfscript ответ Илмари Karonen в в 22 символов, а также 75-полукокса Python ответ undergroundmonorail в том , что получили наибольшее upvotes. Еще раз спасибо всем, кто принял участие!


Измеряется ли частота только для заглавных букв ввода?
Говард

2
@IlmariKaronen да переводы строк считаются пробелами, так что это будет запрещено.
Авраам

8
@Abraham: ИМО; если завершающий перевод строки (в частности) разрешен для некоторых языков, он должен быть разрешен, как правило, для всех языков; Не в последнюю очередь потому, что текстовый поток должен заканчиваться символом новой строки, за которым следует EOF.
Виллихам Тотланд

3
@WillihamTotland, основываясь на количестве голосов, поданных вашим комментарием, я изменю правила, чтобы разрешить перевод новой строки.
Авраам

1
Что делать, если есть два ответа с самым коротким кодом? предлагает присвоить зеленую галочку более раннему решению. Сначала isaacg опубликовал свой ответ, сначала я добавил гольф до 19 байт. Какой бы галстук вы ни выбрали, я буду в порядке, но, на мой взгляд, отсутствие общепринятого ответа - немного анти-климат.
Деннис

Ответы:


26

CJam, 21 19 байтов

qeu:A;'[,65>{A\-,}$

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

пример

$ cjam etaoin.cjam <<< "~XyxY YyxZ"
YXZABCDEFGHIJKLMNOPQRSTUVW

(без новой строки)

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

qeu:A; " Read from STDIN, convert to uppercase, save in the variable “A” and discard, ";
'[,    " Push an array of all ASCII characters before “[” (NUL to “Z”).               ";
65>    " Remove the first 64 characters (NUL to “@”).                                 ";
{      " Sort the array of characters by the following mapping:                       ";
  A\   " Swap the character with the string saved in variable “A”.                    ";
  -    " Remove all occurrences of the character from the string.                     ";
  ,    " Push the length of the string.                                               ";
}$     "                                                                              ";

Чем больше вхождений, тем больше символов удаляется, поэтому наиболее часто встречающиеся символы появляются в начале массива.


Очень умный действительно.
Авраам

Поздравляем @Dennis с победой в конкурсе!
Авраам

43

Python 2 или 3 - 77 75 байтов

f=lambda s:''.join(sorted(map(chr,range(65,91)),key=s.upper().count))[::-1]

У меня был ответ до того, как я получил информацию от STDIN, но я понял, что это технически неверно. Я использовал input()метод, который получает только одну строку, но входные данные из примера подразумевают, что он должен обрабатывать несколько строк одновременно. Чтобы соответствовать спецификации, я превратил свой ответ в функцию, которая принимает строковый аргумент. К моему удивлению, это было на два байта меньше! Мне не пришло в голову, что print(...)и input()были дольше, чем f=lambda s:и s.

Это также делает ответ совместимым как с Python 2, так и с Python 3. Первоначально это был только Python 3, потому что он использовал input()(который был назван raw_input()в 2). Теперь, когда это функция, она работает в обоих.

Разъяснения

                                  range(65,91)                              # The numbers 65 to 90
                          map(chr,range(65,91))                             # Convert to ASCII

                                                    s                       # The input string
                                                    s.upper()               # Convert to uppercase
                                                    s.upper().count         # Function literal for 'how many times the argument appears in the string'

                   sorted(map(chr,range(65,91)),key=s.upper().count)        # Sort by that function
           ''.join(sorted(map(chr,range(65,91)),key=s.upper().count))       # Concatenate to string
           ''.join(sorted(map(chr,range(65,91)),key=s.upper().count))[::-1] # Step through by -1 (i.e. reverse string)

  lambda s:''.join(sorted(map(chr,range(65,91)),key=s.upper().count))[::-1] # Make it a function (`return` is implicit for lambdas)
f=lambda s:''.join(sorted(map(chr,range(65,91)),key=s.upper().count))[::-1] # Give it a name

2
С другой стороны, комментарии в объяснении делают меня лицом к лицу. Добро пожаловать в CS 101!
Изката

6
@Izkata Важно то, что он показывает, в каком порядке читать код. Потому что лучшее место, с которого можно начать читать код в гольфе, редко бывает очевидным, особенно когда он становится немного сложнее или лаконичнее этого.
Мартин Эндер

1
Красивая презентация!
xnor

3
@Izk Моя цель состояла в том, чтобы сделать его понятным для людей, которые не знают Python. Я бы никогда не стал комментировать подобное в реальном проекте.
подземный

2
@imm Нет. countэто не переменная или что-то еще, это буквальная функция. Какой бы крутой ни была возможность умножить возвращаемое значение функции, -1вставив -перед собой, это не то, что есть в Python.
подземный

15

Баш, 65 байт

(tr a-z A-Z;echo {A..Z})|fold -1|sort|uniq -c|sort -nr|tr -dc A-Z

пример

$ bash etaoin.sh <<< "~AbaB BbaC"
BACZYXWVUTSRQPONMLKJIHGFED

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

(              #
  tr a-z A-Z   # Turn lowercase into uppercase letters.
  echo {A..Z}  # Print all uppercase letters.
) |            #
fold -1 |      # Split into lines of length 1.
sort |         # Sort those lines (required for piping to uniq).
uniq -c |      # Print the frequencies of all lines.
sort -nr |     # Sort by frequency (reversed).
tr -dc A-Z     # Remove everything that's not an uppercase letter.

1
Это не переносимая локаль, вам нужно принудительно задать LC_COLLATE = C (или короче, LC_ALL).
Крис Даун

6
@ChrisDown Портативность, как правило, не является проблемой в ответах на гольф-код.
Кевин

1
Без переносимости то, что делает этот ответ, не вполне определено.
Крис Даун

@ChrisDown: я протестировал несколько строк и несколько локалей, но я не смог найти пример, где uniq плохо себя ведет для буквенных символов. Не могли бы вы показать мне один?
Деннис

@ChrisDown Этот скрипт достаточно переносим для запуска на OpenBSD с использованием версий BSD: fold, sort, tr, uniq, если оболочкой является bash или ksh93. Другие оболочки, такие как zsh, не расширяются {A..Z}. Все локали LC_COLLATE работают, потому что OpenBSD имеет только LC_COLLATE = C.
Kernigh

12

Pyth 1.0.2 , 19 20

=ZUwsVm;dSm[cZkk)UG

Попробуйте это здесь: http://ideone.com/fork/YlWpEJ

Узнайте больше о Pyth здесь: http://esolangs.org/wiki/Pyth

Пример:

Исходя из ETAOIN SHRDLU, ваша задача - написать самую короткую программу или функцию на любом языке, которая выводит 26 букв английского алфавита в зависимости от их частоты на входе.

дает:

TENOHARSIULGFPYDCBWQMZXVKJ

Объяснение:

=ZUw: Преобразовать ввод в верхний регистр и сохранить в Z.

sV: Печать суммы на обороте

m;d: Последние записи

S: Отсортировано по первой записи в порядке возрастания

m[cZkk): Списки [количество k в Z, k]

UG: Для k заглавными буквами.

Грубый эквивалент Python:

G='abcdefghijklmnopqrstuvwxyz'
Z=copy(upper(input()))
print(_sum(rev(_map(lambda d:d.pop(),sorted(_map(lambda k:_list(count(Z,k),k),upper(G)))))))

Это не вход, я просто подумал, что людям может понравиться это увидеть. В Pyth 1.0.4 следующая программа представляет собой решение в 10 символов:

JUwo_cJNUG

Объяснение:

JUw: Преобразовать ввод в верхний регистр и сохранить в J.

o: (Печать) Сортировать по

_cJN: -1 * (количество N в J)

UG: Над буквами N в верхнем регистре.

Это не является юридическим решением, потому что некоторые изменения с Pyth 1.0.2 до 1.0.4, включая добавление функции osort by, были ответом на эту проблему.


Я предлагаю вам обновить ссылку Pyth на официальную страницу Pyth, если она существует.
AL

@AL Это официальная страница Pyth, пока я не разместил запись esolang.
Исаак

Зачем вам нужно хранить входные данные в переменной, Zчтобы обратиться к ней позже? Неужели простое помещение выражения for Zна его место вызовет многократное чтение ввода?
xnor

@xnor Позиция Z используется внутри лямбда-функции, потому что она находится в первом аргументе карты, поэтому ее необходимо сохранить в переменной. Использование Uw действительно приведет к тому, что ввод будет прочитан 26 раз.
Исаак

1
@AL Хорошо, Pyth работает как на esolang, так и на github. Ссылка на github находится внизу страницы esolang, на которую есть ссылка в ответе. Github делает раскрашивание кода.
Исаак

11

Javascript ( ES6 ) 119 117

Редактировать: (-2) Устранена необходимость toUpperCaseиспользования регистронезависимого RegEx в splitвызове.

a=prompt(f=x=>a.split(RegExp(x,'i')).length)
alert([...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'].sort((b,c)=>f(c)-f(b)).join(''))

Альтернатива (той же длины): сжатая сортировка и подсчет символов в одну функцию.

a=prompt()
alert([...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'].sort(f=(b,c)=>c?f(c)-f(b):a.split(RegExp(b,'i')).length).join(''))

Как функция: 105 104

Редактировать: (-1) Упорядочить сортировку и подсчет символов в одну функцию.

F=a=>[...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'].sort(f=(b,c)=>c?f(c)-f(b):a.split(RegExp(b,'i')).length).join('')

1
Интересная техника.
Мэтт

1
Брызги струны ... восхитительно!
Берги

10

GolfScript, 22 символа

:?91,+-26>{.32+]?\-,}$

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

Объяснение:

  • :?назначает входную строку для символа ?. (Я использую символ пунктуации, чтобы следующий номер 91не анализировался как часть имени символа.)
  • 91,создает список чисел от 0 до 90 (код ASCII Z).
  • + добавляет этот список к входной строке, тем самым преобразуя его из массива кодов ASCII в строку (и удобно также удаляя входную строку из стека).
  • -26>принимает последние 26 символов этой строки, создавая строку, содержащую буквы ASCII в верхнем регистре от Ato Z.
  • { }$Применяет блок кода для всех символов во входной строке, и сортирует эти символы в соответствии с результатом.
  • Внутри блока кода .дублирует символ и 32+преобразует копию из прописных в строчные. ]Собирает эти два символа в массив, ?\-принимает входную строку , хранящуюся в ?и удаляет все вхождения символов в массиве из него, и ,подсчитывает длину оставшейся строки, которая будет ключом сортировки. С помощью этой клавиши символы будут отсортированы в порядке возрастания и, следовательно, в порядке убывания по количеству появлений.

1
Похоже, у нас была почти та же идея. Незначительная ошибка: буква Z отсутствует. Так и должно быть 91,+-26>.
Деннис

@ Денис: Ах, ой. Исправлено, хотя кому это письмо нужно? :)
Ильмари Каронен

2
@IlmariKaronen Основываясь на отзывах сообщества, я внес поправки в правила, чтобы разрешить конечный перевод строки (полное описание см. В вопросе). Ваш счет сейчас 22, а не 25:)
Авраам

8

Haskell, 110 байт

import Data.List
import Data.Char
a%f=compare(f a).f
f t=sortBy(% \c->length$filter((/=c).toUpper)t)['A'..'Z']

Пример использования:

λ> f "Based off ETAOIN SHRDLU, your challenge is to write the shortest program or function in any language that outputs the 26 letters of the English alphabet based on their frequency in the input."
"ETNAHORISULFGPBCDYMQWJKVXZ"

1
Как насчет (/=c)и избавиться от 0-?
Линн

@Mauris хороший улов! Я отредактировал его и сбрил другого персонажа.
Флонк

6

Ruby 2.0, 53 символа

РЕДАКТИРОВАТЬ : Исправлено для правильной работы с многострочными строками, спасибо @ durron597!

f=->s{$><<(?A..?Z).sort_by{|c|-s.upcase.count(c)}*''}

Создает вызываемую функцию, fкоторую можно использовать следующим образом:

f['jackdaws love my big sphinx of quartzzz']

Печатает на STDOUT:

AZOSICGHEJKLMBFPQRDTUVWXYN

2
Этот ответ не правильный. Это дает ответ: EITASUROLNCMPDVQGBHFKJWXYZдля примера в вопросе
durron597

1
@ durron597 Спасибо, вы правы! Он не обрабатывал многострочные строки правильно - getsвозвращает строку за раз. Это можно исправить, изменив значение getsна, gets$nно изменив его на функцию на 1 символ короче.
Пол Престиж

6

Perl, 54 46 байт

ОБНОВЛЕНИЕ: после дальнейшей оптимизации его можно сжать до 46 байт: (thx dennis для -n/ {}hack; китайский perl goth для <=>-> -hack)

s/./$h{uc$&}++/eg}{say sort{$h{$b}-$h{$a}}A..Z

Это должно быть запущено с бегом с perl -nE

Оригинальное решение (не требует специальных параметров Perl):

s/./$h{uc$&}++/egfor<>;print sort{$h{$b}<=>$h{$a}}A..Z

Проверено в Perl 5.8.3, 5.14.2

Если вы получаете предупреждение, отдельно egи forс пробелом (+1 символ), если вы не возражаете

пример использования:

$ python -c 'import this' | perl -le 's/./$h{uc$&}++/egfor<>;print sort{$h{$b}<=>$h{$a}}A..Z' 2>/dev/null
ETAISONLRHPBUCDYMFGXVWKZJQ

ОБЪЯСНЕНИЕ: Для каждого символа ( .) каждой строки ввода ( for<>) примените подстановочный «шаблон», который фактически оценивается как выражение ( eфлаг s///), который увеличивает символ upcased ( uc) ( ./ $&короче, чем более очевидный (.)/ $1) считать в (неинициализированном) хеше ( %h). Затем хэш буквенной частоты используется в функции сравнения сортировки, чтобы распечатать алфавит в верхнем регистре в правильном порядке.


1
Короче и без сообщений об ошибках:perl -ne 's/./$h{uc$&}++/eg}{print sort{$h{$b}<=>$h{$a}}A..Z'
Деннис

Деннис: очень интересно, похоже на опечатку ... это? У меня было несколько вариантов с использованием -nи END{}, но они всегда были длиннее ... не стесняйтесь обновлять ответ, если хотите
mykhal

1
Да, -nоборачивается while(<>){...}вокруг кода. Я избегаю редактирования кода других пользователей. Слишком легко ошибиться, некоторые вещи работают только на некоторых компьютерах и т. Д.
Деннис

1
Джо. Я говорил об }{«инъекции», а не только о хорошо известном -nварианте. Не было бы ожидать , что код строки на самом деле технически это обернуто в то время как код цикла строки перед выполнением, а не только что - то работает вроде как если бы он был завернут ..
mykhal

1
сохранить еще два символа: заменить $h{$b}<=>$h{$a}на$h{$b}-$h{$a}
китайский Perl гот

5

R, 123 байта

Код улучшен благодаря предложениям @RichieCotton.

text <- "Based off ETAOIN SHRDLU, your challenge is to write the shortest program or function in any language that outputs the 26 letters of the English alphabet based on their frequency in the input."

f=function(x){b=plyr::count(toupper(strsplit(x,"")[[1]]));c=merge(LETTERS,b,all.x=T);paste(c[order(-c$freq),1],collapse="")}

f(text)

Выход:

> f(text)
[1] "ETNAHORISULFGPBCDYMQWJKVXZ"

1
@RichieCotton: я отклонил предложенное вами редактирование дважды. Я не знаю, получите ли вы уведомление о причине отклонения голосования, так что если вы читаете это: пожалуйста, предоставьте улучшения в комментариях, чтобы ФП мог их просмотреть. Вот почему: meta.codegolf.stackexchange.com/a/1619/8478
Мартин Эндер,

4

C ++, 185 183 179 177 байт

Конечно, не ожидается победы (может ли C ++ когда-нибудь победить?), Но, тем не менее, это забавное упражнение.

#include <algorithm>
#include <stdio.h>
int f[256],p;main(){for(p=65;p<91;p++)f[p]=p;while(~(p=getchar()))f[p&95]+=256;p=256;std::sort(f,f+p);while(p--)f[p]&95&&putchar(f[p]);}

Объяснение:

#include <algorithm>         // for std::sort
#include <stdio.h>           // for getchar, putchar
int f[256],p;                // declare an array of count-prefixed chars, and a counter
main(){
    for(p=65;p<91;p++)       // 65 == 'A', 91 == the character after 'Z'
        f[p]=p;              // set the character for the slot
    while(~(p=getchar()))    // read characters until EOF
        f[p&95]+=256;        // increment the packed count for the character stripped of the 'lowercase bit'
    p=256;                   // start a countdown
    std::sort(f,f+p);        // sort the array
    while(p--)               // do the countdown
        f[p]&95 &&           // if the masked-off character is set...
          putchar(f[p]);     // print it
}

4

VBScript 181 109

Обновлен, чтобы использовать совершенно другой алгоритм. Превосходит JavaScript!

Милая:

dim b(99):i=ucase(inputbox(k))
for y=65to 90
    c=chr(y)
    a=len(replace(i,c,k))
    b(a)=c+b(a)
next
msgbox join(b,k)

Golfed:

dim b(99):i=ucase(inputbox(k)):for y=65to 90:c=chr(y):a=len(replace(i,c,k)):b(a)=c+b(a):next:msgbox join(b,k)

4

J 41 35 байт

(u:65+i.26)([\:[#/.~@,e.~#])toupper

Демо-версия:

i=: 'This is a test to see whether this is still working'
(u:65+i.26)([\:[#/.~@,e.~#])toupper i
STIEHLORWAGKNBCDFJMPQUVXYZ

Объяснение:

(u:65+i.26) & ( [ \: [ #/.~@,e.~#]) toupper) )
ABCDE...          |    |    |   |      uppercase the right argument
                  |    |    |   \copy from right only member from left
                  |    |     \append the left argument
                  |    \ Afterwards Count apperances of each letter
                  \ Sort the left according to the appearances

Ключ заключается в добавлении левого массива так, чтобы все буквы были доступны и уже были в порядке. Забавным следствием использования существительного в качестве третьего зубца на развилке является то, что он работает как глагол, а также как фраза.


4

Groovy - 130 123 115 112 98 92

Согласно совету @ cfrick (дважды!):

f={('A'..'Z').collectEntries{c->[c,it.grep(~/(?i)$c/).size()]}.sort{-it.value}*.key.join()}

Небольшой тест (бессовестно украденный у @jpjacobs):

assert f('This is a test to see whether this is still working') == 
    'STIEHLORWAGKNBCDFJMPQUVXYZ'

И предложенный тест также проходит


1
Функция должна выводить все 26 букв, а не только те, которые присутствуют во входной строке.
алгоритмический

@algorithmshark, действительно, моя ошибка исправлена
Will Lp

f={('A'..'Z').collectEntries{c->[c,it.toUpperCase().findAll(c).size()]}.sort{-it.value}.keySet().join()}для 104
cfrick

1
еще 6 байтов: it.grep(~/(?i)$c/)вместоit.toUpperCase().grep(c)
cfrick

@cfrick Ух ты! Еще раз спасибо! Это toUpperCaseчертовски беспокоило меня.
Будет ли Lp

4

SAS - 217 (я думаю)

Входные данные должны быть помещены в строку после оператора cards4 или в соответствующие перфокарты для вашей системы. Я думаю, что этот подход экономит несколько символов против попыток процитировать ввод.

data a;
input;
S = upcase(compress(_INFILE_,,'ak'));
do i=1 to length(S);
l=substr(S,i,1);
output;
end;
cards4;
;;;;
run;
proc sql;
select l into :o separated by '' from
(select l, 1/count(l) as f from a group by l) order by f;
quit;

Я знаю, что это не соответствует полной спецификации, так как он возвращает только символы, которые появляются во входной строке. Возможно, мне придется немного переосмыслить это.


Не соответствует спецификации, но все еще круто, поэтому +1: D
кот

4

AppleScript, 278

Я заметил, что "a" = "A"это правда в AppleScript. Я могу использовать это в коде гольф, но остальная часть сценария слишком многословна. Я использовал AppleScript 1.8.3.

Это определяет функцию f. Если вы добавите f("a string")внизу сценария и запустите его в редакторе сценариев, он покажет результат.

on c(n)
ASCII character(64+n)
end
on f(s)
set{a,r}to{{},""}
repeat with i from 1 to 26
set j to 0
repeat with b in s
if b&""=c(i)then set j to j+1
end
set a to a&j
end
repeat with j from 0 to(count s)
repeat with i from 1 to 26
if a's item i=j then set r to c(i)&r
end
end
r
end

Отформатировано и прокомментировано:

-- Returns nth letter of alphabet.
on c(n)
    ASCII character (64 + n)
end c

-- Returns letters in s sorted by frequency.
on f(s)
    -- a: list of letter counts
    -- r: resulting string
    set {a, r} to {{}, ""}

    -- For each letter from A to Z,
    -- count letters in string s.
    repeat with i from 1 to 26
        set j to 0
        repeat with b in s
            -- Can't use b = c(i), because
            -- b is a reference to a string
            -- and = never dereferences its
            -- operands. Get contents of b,
            -- here by coercing b to string.
            if b & "" = c(i) then set j to j + 1
        end repeat
        -- Set item i of a to count j.
        set a to a & j
    end repeat

    -- Sort letters by frequency.  Do a counting sort
    -- because AppleScript lacks a sort command.
    repeat with j from 0 to (count s)
        repeat with i from 1 to 26
            if a's item i = j then set r to c(i) & r
        end repeat
    end repeat
    r
end f

-- Example call:
f("Now is the time for all good men to come to the aid of their country.")
-- Result: "OTEIRNMHLFDCAYWUSGZXVQPKJB"

3

VBScript 157 156 байт

Изменить: изменил msgbox (p) на msgbox p

Более читабельно:

s=ucase(InputBox(z))    'z is empty.
L=len(s)
Dim a(255)
for i=1to L
    x=asc(mid(s,i))
    a(x)=a(x)+1
next
for t=0to L
    For i=65To 90
        If a(i)=t then p=chr(i)&p
    next
next
msgbox p

Гольф: (155 символов + 1 возврат каретки)

s=ucase(InputBox(z)):L=len(s):Dim a(255):for i=1to L:x=asc(mid(s,i)):a(x)=a(x)+1:next:for t=0to L:For i=65To 90:If a(i)=t then p=chr(i)&p
next:next:msgbox p

У меня это было на 171 ранее с кодом, который я нашел более интересным, но метод сортировки comforblydrei короче и требует len (s), что делает «for» короче, чем «while» для первого цикла. (зевок)

's=UCase(InputBox(Z))&8 'just need any extra character.  0-7 don't work because &7 is octal

s=UCase(InputBox(Z)) 'nevermind
Dim a(999)
While Len(s)
    x=Asc(s) 'returns ascii of first char
    a(x)=a(x)-1 'going negative saves a character later...
    s=Mid(s,2) 'doesn't care if you run out of string
Wend
for j=1 to 26 'this used to be   While Len(p)<26
    For i=65To 90
        If a(i)<a(y) Then y=i 'it is barely not worth it to do a(i)+a(i+32)>a(y) here to skip the ucase() above
    Next
    p=p&Chr(y)
    a(y)=1 'if I didn't go negative this would have to be -1.  arrays default to 0.
Next
MsgBox(p)

Из этого поста я узнал несколько интересных трюков! Спасибо за упоминание тоже. Одно: думаю, так и for t=0должно быть for t=1, иначе вы всегда печатаете весь алфавит.
comfortablydrei

1
@comforblydrei Печать всего алфавита не требуется. «Программа / функция должна выводить только 26 букв в
верхнем регистре

Вау. пропустил это. тогда это моя ошибка. Благодарность!
комфортно

3

J - 38 35 символов

Функция, принимающая ввод справа в виде строки. Не победитель, но было весело писать.

(u:65+i.26)([\:[#/.~@,e.~#])toupper

Разъяснение:

  • toupperэто глагол в стандартной библиотеке, который содержит строку Это тогда становится правильным аргументом глагола, в то время как левый аргумент является алфавитом: кодовые точки ASCII от 65 до 90.

  • [и ,e.~#])выбирает ( #) те буквы в правом arg ( ]), которые являются элементами ( e.~) left, а затем prepends ( ,) left arg ( [). Мы сохраняем только заглавные буквы и добавляем одну копию алфавита в конец, чтобы мы могли их всех поймать.

  • #/.~@затем дает частоты каждого символа. Так получилось, что это дано в алфавитном порядке, поэтому сразу после этого мы можем уменьшить ( \:) алфавит (левый аргумент [).

Быстрый ленивый пример ниже. Вы можете попробовать его для себя в tryj.tk .

   (u:65+i.26)([\:[#/.~@,e.~#])toupper 'Based off ETAOIN SHRDLU, your challenge is to write the shortest program or function in any language that outputs the 26 letters of the English alphabet based on their frequency in the input.'
ETNAHORISULFGPBCDYMQWJKVXZ

3

T-SQL 178

По сути, это мое решение на VBScript, но реализованное на SQL.

Это злоупотребление выводом XML для конкатенации столбца. В практическом использовании, это может быть присоединено к внешней таблице для эмуляции GROUP_CONCATфункций в MySQL и других.

Объявление @переменной:

DECLARE @ CHAR(1024)= 'enter your text here';

Код:

with y AS(
    SELECT UPPER(@)i,0l,91y
    UNION ALL
    SELECT i,len(replace(i,char(y-1),'')),y-1
    FROM y
    WHERE y>65
)
SELECT LTRIM(
(
    SELECT char(y)
    FROM y
    WHERE y<91
    ORDER BY l
    FOR XML PATH(''))
)

3

Perl, 78 байт

undef$/;$i=<>;$r{$i=~s/$_//gi}.=$_ for A..Z;print$r{$_}for sort{$b<=>$a}keys%r
  • Только 26 прописных букв ASCII без пробелов выводятся в частотном порядке.
  • Связанные символы приведены в алфавитном порядке.

Результат для примера в вопросе:

EITUSALNROMCDPVGQBFHJKWXYZ

Ungolfed:

# read input
# ----------
undef $/; # disable input separator
$i = <>;  # $i holds the complete input as one string

# analyze
# -------
# For each uppercase letter (A upto Z) its occurences are counted
# via the number of substitutions made by s/$_//gi. The lowercase
# letter is included via modifier "i".
# 
# The occurrence count is then used as key for hash %r.
# The uppercase letter is appended to the value of that hash entry.
$r{$i =~ s/$_//gi} .= $_ for A..Z;

# output
# ------
# The hash keys are sorted numerically in reverse order by
# the specified sort function.
print $r{$_} for sort {$b<=>$a} keys %r

Это может сработать для примера, бот не например, для echo -e 'x\ny\n\nz\n'вывода, который должен возвращать XYZABCDEFGHIJKLMNOPQRSTUVW, но дает XYABCDEFGHIJKLMNOPQRSTUVWZвместо этого. Угадай почему .. :)
Михал

@mykhal: исправлено.
Хейко Обердик

3

PHP - 105 байт

<?preg_filter(~‹§æ“Ö¢‹ö,'$f[$0&fl]++',join('',range(a,z)).$argv[1]);arsort($f);foreach($f as$l=>$F)echo$l;

Вот hexdump, причина специальных символов:

0000000 3c 3f 70 72 65 67 5f 66 69 6c 74 65 72 28 7e dc
0000010 a4 be d2 85 a2 dc 9a 2c 27 24 66 5b 24 30 26 df
0000020 5d 2b 2b 27 2c 6a 6f 69 6e 28 27 27 2c 72 61 6e
0000030 67 65 28 61 2c 7a 29 29 2e 24 61 72 67 76 5b 31
0000040 5d 29 3b 61 72 73 6f 72 74 28 24 66 29 3b 66 6f
0000050 72 65 61 63 68 28 24 66 20 61 73 24 6c 3d 3e 24
0000060 46 29 65 63 68 6f 24 6c 3b                     
0000069

И чуть менее гольф версия:

<?
preg_filter(           // regular expression
  "#[A-z]#e",          // matches every letter + 'eval' flag
  '$f[$0&fl]++',        // so this code runs for every letter
                       // $f is an array whose indices are uppercase letters
                       //   and whose values represent the number of occurences
                       // lowercase is converted to uc with the bitwise and
                       //   fl is 11011111 in binary, every bit except for 32's is set
  join('', range(a,z)) // adding abcdefghijklmnopqrstuvwxyz to the input
    .$argv[1]);        //   because not all letters have to appear in the input
arsort($f);            // sort $f in reverse, maintaining indices
foreach($f as$l=>$F)   //
  echo$l;              // print each index in order

Пример:

 $ php etaoin_shrdlu.php "This function sorts an array such that array indices maintain their correlation with the array elements they are associated with."
 ATIRESHNOCYUWMDLFXZBVGPQKJ

Как работают специальные персонажи preg_filter()?
Авраам

3
В PHP ~ есть побитовый оператор NOT, и вы можете применять его и к строкам, в этом случае он работает с каждым символом. Кроме того, PHP с удовольствием разбирает строки текста как строковые литералы, учитывая, что в них нет специальных символов (например, операторы, $ для переменных, точка с запятой, парантезы ...). Таким образом, запись ~ ‹§æ« Ö ¢ ‹ö (версия с побитовой инверсией) вместо« # [Az] #e »сохраняет один байт, поскольку его не нужно заключать в кавычки.
Аурел Бийл,

Ах, спасибо. Имеет смысл сейчас.
Авраам

1
Поскольку все, что в PHP, имеет смысл. Святой моли.
пушистый

echo join(array_keys($f));может сохранить один байт
Тит

3

C # в LINQPad - 203 байта

Я принял другой подход к ответу Логан Дам. Сначала я убедился, что каждый символ во входной строке отсортирован по внешнему виду и существует только один раз в выходной строке. После этого я добавил каждый пропущенный символ из алфавита в строку вывода.

void e(string i){var a="";foreach(var d in i.ToUpper().GroupBy(x=>x).OrderByDescending(u=>u.Count()))if(d.Key<91&&d.Key>64){a+=d.Key;}for(int x=65;x<91;x++)if(!a.Contains((char)x)){a+=(char)x;}a.Dump();}

К сожалению, это не победило бы ответ Логана Дэма, если бы я сделал в Visual Studio.

Более читаемая версия:

void e(string i)
    {
        var a = "";
        foreach (var d in i.ToUpper().GroupBy(x => x).OrderByDescending(u => u.Count()))
        {
            if (d.Key < 91 && d.Key > 64)
            {
                a += d.Key;
            }
        }
        for (int x = 65; x < 91; x++)
        {
            if (!a.Contains((char)x))
            {
                a += (char)x;
            }
        }
        a.Dump();
    }

Yay, больше LINQ любви! : D
ldam

3

C # (и LINQ) 255 226 210 байт

Используя совет Патрика Хайзинга, синтаксис запроса теперь короче:

namespace System.Linq{class P{static void Main(string[]a){Console.Write((from c in(a[0]+"ABCDEFGHIJKLMNOPQRSTUVWXYZ").ToUpper()where c>'@'&&c<'['group c by c into g orderby-g.Count()select g.Key).ToArray());}}}

Объяснение:

Console.Write(
    (from c //declare our range variable
       in (a[0] + "ABCDEFGHIJKLMNOPQRSTUVWXYZ").ToUpper() //declare the datasource
     where c > '@' && c < '[' //include only letters
     group c by c into g //run of the mill group by
     orderby -g.Count() //order by descending
     select g.Key //we only want the actual letters
     ).ToArray() //mash it all into an array
  );

Синтаксис эквивалентного метода (217):

namespace System.Linq{class P{static void Main(string[]a){Console.Write((a[0]+"ABCDEFGHIJKLMNOPQRSTUVWXYZ").ToUpper().GroupBy(c=>c).OrderBy(c=>-c.Count()).Where(c=>c.Key>'@'&&c.Key<'[').Select(c=>c.Key).ToArray());}}}

Исходное сообщение:

namespace System.Linq{class P{static void Main(string[]a){(a[0]+"ABCDEFGHIJKLMNOPQRSTUVWXYZ").ToUpper().GroupBy(c=>c).OrderByDescending(c=>c.Count()).Where(c=>c.Key>'@'&&c.Key<'[').ToList().ForEach(c=>Console.Write(c.Key));}}}

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

Объяснение:

(a[0] + "ABCDEFGHIJKLMNOPQRSTUVWXYZ") //ensure each character appears once
  .ToUpper()
  .GroupBy(c => c) //get access to .Count()
  .OrderByDescending(c => c.Count())
  .Where(c => c.Key > '@' && c.Key < '[') //exclude anything other than letters
  .ToList() //Only lists have a .ForEach() :(
  .ForEach(c => Console.Write(c.Key)); //print output

Я никогда не использовал синтаксис метода для LINQ, так что для меня это был опыт обучения :), также подумав об этом, теперь я мог бы сэкономить 2 байта, заменив символьные литералы их целочисленными аналогами, но, ме.

Сокращено благодаря советам от ProgramFOX и Num Lock :)

Эквивалентный синтаксис запроса (чуть длиннее):

(from c in (a[0]+"ABCDEFGHIJKLMNOPQRSTUVWXYZ").ToUpper() where c>'@'&&c<'[' group c by c into g orderby g.Count() descending select g.Key).ToList().ForEach(c=>Console.Write(c));

1
На первый взгляд, вы можете сохранить много символов, назвав свой класс просто Pвместо Programи string[]aвместо string[] argsи c=>...вместо (c)=>....
Num Lock

Вместо двух usingоператоров вы также можете поместить свой класс в System.Linqпространство имен и удалить оба с помощью операторов. Затем вы можете сохранить некоторые символы, и он все равно будет работать нормально.
ProgramFOX

@NumLock Правильно, я даже не думал об этом :) @ProgramFOX, который не спасет меня, потому что namespaceон длиннее, usingи два дополнительных {}s будут стоить мне дороже.
ldam

1
namespace System.Linq{}явно короче, чем using System;using System.Linq;просто смотреть на него. Идея состоит в том, чтобы полностью опустить оба using.
Num Lock

Ах, да, это удаляет оба, вы правы, я думал, что это только удалил один. Спасибо.
1

3

C ++ 701 322 232 байта

Первая версия 701 байт (идиоматическое использование STL)

#define _HAS_TRADITIONAL_STL 1
#include <numeric>
#include <iostream>
#include <iterator>
#include <string>
#include <algorithm>
#include <functional>
#include <map>
#include <set>
#define ALL(x) x.begin(), x.end()
using namespace std;
typedef istream_iterator<char> iic;typedef pair<int, char> pic;map<char, int> c;set<pic> d;
void f1(char x) {c[x]--;}
void f2(const pic &p) {d.insert(make_pair(p.second, p.first));}
int main(){string s(26, 0);stdext::iota(ALL(s), 65);copy(ALL(s), ostream_iterator<char>(cout));transform(iic(cin), iic(), back_inserter(s), toupper);for_each(ALL(s), f1);for_each(ALL(c), f2);transform(ALL(c2), ostream_iterator<char>(cout), select2nd<pic>());}

Расширенная чистая версия:

#define _HAS_TRADITIONAL_STL 1
#include <numeric>
#include <iostream>
#include <iterator>
#include <string>
#include <algorithm>
#include <functional>
#include <map>
#include <set>
using namespace std;

typedef istream_iterator<char> iic;
map<char, int> counts;
set<pair<int, char> > counts2;

void docount(char ch) { counts[ch]--; }
void toCounts2(const pair<char, int> &p) { counts2.insert(make_pair(p.second, p.first)); }

int main()
{
    string s(26, 0);
    stdext::iota(s.begin(), s.end(), 65);
    transform(iic(cin), iic(), back_inserter(s), toupper);
    for_each(s.begin(), s.end(), docount);
    for_each(counts.begin(), counts.end(), toCounts2);
    transform(counts2.begin(), counts2.end(), ostream_iterator<char>(cout), select2nd< pair<int, char> >());
}

Идея состоит в том, чтобы продемонстрировать «правильную» C ++ программу без каких-либо взломов. Не обращайте внимания на шаблон и тот факт, что это компилируется только на VC ++

Пояснение:

Мы заполняем от A до Z в строку с помощью iota () , это гарантирует, что при подсчете вхождений каждый символ появляется, даже если его нет на входе.

transform () копирует символ за символом из стандартного ввода и помещает его в конец s после вызова toupper () для каждого

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

Записи карты подсчетов копируются в набор пар, заменяя (char, count) на (count, char). Поскольку наборы упорядочены, мы сортируем их по убыванию частоты

Наконец, мы копируем содержимое набора в стандартный формат , используя transform и select2nd (), чтобы выбрать только второй член пары.

Код довольно читабелен. Решение на C ++ 11 выглядело бы намного красивее, поскольку мы можем использовать лямбда-выражения

Версия C ++ 11 - нет необходимости в лямбдах, но авто и диапазон на основе делают вещи очень чистыми (если подумать, вы можете сделать очень похожее с обычным C ++ 98)

#include<iostream>
#include<iterator>
#include<map>
#include<set>
using namespace std;int main(){istream_iterator<char> b(cin),e;map<char,int> c;set<pair<int,char>> d;for(char i='A';i<='Z';++i){--c[i];}for(auto i=b;i!=e;++i){c[toupper(*i)]--;}for(auto p:c){d.insert(make_pair(p.second,p.first));}for(auto p:d){cout<<p.second;}}

Расширенная версия:

#include <iostream>
#include <iterator>
#include <map>
#include <set>
using namespace std;
int main()
{
    istream_iterator<char> b(cin), e;
    map<char, int> c;
    set<pair<int, char>> d;
    for(char i = 'A'; i <= 'Z'; ++i) {--c[i];}
    for(auto i = b; i != e; ++i) {c[toupper(*i)]--;}
    for(auto p : c) { d.insert(make_pair(p.second, p.first)); }
    for(auto p : d) { cout << p.second; }
}

Следующая итерация (зачем читать из stdin, когда у нас есть argv):

#include <set>
#include <iostream>
int c[256];int main(int n, char **s){std::set<std::pair<int,char>> d;while(*s[1]){c[toupper(*s[1]++)]--;}for(n=65;n<92;++n){d.insert(std::make_pair(--c[n],n));}for(auto p:d){std::cout<<p.second;}}

Расширенная версия:

#include <set>
#include <iostream>
int c[256];
int main(int n, char **s)
{
    std::set<std::pair<int, char>> d;
    while (*s[1])
    {
        c[toupper(*s[1]++)]--;
    }
    for (n = 65; n < 92; n++)
    {
        d.insert(std::make_pair(--c[n], n));
    }
    for (auto p : d)
    {
        std::cout << p.second;
    }
}

3

Желе , 9 байт (не конкурирует)

ØAŒuċ¥@ÞU

объяснение

ØAŒuċ¥@ÞU  Main Link
       Þ   Sort
ØA         The uppercase alphabet by
  Œuċ¥@    number of occurrences in the input:
  Œu       Uppercase
    ċ      Count occurrences
     ¥     Grammar: Last two links as a dyad
      @    Swap arguments
        U  Reverse (because sort sorts up)

Это читается как «сортировка заглавного алфавита по количеству вхождений во вводе заглавными буквами, обратный», что является довольно буквальным переводом задачи: P

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

Эта задача была связана с Jelly HyperTraining, где мы решили эту задачу. Я отправил это, потому что я был первым, чтобы достигнуть 10 байтов.

-1 байт благодаря Эрику Аутгольферу (учитель JHT)


9 байт:ØAŒuċ¥@ÞU
Эрик Outgolfer

@EriktheOutgolfer О, круто, спасибо!
HyperNeutrino

2

C ++ 377

Реализует qsort, используя количество букв в массиве n для сортировки алфавита в массиве A. Запуск через командную строку: golf.exe < in.txt

int n[26],c,k,N;
char A[26];
int C(const void*a,const void*b)
{
int i=(int)(*(char*)a -'A');
int j=(int)(*(char*)b -'A');
return n[j]-n[i];
}
int main()
{
for(;k<26;k++)
{
A[k]=k+'A';
}
N=sizeof(A);
c=getchar();
while(c>0)
{
c=toupper(c);
c=c-'A';
if(c>=0&&c<26)n[c]++;
c=getchar();
}
qsort(A,N,1,C);
for(k=0;k<N;k++)
{
putchar(A[k]);
}
return 0;
}

2

C 117 (119) байтов

x[256];m=1;char c;main(){while(c=getchar()+1)++x[c-1&95];for(;m=x[++c]<x[m]?m:c;x[m<65|m>90||c?m*!c:putchar(m)]=-1);}
  • Некоторые входы, содержащие коды ASCII> = 128, неправильно увеличивают буквенные частоты. Чтобы это исправить, заменить константу 95с 223, при стоимости 1 дополнительных байт.
  • Это рано завершится на входах, содержащих символ с кодом ASCII 255. Чтобы исправить это за счет 1 дополнительного байта, измените char c;на just c;и ++cна c=c+1%255.

2

PowerShell - 139 символов

Во-первых, я не эксперт PowerShell. Уверен, что есть короче, чем это. Но был доволен этим и решил поделиться.

$a = Read-host
$b = ($a.ToUpper() -replace '[^A-Z]','').ToCharArray() + (65..90|%{[char[]]$_})|Group|sort Count -desc|%{$_.Name}
-join $b

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

$a = Read-host            # read from stdin and save into a string var $a
$a.ToUpper()              # Convert the string to UPPERCASE
-replace'[^A-Z]',''       # Remove all non A-Z characters from the str
(...).ToCharArray()       # Convert the inner object (string) to a Char Array
+  (65..90|%{[char[]]$_}) # Create another char array with A-Z chars expanded, 
                          #  and append it to the previous one.
|Group                    # Group the char array by value for each element, 
                          #  consolidates them and count each char occurrence. Example:
                          #  Count | Name
                          #  ----- | -----
                          #      4 | B
                          #      1 | F
                          #      2 | C 
                          #     .. | ..
                          # 
|sort Count -desc         # Sorts the previous hash-table by the 'Count' column 
                          #   in desc ordering
|%{$_.Name}               # Grab only the 'Name' column from the previous sorted hash-table. 
                          # The retuslt obj will be a simple char array again, 
                          #   with the letters in the desired order
$b = (...)                # Saves the resulting char array into a new variable $b
-join $b                  # join the resulting char array elements into a single 
                          #   string, and print it to stdout. 


2

APL, 26 20 символов

⎕a[⍒+/⎕a∘.=('\w'⎕r'\u0')⍞]

⎕a[⍒+/⎕a∘.=1(819⌶)⍞]

-6 спасибо Адаму.


1
('\w'⎕r'\u0')1(819⌶)
Адам
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.