Алфавит моей дочери


65

На днях мы писали предложения с моей дочерью с магнитным письмом на холодильник. Хотя мы смогли сделать некоторые ( 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

(спасибо, Исаак!)

победитель

Кратчайшая реализация (код)

ОБНОВЛЕНО: Тестирование

Я создал дополнительный тест и попробовал с различными ответами здесь:

https://gist.github.com/romaninsh/11159751


2
В vвыводе должна быть буква ;)
Антонио Рагагнин

40
Разрешено ли / необходимо ли заменить перевернутую Mдля Wили боковую Nдля Z? ;-)
Илмари Каронен

4
По сути, вы можете построить любую букву, используя Is.
swish

7
Если серьезно, когда вы говорите «игнорировать случаи», вы имеете в виду, что мы можем предположить, что входные данные уже находятся в одном и том же случае или что мы должны преобразовать все это в один и тот же случай? Кроме того, это нормально для вывода, чтобы включить некоторые пробелы?
Ильмари Каронен

3
@ Doorknob:_\¯
Илмари Каронен

Ответы:


18

GolfScript, 28/34 символа

n/:a{|}*{a{.[2$]--}%*$-1=}%$

Программа, состоящая из 28 символов, предполагает, что все вводимые буквы находятся в одном и том же регистре. Если это не обязательно так, мы можем принудительно ввести их в верхний регистр, добавив {95&}%к коду всего 34 символа:

{95&}%n/:a{|}*{a{.[2$]--}%*$-1=}%$

Примечания:

  • Для корректной работы ввод должен содержать хотя бы одну новую строку. Это будет верно для обычных текстовых файлов с символами новой строки в конце каждой строки, но может быть неверным, если входные данные состоят только из одной строки без завершающего символа новой строки. Это может быть исправлено за счет двух дополнительных символов путем добавления n+кода.

  • Верхний регистр, используемый в 34-символьной версии, действительно грубый - он отображает строчные буквы ASCII в их прописные эквиваленты (и пробелы в NULs), но создает полный беспорядок чисел и большинства знаков препинания. Я предполагаю, что на входе не будет таких символов.

  • 28-символьная версия обрабатывает все входные символы (кроме символов новой строки и NULs) одинаково. В частности, если входные данные содержат пробелы, некоторые также появятся в выходных данных; удобно, они будут сортировать перед любыми другими печатными символами ASCII. Версия из 34 символов, тем не менее, игнорирует пробелы (потому что оказывается, что я могу сделать это без дополнительных затрат).

Объяснение:

  • Необязательный {95&}%префикс вводит верхний регистр ввода путем обнуления шестого бита кода ASCII каждого входного байта ( ). Это отображает строчные буквы ASCII в верхний регистр, пробелы в нулевые байты и оставляет новые строки без изменений.95 = 64 + 31 = 10111112

  • n/разбивает ввод в новых строках и :aприсваивает результирующий массив переменной a. Затем {|}*вычисляется объединение множеств строк в массиве, которое (при условии, что массив имеет как минимум два элемента) дает строку, содержащую все уникальные (не новые строки) символы во входных данных.

  • Следующий { }%цикл перебирает каждый из этих уникальных символов. Внутри тела цикла внутренний цикл a{.[2$]--}%выполняет итерацию по строкам в массиве a, удаляя из каждой строки все символы, не совпадающие с символами, по которым внешний цикл выполняет итерацию.

    Внутренний цикл оставляет код ASCII текущего символа в стеке ниже отфильтрованного массива. Мы используем это, повторяя отфильтрованный массив столько раз, сколько указано в коде ASCII ( *), прежде чем сортировать его ( $) и брать последний элемент ( -1=). По сути, это дает самую длинную строку в фильтрованном массиве (так как все они состоят из повторов одного и того же символа, лексикографическая сортировка просто сортирует их по длине), за исключением случаев, когда у символа есть код ASCII, равный нулю, и в этом случае он ничего не дает.

  • Наконец, $в конце просто сортирует вывод в алфавитном порядке.


3
Удивительно. ТОДО: Изучите GolfScript!
DLosc

1
Вы можете даже уменьшить его до 26 n/:a{|}*{{{=}+,}+a%$-1=}%$.
Говард

13

J - 37 символов

Читает из стандартного ввода, выводит на консоль.

dlb#&a.>./+/"2=/&a.tolower;._2[1!:1]3

1!:1]3это вызов к STDIN. tolower;._2выполняет двойную функцию, разбивая строки и делая их строчными одновременно. Затем мы подсчитываем, сколько раз символ встречается в каждой строке +/"2=/&a., и берем точечный максимум по всем строкам >./.

Наконец, мы вытягиваем столько символов из алфавита с помощью #&a.. Это включает пробелы - все они находятся спереди из-за их низкого значения ASCII - поэтому мы просто удаляем начальные пробелы с помощью dlb.


12

JavaScript (ECMAScript 6) - 148 139 135 символов

Версия 2:

Обновлен для использования понимания массива:

[a[i][0]for(i in a=[].concat(...s.split('\n').map(x=>x.split(/ */).sort().map((x,i,a)=>x+(a[i-1]==x?++j:j=0)))).sort())if(a[i-1]<a[i])]

Версия 1:

[].concat(...s.split('\n').map(x=>x.split(/ */).sort().map((x,i,a)=>x+(a[i-1]==x?++j:j=0)))).sort().filter((x,i,a)=>a[i-1]!=x).map(x=>x[0])

Предполагается, что:

  • Входная строка находится в переменной s;
  • Мы можем игнорировать случай ввода (как указано в вопросе - то есть все это в верхнем или нижнем регистре);
  • Вывод представляет собой массив символов (который настолько близок, насколько JavaScript может получить требование OP по списку символов); а также
  • Вывод должен отображаться на консоли.

С комментариями:

var l = s.split('\n')             // split the input up into sentences
         .map(x=>x.split(/ */)   // split each sentence up into letters ignoring any
                                  // whitespace
                  .sort()         // sort the letters in each sentence alphabetically
                  .map((x,i,a)=>x+(a[i-1]==x?++j:j=0)))
                                  // append the frequency of previously occurring identical
                                  // letters in the same sentence to each letter.
                                  // I.e. "HELLO WORLD" =>
                                  // ["D0","E0","H0","L0","L1","L2","O0","O1","R0","W0"]
[].concat(...l)                   // Flatten the array of arrays of letters+frequencies
                                  // into a single array.
  .sort()                         // Sort all the letters and appended frequencies
                                  // alphabetically.
  .filter((x,i,a)=>a[i-1]!=x)     // Remove duplicates and return the sorted
  .map(x=>x[0])                   // Get the first letter of each entry (removing the
                                  // frequencies) and return the array.

Если хочешь:

  • Верните его как строку, затем добавьте .join('')в конце;
  • Получите ввод от пользователя, затем замените sпеременную на prompt(); или же
  • Напишите это как функцию, fзатем добавьте f=s=>в начало.

Бег:

s="HELLO\nI LOVE CAT\nI LOVE DOG\nI LOVE MOMMY\nMOMMY LOVE DADDY";
[].concat(...s.split('\n').map(x=>x.split(/ */).sort().map((x,i,a)=>x+(a[i-1]==x?++j:j=0)))).sort().filter((x,i,a)=>a[i-1]!=x).map(x=>x[0])

Дает вывод:

["A","C","D","D","D","E","G","H","I","L","L","M","M","M","O","O","T","V","Y","Y"]

1
Приятно! Вы можете сэкономить 3 байта, уменьшив /\s*/до / */и удалив j=0
скобки

1
ты не мог бы использовать ...вместо apply?
Ven

Благодаря вам обоим - это экономит 9 символов - Оператор spread ( ...) - это оператор, с которым я раньше не сталкивался.
MT0

[].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``;
м2 18

11

Perl - 46 байт

#!perl -p
$s=~s/$_//ifor/./g;$s.=uc}for(sort$s=~/\w/g){

Считая Шебанг как 1. Это свободный перевод решения Ruby ниже.


Рубин 1,8 - 72 байта

s='';s+=$_.upcase.scan(/./){s.sub!$&,''}while gets;$><<s.scan(/\w/).sort

Вклад взят из stdin.

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

$ more in.dat
Hello
I love cat
I love dog
I love mommy
Mommy loves daddy

$ ruby fridge-letters.rb < in.dat
ACDDDEGHILLMMMOOSTVYY

Вывод должен быть отсортирован.
Мэтт

@Matt теперь исправлен.
Прим

Приятно. Если ваш Perl хоть и не совсем новый, вам понадобится пробел между /iи for.
tobyink

8

Питон - 206 204 199 177 145 129 117 94 88 символов

print(''.join(c*max(l.lower().count(c)for l in open(f))for c in map(chr,range(97,123))))

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


8
в духе Unix - вы могли читать со стандартного ввода.
Романиньш

5
всегда делайте имя файла длиной в один символ ...

3
@Tal Я тоже новичок, но если он спасает персонажей, почему бы и нет?

1
Предполагая fдля входного имени файла и используя верхний регистр (все буквы магнита в любом случае являются заглавными), вы можете уменьшить его до 91:print(''.join([chr(i)*max(l.upper().count(chr(i))for l in open(f))for i in range(65,91)]))
Гейб

1
@ njzk2 хорошо, если мы запустим это в консоли, теоретически он просто напечатает результат сам ...
Tal

6

Ruby 1.9+, 51 (или 58 или 60)

a=*$<
?a.upto(?z){|c|$><<c*a.map{|l|l.count c}.max}

Предполагается, что все в нижнем регистре. Нечувствительность к регистру стоит 7 символов .upcase, а нечувствительность к регистру и вывод в нижнем регистре - 9 символов .downcase.


4

R (156, включая чтение файла)

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

a=c();for(w in tolower(read.csv(fn,h=F)$V1))a=c(a,table(strsplit(w,"")[[1]]));a=tapply(seq(a),names(a),function(i)max(a[i]))[-1];cat(rep(names(a),a),sep="")

Ungolfed:

a=c()
words = read.csv(fn,h=F)$V1
for(w in tolower(words))
  a=c(a, table(strsplit(w, "")[[1]]))
a = tapply(seq(a), names(a), function(i) max(a[i]))[-1] ## The -1 excludes the space count.
cat(rep(names(a), a), sep="")

Решение:

acdddeghillmmmoooooostuvyy

@lambruscoAcido, вы можете векторизовать три первые строки (кода без гольфа), которые вам дадут 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 символа короче
jkd

Другой подход, cat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")предполагающий использование только 112 символов, f- это имя файла
jkd

4

Haskell, 109 108

import Data.List
import Data.Char
main=interact$sort.filter(/=' ').foldl1(\x y->x++(y\\x)).lines.map toLower

Программа читает из stdin и пишет в sdtout.

Это довольно просто: он разбивает строку на список строк и перестраивает ее, перебирая список и добавляя новые буквы, содержащиеся в каждой строке.


Ого, почему я никогда не слышал (\\) раньше?
Flonk


4

Perl 6: 56 53 символа; 58 55 байт

say |sort
([∪] lines.map:{bag comb /\S/,.lc}).pick(*)

Для каждой строки она прочесывает ее для непробельных символов в строчной строке ( comb /\S/,.lc) и создает Bagили собирает каждый символ и сколько раз это происходит. [∪]берет объединение Bags по всем строкам, которое получает максимальное количество раз, когда встречался символ. .pick(*)хак-у, но это самый короткий способ получить всех персонажей изBag реплицированные по количеству повторений.

РЕДАКТИРОВАТЬ: Чтобы увидеть, если это будет короче, я попытался перевести ответ гистократ Руби . Это 63 символа, но мне все еще очень нравится подход:

$!=lines».lc;->$c{print $c x max $!.map:{+m:g/$c/}} for"a".."z"

3

Хаскелл, 183 162 159

Предполагая, что файл находится в file.txt!

import Data.Char
import Data.List
main=readFile"file.txt">>=putStr.concat.tail.map(tail.maximum).transpose.map(group.sort.(++' ':['a'..'z'])).lines.map toLower

Если file.txt содержит, например,

abcde
abcdef
aaf

Скрипт выведет

aabcdef

По сути, я добавляю весь алфавит к каждой строке, чтобы при группировке и сортировке я был уверен, что получу список из 27 элементов. Затем я переставляю «таблицу частот», чтобы каждая строка в этом массиве состояла из частот одной буквы в каждой строке, например ["a","","aaa","aa","aaaa"]. Затем я выбираю максимум каждого массива (который работает точно так же, как я хочу из-за того, как работает Ordэкземпляр-Strings), и удаляю букву, которую я добавил в начале, избавляюсь от пробелов и выводу результат.


1
Вместо этого drop 1просто используйтеtail
Bergi

@ Берги Хаха, сумасшедший, спасибо! Я изменил это в посте.
Flonk

3

С, 99 символов

t[256];main(c){for(--*t;++t[1+tolower(getchar())];);for(c=97;c<123;c++)while(t[c]--)putchar(c-1);}

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


Я пытался, но это не дало правильных результатов. gist.github.com/romaninsh/11159751
romaninsh

3

кдб (к / к): 59 символов:

d:.Q.a! 26#0
.z.pi:{d|:.Q.a##:'=_y}.z.exit:{-1@,/.:[d]#'!:d}
  • создать предварительно отсортированный начальный словарь из алфавита .Qa
  • обрабатывает каждую строку ввода, преобразует в нижний регистр, группирует в словарь, подсчитывает каждый элемент, берет буквенные символы из результата (т.е. сокращает пробелы, переводы строк и т. д. на этом этапе) и использует max-assign для global d, чтобы сохранить промежуточный итог.
  • определить обработчик выхода, который передается в .z.pi для сохранения разделителя, но в противном случае там не используется. Возьмите из каждого значения ключа, чтобы сгенерировать список символов, сгладить и, наконец, вывести на стандартный вывод.

-1 добавляет новую строку, использование 1 сохранит символ, но не сгенерирует указанный вывод. Хотел бы я избавиться от шаблона .z.pi / .z.exit, который удалил бы 14 символов.

Редактировать: избегать использования inter / asc с помощью начального словаря.


3

Perl, 46

for$:(a..z){$a[ord$:]|=$:x s/$://gi}}{print@a

Вот еще одно решение Perl, считываемое из STDIN, требующее -nпереключения (+1 к счету), связанное со счетом primo, но работающее без нареканий :-). Он использует тот факт, что побитовый orрезультат имеет большую длину строкового аргумента.


1
попробовал с моим тестом, и он работал отлично.
Романиньш

3

Я добавляю свое собственное решение:

Баш - 72

Предполагается, что вход находится в файле "я"

for x in {A..Z};do echo -n `cat i|sed "s/[^$x]//g"|sort -r|head -1`;done

объяснение

Для каждой возможной буквы отфильтровывает ее только из входного файла, получая что-то вроде этого:

AAA
A
A

AAAA

A
AAAAAAAAAAAAAAAA

Затем результат сортируется и выбирается самая длинная строка. echo -nтам, чтобы удалить переводы строки.


3

Баш, 171 159 158, 138 с ненужным выходом

Требуется ввод только в нижнем регистре. Предполагается, что файл называется _(подчеркивание). Максимум 26 строк во входном файле из-за надоедливых имен файлов, которые splitсоздает (xaa, xab ... xaz, ???).

В bash, {a..z}выходы a b c d e f ....

touch {a..z}
split _ -1
for l in {a..z}
do for s in {a..z}
do grep -so $l xa$s>b$l
if [ `wc -l<b$l` -ge `wc -l<$l` ]
then mv b$l $l
fi
done
tr -d '\n'<$l
done

Образец вывода

acdddeghillmmmoostvyy

объяснение

touch {a..z}

Создайте файлы, которые мы будем читать позже, чтобы bash не жаловался, что их не существует. Если вы удалите эту строку, вы сохраните 13 символов, но получите много ненужного вывода.

split _ -1

Разделите входной файл на разделы, каждый из которых хранит 1 строку. Файлы, которые создает эта команда, называются xaa, xab, xac и так далее, я понятия не имею, почему.

for l in {a..z}
do for s in {a..z}

Для каждого письма $lпрочитайте все строки, хранящиеся в файлах xa$s.

do grep -so $l xa$s>b$l

Уберите -sпереключатель, чтобы сохранить 1 символ и получить много ненужного вывода. Он не позволяет grepжаловаться на несуществующие файлы (произойдет, если у вас нет 26 строк ввода). Это обрабатывает файл xa$s, удаляя все, кроме случаев $l, и отправляя вывод в файл b$l. Таким образом, «я люблю маму» становится «ммм» с новыми строками после каждой буквы, когда $lм.

if [ `wc -l<b$l` -ge `wc -l<$l` ]

Если количество строк в файле, который мы только что создали, больше или равно (то есть, больше букв, так как в строке одна буква), то количество строк в нашем самом высоком результате (сохраненном в $l) ...

then mv b$l $l

... сохранить нашу новую запись в файле $l. В конце этого цикла, когда мы прошли все строки, файл $lбудет хранить x строк, каждая из которых содержит букву $l, где x - наибольшее количество вхождений этой буквы в одной строке.

fi
done
tr -d '\n'<$l

Выведите содержимое нашего файла для этой конкретной буквы, удалив новые строки. Если вы не хотите удалять новые строки, измените строку trна echo $l, сохранив 6 символов.

done

Пробовал с GNU bash, версия 3.2.51 (apple), но файл '-l1aa' в текущей папке, содержащей входные данные ..
romaninsh

@romaninsh Возможно, у вас другая версия split(от coreutils). В настоящее время я использую GNU bash 4.3.8 и GNU coreutils 8.21 на Ubuntu 14.04, и он отлично работает (он также работал на Ubuntu 13.10 до обновления). Однако мне пришлось поместить программу и входной файл в отдельный каталог, чтобы он работал должным образом - я подозреваю, что это произошло только из-за миллионов ненужных файлов в моей домашней папке .

На самом деле @romaninsh, если вы посмотрите на точную команду в сценарии: split _ -l1и вы заметили, что ваш ввод сохраняется -l1aa, я думаю, что ваша версия split не распознается -l1как опция, а вместо этого принимает ее за префикс для вывода. , Попробуйте поставить пробел между -lи 1, или поставить --lines=1, или просто -1(кажется, это устаревший и более сложный синтаксис, который я сейчас обновлю).

3

C #, 172 байта

var x="";foreach(var i in File.ReadAllText(t).ToLower().Split('\r','\n'))foreach(var j in i)if(x.Count(c=>c==j)<i.Count(c=>c==j))x+=j;string.Concat(x.OrderBy(o=>o)).Trim();

Умный ... умный ... Я думал об игре с linq, но сомневаюсь, что он будет таким же коротким, как эти искаженные foreachs :)
Noctis

2

Питон 2 - 129

Идея от @Tal

a,r=[0]*26,range(26)
for l in open('f'):a=[max(a[i],l.lower().count(chr(i+97)))for i in r]
print''.join(chr(i+97)*a[i]for i in r)

Еще пара способов сделать то же самое в том же количестве символов:

a=[0]*26
b='(chr(i+97)))for i in range(26)'
exec'for l in open("f"):a=[max(a[i],l.lower().count'+b+']\nprint"".join(a[i]*('+b+')'

a=[0]*26
b='(chr(i+97)))for i in range(26))'
exec'for l in open("f"):a=list(max(a[i],l.lower().count'+b+'\nprint"".join(a[i]*('+b

Это предполагает, что файл сохранен как f в доступном каталоге. Эта программа запускается напрямую, без необходимости дополнительного ввода.


Почему голосование против? Извините, если я сделал что-то не так.
Исаак


2

Скала, 125 символов

val i=""::io.Source.stdin.getLines.toList.map(_.toLowerCase);println('a'to'z'map(c=>(""+c)*i.map(_.count(_==c)).max)mkString)

Сначала я читаю ввод, преобразовывая его в нижний регистр и добавляя одну пустую строку.

Затем для каждой буквы от aдо zя повторяю эту букву максимальное количество раз, которое она встречается в любой из строк (поэтому мне нужна пустая строка: maxне может быть вызвана на вход enpty). Затем я просто присоединяю результаты и печатаю к выводу.

Для чтения из файла, заменить stdinс fromFile("FILENAME"), увеличивая размер кода до 132 символов + файл длина имени.


2

Javascript, 261 символ

eval('s=prompt().toUpperCase().split("\\n");Z=[########0,0];H=Z.slice();s@r){h=Z.slice();r.split("")@c){if(c.match(/\\w/))h[c.charCodeAt(0)-65]++});H=H@V,i){return V>h[i]?V:h[i]})});s="";H@n,i){s+=Array(n+1).join(String.fromCharCode(i+97))});s'.replace(/@/g,".map(function(").replace(/#/g,"0,0,0,"))

Удалить eval(...)и выполнить, чтобы получить реальный код; это ( несколько ) сжато.

smulti-функции как массив строк и как выведенная строка, hсодержит гистограмму букв в строке и Hсодержит гистограмму с максимальными значениями до сих пор. Он не учитывает регистр и просто игнорирует все, кроме az и AZ (я думаю ... массивы JS иногда странные).

Сейчас поправлю :)


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

@ Мэтт, да, все верно ... Я исправлю это позже. На самом деле сейчас нет времени.
Томсминг

1
Интересно, что происходит, @пока я не дошел до конца. Мне это нравится :)
Мэтт

2

JavaScript ( ES5 ) 141 байт

Предполагая, что переменная sявляется входной строкой без требований проверки регистра и вывода массива:

for(a in s=s[o=_='',y='split']('\n'))for(i=0;x=s[a][i++];)o+=x!=0&&(l=s[a][y](x).length-~-o[y](x).length)>0?Array(l).join(x):_;o[y](_).sort()

Я проверил ваше решение и искал вывод "o", но, похоже, он не отсортирован должным образом. (см. gist.github.com/romaninsh/11159751 )
romaninsh

@romaninsh вывод, который я вижу в твоей сути, выглядит правильно отсортированным
nderscore

Да, это справочный / правильный вывод. Когда я попробовал ваш код, я получил это: gist.github.com/romaninsh/11161018
romaninsh

Извиняюсь, если я выполнил ваш пример неправильно.
Романиньш

@romaninsh ах, я собирался запустить его в консоли браузера. Вот переформатированная версия, которая работает на узле: gist.github.com/nderscore/96aa888c77d275c26c15
nderscore

2

PowerShell - 141

Читает текст из файла с именем «а».

$x=@{}
gc a|%{[char[]]$_|group|%{$c=$_.name.tolower().trim()
$n=$_.count;$x[$c]=($n,$x[$c])[$n-lt$x[$c]]}}
($x.Keys|sort|%{$_*$x[$_]})-join""

2

Groovy, 113/127 102/116 символов

Предполагая, что файл все в одном случае (102 символа):

t=new File('f').text;t.findAll('[A-Z]').unique().sort().each{c->print c*t.readLines()*.count(c).max()}

Предполагая, что файл в смешанном регистре (116 символов):

t=new File('f').text.toUpperCase();t.findAll('[A-Z]').unique().sort().each{c->print c*t.readLines()*.count(c).max()}

В основном:

  • t=new File('f').text Чтобы получить текст файла.
  • t.findAll('[A-Z]').unique().sort().each{c-> Чтобы получить уникальные символы, сортируйте их и повторяйте.
  • print c*t.readLines()*.count(c).max() Получите максимальные вхождения в одну строку и напечатайте символ много раз.

2

Bash (в основном awk) - 172 163 157

awk -v FS="" '{delete l;for(i=1;i<=NF;i++)l[toupper($i)]++;for(i in l)o[i]=(o[i]>l[i]?o[i]:l[i])}END{for(i in o)for(j=0;j<o[i];j++)print i}'|sort|tr -d ' \n'

Текст должен быть передан в awk (или указан в виде файла).

Пример ввода

Hello
I love cat
I love dog
I love mommy
Mommy loves daddy

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

ACDDDEGHILLMMMOOSTVYY

PHP (возможно, может быть лучше) - 174 210

$o=array();foreach(explode("\n",$s) as $a){$l=array();$i=0;while($i<strlen($a)){$k=ucfirst($a[$i++]);if($k==' ')continue;$o[$k]=max($o[$k],++$l[$k]);}}ksort($o);foreach($o as $k=>$v)for($i=0;$i<$v;$i++)echo $k;

Предполагается, что строка содержится в переменной $ s

Пример ввода

Hello
I love cat
I love dog
I love mommy
Mommy loves daddy

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

ACDDDEGHILLMMMOOSTVYY

2

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

- (NSArray *) lettersNeededForString:(NSString *)sourceString {
    sourceString = [sourceString stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    sourceString = [sourceString stringByReplacingOccurrencesOfString:@" " withString:@""];
    const char * sourceChars = sourceString.UTF8String;
    NSMutableArray * arr = [NSMutableArray new];
    for (int i = 0; i < sourceString.length; i++) {
        [arr addObject:[NSString stringWithFormat:@"%c", sourceChars[i]]];
    }
    return [arr sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
}    

Затем вы можете вызвать его для любой строки:

NSArray * letters = [self lettersNeededForString:@"Hello\nI love cat\nI love dog\nI love mommy\nMommy loves daddy"];
NSLog(@"%@",letters);

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

- (NSDictionary *) numberOfLettersNeededFromString:(NSString *)sourceString {

    sourceString = [sourceString stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    sourceString = [sourceString stringByReplacingOccurrencesOfString:@" " withString:@""];
    const char * sourceChars = sourceString.UTF8String;
    NSMutableArray * arr = [NSMutableArray new];
    for (int i = 0; i < sourceString.length; i++) {
        [arr addObject:[NSString stringWithFormat:@"%c", sourceChars[i]]];
    }

    static NSString * alphabet = @"abcdefghijklmnopqrstuvwxyz";
    NSMutableDictionary * masterDictionary = [NSMutableDictionary new];
    for (int i = 0; i < alphabet.length; i++) {
        NSString * alphabetLetter = [alphabet substringWithRange:NSMakeRange(i, 1)];
        NSIndexSet * indexes = [arr indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
            if ([[(NSString *)obj lowercaseString] isEqualToString:alphabetLetter]) {
                return YES;
            }
            else {
                return NO;
            }
        }];

        masterDictionary[alphabetLetter] = @(indexes.count);
    }

    return masterDictionary;
}

Беги как:

NSDictionary * lettersNeeded = [self numberOfLettersNeededFromString:@"Hello\nI love cat\nI love dog\nI love mommy\nMommy loves daddy"];
NSLog(@"%@", lettersNeeded);

Дам тебе:

{а = 2; б = 0; с = 1; д = 4; е = 5; f = 0; г = 1; h = 1; я = 3; j = 0; k = 0; l = 6; м = 6; n = 0; о = 8; р = 0; q = 0; r = 0; s = 1; т = 1; и = 0; v = 4; w = 0; х = 0; у = 3; z = 0; }

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



2

Python 2, 154 байта

import collections
c = collections.Counter()
for line in open("input.txt"):
    c |= collections.Counter(line.upper())
print "".join(sorted(c.elements()))

Добро пожаловать в PCG! Этот сайт поддерживает синтаксис Markdown, который можно использовать для форматирования кода, чтобы он выглядел хорошо: просто сделайте отступ в каждой строке кода на 4 пробела.
алгоритмистика

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

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

Вы пропускаете sв конце importоператора, а в withблоке отсутствует отступ. А так как это кодовый гольф, вам будет очень полезно удалить ненужные пробелы, где это возможно.
Fraxtil

так как это кодовый гольф, удалите оператор with (просто переберите вызов open), и я не думаю, что элементы нуждаются в сортировке.
RemcoGerlich

2

C 298 байт

char c;
int j,n;
char C[26];
char D[26];
int main()
{
char a='a';
while((c=getchar())>=0)
{
c=tolower(c);
if(c>=a&&c<='z'){j=c-a;D[j]++;}
if(c=='\n'){
for(j=0;j<26;j++){
if(D[j]>C[j])
{C[j]=D[j];}
D[j]=0;
}
}
}
for(j=0;j<26;j++)
{
n=C[j];
while(n--)
{
putchar(a+j);
}
}
}

Массив D содержит количество букв для каждой строки, затем максимальное количество копируется в C.

Примечание: вчера я поставил свой ответ, но теперь его нет в списке. Может быть, я нажал кнопку «Удалить» вместо того, чтобы по ошибке редактировать?


Это всего 271 байт. У вас также есть много посторонних новых строк. Кроме того, вы можете опустить intот int main()и int j,n;.
nyuszika7h

Кроме того, ваш предыдущий ответ все еще там.
nyuszika7h

2

PHP, 143 байта

Предполагая, что входные данные передаются в переменной $s:

$i=explode("\n",$s);foreach(range('a','z')as$c){$x=array_map(function($l)use($c){return substr_count($l,$c);},$i);echo str_repeat($c,max($x));}

объяснение

Для каждой возможной буквы я отображаю массив, содержащий список строк, через пользовательскую функцию, которая заменяет каждую строку количеством используемых символов. Для буквы «d» строка «Мама любит папу» будет отображена в 3.

После этого я нахожу максимальное значение внутри массива и выходной буквы только много раз. Вот многострочная версия:

$i=explode("\n",$s);
foreach(range('A','Z')as $c){
    $x=array_map(function($l)use($c){
        return substr_count($l,$c);
    },$i);
    echo str_repeat($c,max($x));
}

1

Python (209, с включенным образцом, 136 без.):

from collections import*;c=Counter()
for i in ["Hello","I love cat", "I love Dog", "I love mommy", "Mommy loves daddy"]:
 for j in i.lower(): c[j]=max(c[j],list(i).count(j))
print "".join(sorted(c.elements()))

Я выложу образец PYG сегодня днем.


Я понятия не имел, что в строках Python есть метод подсчета ... Я не думаю, что считается правильным изменить свой ответ на вопрос, чтобы использовать это новое найденное знание? : p
Tal

@tal Они не делают. Это метод списка, если вы посмотрите ближе
Aprıʇǝɥʇuʎs

1
О, я вижу ... но неожиданным образом оказывается, что у строк, по-видимому, также есть этот метод (в любом случае в 3.x)
Tal
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.