Алфавіт моєї дочки


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

(спасибі, isaacg!)

Переможець

Найкоротша реалізація (код)

ОНОВЛЕНО: Тестування

Я створив додатковий тест і спробував тут різні відповіді:

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


2
У vвиході має бути лист ;)
Антоніо Рагагнін

40
Чи дозволено нам / зобов’язано замінити перевернутий на ногу Ma Wабо збоку Nна a Z? ;-)
Ілмарі Каронен

4
В основному ви можете побудувати будь-який лист за допомогою Is.
швейцарський

7
Більш серйозно, якщо ви говорите "ігноруйте випадки", ви маєте на увазі, що ми можемо вважати, що вхід вже є в одному і тому ж випадку, або що ми повинні все це перетворити в той самий випадок? Крім того, чи нормально, щоб вихід містив провідні пробіли?
Ільмарі Каронен

3
@Doorknob:_\¯
Ilmari Karonen

Відповіді:


18

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

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

Програма з 28 символами вище передбачає, що всі вхідні літери знаходяться в одному і тому ж регістрі. Якщо це не обов'язково, ми можемо змусити їх у верхньому регістрі, попередньо додавши {95&}%до коду, загалом 34 символи:

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

Примітки:

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

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

  • 28-символьна версія NULоднаково розглядає всі вхідні символи (крім нових рядків та s). Зокрема, якщо вхід містить якісь пробіли, деякі також з’являться у висновку; зручно вони сортуватимуть перед будь-якими іншими символами для друку ASCII. 34-символьна версія, однак, ігнорує пробіли (оскільки, виявляється, я можу це зробити, без того, щоб це коштувало мені додаткових символів).

Пояснення:

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

  • n/розбиває введення на нові рядки та :aприсвоює отриманий масив змінній a. Потім {|}*обчислює встановлене об'єднання рядків у масиві, який (припускаючи, що масив має щонайменше два елементи) дає рядок, що містить усі унікальні (ненові рядки) символи у вхідному документі.

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

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

  • Нарешті, $в кінці просто сортує вихідний алфавіт.


3
Дивовижний. TODO: Дізнайтеся GolfScript!
DLosc

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

13

J - 37 char

Читає від stdin, виводить на консоль.

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 може дійти до вимоги ОП щодо списку символів); і
  • Вихід повинен відображатися на консолі.

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

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
nderscore

1
ти не міг використати ...замість цього apply?
Вр

Завдяки вам обом - що зберігає 9 символів - оператор спред ( ...) - це той, якого я раніше не стикався.
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``;
l4m2

11

Perl - 46 байт

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

Підрахунок шебангу як 1. Це нижчий переклад рішення Рубі нижче.


Рубін 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 - можна було читати зі stdin.
romaninsh

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="")

Безголівки:

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

Інший підхід тільки 112 символів було б cat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")передбачають fім'я файлу
ДКД

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.

Це досить просто: він розбиває рядок на список рядків і відновлює його, повторюючи його за списком і додаючи нові літери, що містяться в кожному рядку.


Ох, чому я ніколи раніше не чув (\\)?
Флонк


4

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

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

Для кожного рядка він розчісує його для непробільних символів рядка з нижньою обробкою ( comb /\S/,.lc), і робить a Bag, або колекцію кожного символу і скільки разів він відбувається. [∪]приймає об'єднання Bags по всіх рядках, що отримує максимальну кількість разів, коли персонаж відбувся. .pick(*)тут хак-у, але це найкоротший спосіб отримати всіх персонажів з Bagреплікації, скільки разів це відбулося.

EDIT: Щоб побачити, чи буде це коротше, я спробував перекласти відповідь Рубі на свого історика . Це 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

Якщо файл.txt містить, наприклад,

abcde
abcdef
aaf

Сценарій виведе

aabcdef

В основному я додаю цілий алфавіт до кожного рядка, так що при групуванні та сортуванні я впевнений, що в кінцевому підсумку зі списком, який містить 27 елементів. Далі я перекладаю "таблицю частот", так що кожен рядок у цьому масиві складається з частот однієї літери у кожному рядку, наприклад ["a","","aaa","aa","aaaa"]. Потім я вибираю максимум кожного масиву (який працює так, як я хочу через те, як працює Ordречовина Strings), і відкидаю лист, який я додав на початку, позбавляюсь пробілів і виводжу результат.


1
Замість цього drop 1просто скористайтесяtail
Бергі

@Bergi Haha дерп, дякую! Я змінив це на посаді.
Флонк

3

C, 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

kdb (q / k): 59 символів:

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

-1 додає новий рядок, використовуючи 1, збереже символ, але не генерує вказаний вихід. Побажаю, щоб я міг позбутися котлової коробки .z.pi / .z.exit, на якому було б видалено 14 символів.

Редагувати: уникайте використання inter / asc, використовуючи насіннєвий словник.


3

Перл, 46

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

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


1
спробував з моїм тестом, і він спрацював чудово.
romaninsh

3

Я додаю власне рішення:

Баш - 72

Передбачається, що вхід знаходиться у файлі "i"

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 char і отримати багато небажаної продукції. Це заважає 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збереже х рядків, кожен з яких містить літеру $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, але сумніваюся, що це буде так коротко, як ці спотворені передчуття :)
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 у доступному каталозі. Ця програма безпосередньо керується, не потребуючи додаткового введення.


Чому голосування проти? Вибачте, якщо я зробив щось не так.
isaacg

2

Mathematica v10 - 110

Ще не вийшло, але читати нову документацію дуже уважно, я думаю, це має спрацювати:

StringJoin@MapIndexed[#2~Table~{#1}&,Rest@Merge[Counts/@Characters@StringSplit[ToLowerCase@Input[],"\n"],Max]]

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не можна викликати на порожній вхід). Тоді я просто приєднуюся до результатів і друкую на вихід.

Для читання з файлу замініть 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(...)і виконайте, щоб отримати реальний код; це ( дещо ) стиснуте.

sбагатофункціональність як масив рядків і як рядок, що виводиться, hмістить гістограму букв на рядок і Hмістить гістограму з максимальними значеннями до цих пір. Це нечутливе до регістру, і просто ігнорує будь-що, крім az та AZ (я думаю ... JS-масиви іноді дивні).

Тепер правильно :)


Це просто підсумовує персонажів, не зовсім те, що задавали питання. Літери повинні бути загальним мінімальним значенням, щоб утворювати будь-яке одне речення у введенні, не всі. Мені дуже подобається ваш підхід, щоб запобігти необхідності сортування вихідних даних.
Метт

@ Матт о, це правильно ... я це виправлю пізніше. Наразі ще не було часу.
tomsmeding

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

Так, це вихідний / правильний вихід. Коли я спробував ваш код, у мене з'ясувалося
romaninsh

Вибачте, якщо я неправильно виконав ваш приклад.
romaninsh

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

2

PowerShell - 141

Читає текст з файлу з назвою "a".

$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

Гроовий , 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);

Дасть вам:

{a = 2; b = 0; c = 1; d = 4; е = 5; f = 0; g = 1; h = 1; i = 3; j = 0; k = 0; l = 6; m = 6; n = 0; o = 8; р = 0; q = 0; r = 0; s = 1; t = 1; u = 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 пробілами.
алгоритм

Вам потрібно буде додати символи, необхідні для імпорту колекцій.
isaacg

1
не відповідає на запитання, оскільки вам потрібна мінімальна кількість літер, щоб написати кожне речення окремо. У своєму коді ви виводите кількість букв, необхідних для написання всіх речень одночасно.
njzk2

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

Оскільки це код гольфу, видаліть з оператором (просто переведіть на дзвінок, щоб відкрити), і я не думаю, що елементи потребують сортування.
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 Вони цього не роблять. Це метод списку, якщо придивитись ближче
ɐɔıʇǝɥʇuʎs

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