На днях мы писали предложения с моей дочерью с магнитным письмом на холодильник. Хотя мы смогли сделать некоторые ( I love cat
), у нас не было достаточно букв, чтобы сделать другие ( I love you too
) из-за недостаточного количества букв o
(4)
Затем я узнал, что, хотя один набор включает в себя 3 e
буквы, он имеет только 2 o
буквы. Вероятно, вдохновленный http://en.wikipedia.org/wiki/Letter_frequency, это все равно не будет отражать реальную ситуацию "на холодильнике".
проблема
Учитывая текстовый файл, где каждая строка содержит «примерное предложение», которое нужно написать в холодильнике, предложите алфавитный набор с минимальным количеством букв, но все же достаточный для написания каждого предложения по отдельности.
Примечание: игнорируйте регистры, в любом случае все буквы-магниты являются заглавными.
вход
Файл содержит новые строки, разделенные предложениями:
hello
i love cat
i love dog
i love mommy
mommy loves daddy
Выход
Предоставьте обратно отсортированный список букв, где каждая буква появляется только столько раз, сколько достаточно, чтобы написать любое предложение:
acdddeghillmmmoostvyy
(спасибо, Исаак!)
победитель
Кратчайшая реализация (код)
ОБНОВЛЕНО: Тестирование
Я создал дополнительный тест и попробовал с различными ответами здесь:
v
выводе должна быть буква ;)M
дляW
или боковуюN
дляZ
? ;-)I
s._\¯
Ответы:
GolfScript, 28/34 символа
Программа, состоящая из 28 символов, предполагает, что все вводимые буквы находятся в одном и том же регистре. Если это не обязательно так, мы можем принудительно ввести их в верхний регистр, добавив
{95&}%
к коду всего 34 символа:Примечания:
Для корректной работы ввод должен содержать хотя бы одну новую строку. Это будет верно для обычных текстовых файлов с символами новой строки в конце каждой строки, но может быть неверным, если входные данные состоят только из одной строки без завершающего символа новой строки. Это может быть исправлено за счет двух дополнительных символов путем добавления
n+
кода.Верхний регистр, используемый в 34-символьной версии, действительно грубый - он отображает строчные буквы ASCII в их прописные эквиваленты (и пробелы в
NUL
s), но создает полный беспорядок чисел и большинства знаков препинания. Я предполагаю, что на входе не будет таких символов.28-символьная версия обрабатывает все входные символы (кроме символов новой строки и
NUL
s) одинаково. В частности, если входные данные содержат пробелы, некоторые также появятся в выходных данных; удобно, они будут сортировать перед любыми другими печатными символами ASCII. Версия из 34 символов, тем не менее, игнорирует пробелы (потому что оказывается, что я могу сделать это без дополнительных затрат).Объяснение:
Необязательный
{95&}%
префикс вводит верхний регистр ввода путем обнуления шестого бита кода ASCII каждого входного байта ( ). Это отображает строчные буквы ASCII в верхний регистр, пробелы в нулевые байты и оставляет новые строки без изменений.95 = 64 + 31 = 10111112
n/
разбивает ввод в новых строках и:a
присваивает результирующий массив переменнойa
. Затем{|}*
вычисляется объединение множеств строк в массиве, которое (при условии, что массив имеет как минимум два элемента) дает строку, содержащую все уникальные (не новые строки) символы во входных данных.Следующий
{ }%
цикл перебирает каждый из этих уникальных символов. Внутри тела цикла внутренний циклa{.[2$]--}%
выполняет итерацию по строкам в массивеa
, удаляя из каждой строки все символы, не совпадающие с символами, по которым внешний цикл выполняет итерацию.Внутренний цикл оставляет код ASCII текущего символа в стеке ниже отфильтрованного массива. Мы используем это, повторяя отфильтрованный массив столько раз, сколько указано в коде ASCII (
*
), прежде чем сортировать его ($
) и брать последний элемент (-1=
). По сути, это дает самую длинную строку в фильтрованном массиве (так как все они состоят из повторов одного и того же символа, лексикографическая сортировка просто сортирует их по длине), за исключением случаев, когда у символа есть код ASCII, равный нулю, и в этом случае он ничего не дает.Наконец,
$
в конце просто сортирует вывод в алфавитном порядке.источник
n/:a{|}*{{{=}+,}+a%$-1=}%$
.J - 37 символов
Читает из стандартного ввода, выводит на консоль.
1!:1]3
это вызов к STDIN.tolower;._2
выполняет двойную функцию, разбивая строки и делая их строчными одновременно. Затем мы подсчитываем, сколько раз символ встречается в каждой строке+/"2=/&a.
, и берем точечный максимум по всем строкам>./
.Наконец, мы вытягиваем столько символов из алфавита с помощью
#&a.
. Это включает пробелы - все они находятся спереди из-за их низкого значения ASCII - поэтому мы просто удаляем начальные пробелы с помощьюdlb
.источник
JavaScript (ECMAScript 6) -
148139135 символовВерсия 2:
Обновлен для использования понимания массива:
Версия 1:
Предполагается, что:
s
;С комментариями:
Если хочешь:
.join('')
в конце;s
переменную наprompt()
; или жеf
затем добавьтеf=s=>
в начало.Бег:
Дает вывод:
источник
/\s*/
до/ */
и удаливj=0
...
вместоapply
?...
) - это оператор, с которым я раньше не сталкивался.[].concat(...s.split`N`.map(x=>x.split(/ */).map((x,i,a)=>x+(a[x]=a[x]?++j:j=1)))).sort().map((x,i,a)=>a[i-1]<x?x[0]:'').join``;
Perl - 46 байт
Считая Шебанг как 1. Это свободный перевод решения Ruby ниже.
Рубин 1,8 - 72 байта
Вклад взят из
stdin
.Пример использования:
источник
/i
иfor
.Питон -
2062041991771451291179488 символовЯ не был уверен, как я должен был получить имя файла, поэтому в данный момент код предполагает, что он содержится в переменной с именем
f
. Пожалуйста, дайте мне знать, если мне нужно это изменить.источник
f
для входного имени файла и используя верхний регистр (все буквы магнита в любом случае являются заглавными), вы можете уменьшить его до 91:print(''.join([chr(i)*max(l.upper().count(chr(i))for l in open(f))for i in range(65,91)]))
Ruby 1.9+, 51 (или 58 или 60)
Предполагается, что все в нижнем регистре. Нечувствительность к регистру стоит 7 символов
.upcase
, а нечувствительность к регистру и вывод в нижнем регистре - 9 символов.downcase
.источник
R (156, включая чтение файла)
С помощью таблицы я строю таблицу частот букв для каждого предложения. Затем я получаю для каждой буквы максимальное значение.
Ungolfed:
Решение:
источник
a=unlist(lapply(readLines(fn),function(x)table(strsplit(tolower(x),""))));a=tapply(seq(a),names(a),function(i)max(a[i]))[-1];cat(rep(names(a),a),sep="")
, но это всего на 3 символа корочеcat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")
предполагающий использование только 112 символов,f
- это имя файлаHaskell,
109108Программа читает из stdin и пишет в sdtout.
Это довольно просто: он разбивает строку на список строк и перестраивает ее, перебирая список и добавляя новые буквы, содержащиеся в каждой строке.
источник
Perl 6:
5653 символа;5855 байтДля каждой строки она прочесывает ее для непробельных символов в строчной строке (
comb /\S/,.lc
) и создаетBag
или собирает каждый символ и сколько раз это происходит.[∪]
берет объединениеBag
s по всем строкам, которое получает максимальное количество раз, когда встречался символ..pick(*)
хак-у, но это самый короткий способ получить всех персонажей изBag
реплицированные по количеству повторений.РЕДАКТИРОВАТЬ: Чтобы увидеть, если это будет короче, я попытался перевести ответ гистократ Руби . Это 63 символа, но мне все еще очень нравится подход:
источник
Хаскелл,
183 162159Предполагая, что файл находится в
file.txt
!Если file.txt содержит, например,
Скрипт выведет
По сути, я добавляю весь алфавит к каждой строке, чтобы при группировке и сортировке я был уверен, что получу список из 27 элементов. Затем я переставляю «таблицу частот», чтобы каждая строка в этом массиве состояла из частот одной буквы в каждой строке, например
["a","","aaa","aa","aaaa"]
. Затем я выбираю максимум каждого массива (который работает точно так же, как я хочу из-за того, как работаетOrd
экземпляр-Strings), и удаляю букву, которую я добавил в начале, избавляюсь от пробелов и выводу результат.источник
drop 1
просто используйтеtail
С, 99 символов
Вылетает, если указано менее одного символа новой строки. Я думаю, что это можно исправить довольно легко.
источник
кдб (к / к): 59 символов:
-1 добавляет новую строку, использование 1 сохранит символ, но не сгенерирует указанный вывод. Хотел бы я избавиться от шаблона .z.pi / .z.exit, который удалил бы 14 символов.
Редактировать: избегать использования inter / asc с помощью начального словаря.
источник
Perl, 46
Вот еще одно решение Perl, считываемое из STDIN, требующее
-n
переключения (+1 к счету), связанное со счетом primo, но работающее без нареканий :-). Он использует тот факт, что побитовыйor
результат имеет большую длину строкового аргумента.источник
Я добавляю свое собственное решение:
Баш - 72
Предполагается, что вход находится в файле "я"
объяснение
Для каждой возможной буквы отфильтровывает ее только из входного файла, получая что-то вроде этого:
Затем результат сортируется и выбирается самая длинная строка.
echo -n
там, чтобы удалить переводы строки.источник
Баш,
171159158, 138 с ненужным выходомТребуется ввод только в нижнем регистре. Предполагается, что файл называется
_
(подчеркивание). Максимум 26 строк во входном файле из-за надоедливых имен файлов, которыеsplit
создает (xaa, xab ... xaz, ???).В
bash
,{a..z}
выходыa b c d e f ...
.Образец вывода
объяснение
Создайте файлы, которые мы будем читать позже, чтобы bash не жаловался, что их не существует. Если вы удалите эту строку, вы сохраните 13 символов, но получите много ненужного вывода.
Разделите входной файл на разделы, каждый из которых хранит 1 строку. Файлы, которые создает эта команда, называются xaa, xab, xac и так далее, я понятия не имею, почему.
Для каждого письма
$l
прочитайте все строки, хранящиеся в файлахxa$s
.Уберите
-s
переключатель, чтобы сохранить 1 символ и получить много ненужного вывода. Он не позволяетgrep
жаловаться на несуществующие файлы (произойдет, если у вас нет 26 строк ввода). Это обрабатывает файлxa$s
, удаляя все, кроме случаев$l
, и отправляя вывод в файлb$l
. Таким образом, «я люблю маму» становится «ммм» с новыми строками после каждой буквы, когда$l
м.Если количество строк в файле, который мы только что создали, больше или равно (то есть, больше букв, так как в строке одна буква), то количество строк в нашем самом высоком результате (сохраненном в
$l
) ...... сохранить нашу новую запись в файле
$l
. В конце этого цикла, когда мы прошли все строки, файл$l
будет хранить x строк, каждая из которых содержит букву$l
, где x - наибольшее количество вхождений этой буквы в одной строке.Выведите содержимое нашего файла для этой конкретной буквы, удалив новые строки. Если вы не хотите удалять новые строки, измените строку
tr
наecho $l
, сохранив 6 символов.источник
split
(от coreutils). В настоящее время я использую GNU bash 4.3.8 и GNU coreutils 8.21 на Ubuntu 14.04, и он отлично работает (он также работал на Ubuntu 13.10 до обновления). Однако мне пришлось поместить программу и входной файл в отдельный каталог, чтобы он работал должным образом - я подозреваю, что это произошло только из-за миллионов ненужных файлов в моей домашней папке .split _ -l1
и вы заметили, что ваш ввод сохраняется-l1aa
, я думаю, что ваша версияsplit
не распознается-l1
как опция, а вместо этого принимает ее за префикс для вывода. , Попробуйте поставить пробел между-l
и1
, или поставить--lines=1
, или просто-1
(кажется, это устаревший и более сложный синтаксис, который я сейчас обновлю).C #, 172 байта
источник
Питон 2 - 129
Идея от @Tal
Еще пара способов сделать то же самое в том же количестве символов:
Это предполагает, что файл сохранен как f в доступном каталоге. Эта программа запускается напрямую, без необходимости дополнительного ввода.
источник
Mathematica v10 - 110
Это еще не вышло, но чтение новой документации очень внимательно, я думаю, это должно работать:
источник
Скала, 125 символов
Сначала я читаю ввод, преобразовывая его в нижний регистр и добавляя одну пустую строку.
Затем для каждой буквы от
a
доz
я повторяю эту букву максимальное количество раз, которое она встречается в любой из строк (поэтому мне нужна пустая строка:max
не может быть вызвана на вход enpty). Затем я просто присоединяю результаты и печатаю к выводу.Для чтения из файла, заменить
stdin
сfromFile("FILENAME")
, увеличивая размер кода до 132 символов + файл длина имени.источник
Javascript, 261 символ
Удалить
eval(...)
и выполнить, чтобы получить реальный код; это ( несколько ) сжато.s
multi-функции как массив строк и как выведенная строка,h
содержит гистограмму букв в строке иH
содержит гистограмму с максимальными значениями до сих пор. Он не учитывает регистр и просто игнорирует все, кроме az и AZ (я думаю ... массивы JS иногда странные).Сейчас поправлю :)
источник
@
пока я не дошел до конца. Мне это нравится :)JavaScript ( ES5 ) 141 байт
Предполагая, что переменная
s
является входной строкой без требований проверки регистра и вывода массива:источник
PowerShell - 141
Читает текст из файла с именем «а».
источник
Groovy,
113/127102/116 символовПредполагая, что файл все в одном случае (102 символа):
Предполагая, что файл в смешанном регистре (116 символов):
В основном:
t=new File('f').text
Чтобы получить текст файла.t.findAll('[A-Z]').unique().sort().each{c->
Чтобы получить уникальные символы, сортируйте их и повторяйте.print c*t.readLines()*.count(c).max()
Получите максимальные вхождения в одну строку и напечатайте символ много раз.источник
Bash (в основном awk) -
172163157Текст должен быть передан в awk (или указан в виде файла).
Пример ввода
Пример вывода
PHP (возможно, может быть лучше) -
174210Предполагается, что строка содержится в переменной $ s
Пример ввода
Пример вывода
источник
Я понимаю, что это, вероятно, не самый эффективный ответ, но я все равно хотел попытаться решить проблему. Вот мой вариант ObjC:
Затем вы можете вызвать его для любой строки:
Я думал о приложениях с большим количеством текста, и мне не нужно считать мой массив. Для этого я добавил метод, чтобы получить это:
Беги как:
Дам тебе:
Что, я думаю, было бы лучше, если бы у меня было очень большое количество текста, и мне просто нужно было знать, сколько из каждого письма мне понадобится.
источник
К, 34
источник
Python 2, 154 байта
источник
s
в концеimport
оператора, а вwith
блоке отсутствует отступ. А так как это кодовый гольф, вам будет очень полезно удалить ненужные пробелы, где это возможно.C 298 байт
Массив D содержит количество букв для каждой строки, затем максимальное количество копируется в C.
Примечание: вчера я поставил свой ответ, но теперь его нет в списке. Может быть, я нажал кнопку «Удалить» вместо того, чтобы по ошибке редактировать?
источник
int
отint main()
иint j,n;
.PHP, 143 байта
Предполагая, что входные данные передаются в переменной
$s
:объяснение
Для каждой возможной буквы я отображаю массив, содержащий список строк, через пользовательскую функцию, которая заменяет каждую строку количеством используемых символов. Для буквы «d» строка «Мама любит папу» будет отображена в 3.
После этого я нахожу максимальное значение внутри массива и выходной буквы только много раз. Вот многострочная версия:
источник
Python (209, с включенным образцом, 136 без.):
Я выложу образец PYG сегодня днем.
источник