Alfabet mojej córki

65

Pewnego dnia pisaliśmy zdania z moją córką za pomocą magnesu na lodówkę. Chociaż mogliśmy stworzyć niektóre ( I love cat), nie mieliśmy wystarczającej liczby liter, aby utworzyć inne ( I love you too) z powodu niewystarczającej ilości liter o(4)

Potem dowiedziałem się, że chociaż jeden zestaw zawiera 3 elitery, ma tylko 2 olitery. Prawdopodobnie zainspirowany http://en.wikipedia.org/wiki/Letter_frequency nadal nie odzwierciedlałoby to faktycznej sytuacji „na lodówce”.

Problem

Biorąc pod uwagę plik tekstowy, w którym każda linia zawiera „przykładowe zdanie”, które chcielibyśmy napisać na lodówce, zaproponuj zestaw alfabetu z minimalną ilością liter, ale wciąż wystarczającą do napisania każdego zdania osobno.

Uwaga: ignoruj ​​przypadki, wszystkie litery magnesów i tak są wielkimi literami.

Wejście

Plik zawiera zdania oddzielone znakiem nowej linii:

hello
i love cat
i love dog
i love mommy
mommy loves daddy

Wynik

Podaj posortowaną listę liter, gdzie każda litera pojawia się tylko tyle razy, aby wystarczyło napisać dowolne zdanie:

acdddeghillmmmoostvyy

(dzięki, isaacg!)

Zwycięzca

Najkrótsza implementacja (kod)

AKTUALIZACJA: Testowanie

Stworzyłem dodatkowy test i wypróbowałem różne odpowiedzi tutaj:

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

romaninsh
źródło
2
vWyjście powinno zawierać literę ;)
Antonio Ragagnin
40
Czy wolno nam / obowiązkowo zamienić na odwrócone Mna W, czy na boki Nna Z? ;-)
Ilmari Karonen
4
Zasadniczo możesz zbudować dowolną literę za pomocą Is.
świst
7
Mówiąc poważniej, kiedy mówisz „ignoruj ​​przypadki”, czy masz na myśli, że możemy założyć, że dane wejściowe są już w tym samym przypadku, czy też musimy je przekonwertować na tę samą sprawę? Ponadto, czy wyjście może zawierać niektóre spacje wiodące?
Ilmari Karonen
3
@Doorknob:_\¯
Ilmari Karonen

Odpowiedzi:

18

GolfScript, 28/34 znaków

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

28-znakowy program powyżej zakłada, że ​​wszystkie litery wejściowe są w tym samym przypadku. Jeśli nie jest to konieczne, możemy zmusić je do wielkich liter, przygotowując {95&}%się do kodu, w sumie 34 znaków:

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

Uwagi:

  • W celu poprawnego działania wejście musi zawierać co najmniej jedną nową linię. Dotyczy to normalnych plików tekstowych z nowymi liniami na końcu każdej linii, ale może nie być prawdą, jeśli dane wejściowe składają się tylko z jednej linii bez nowej linii. Można to naprawić kosztem dwóch dodatkowych znaków, przygotowując n+kod.

  • Wielkie litery używane w wersji 34-znakowej są naprawdę prymitywne - odwzorowuje małe litery ASCII na ich wielkie odpowiedniki (i spacje na NULs), ale robi kompletny bałagan z liczbami i większością interpunkcji. Zakładam, że dane wejściowe nie będą zawierać takich znaków.

  • Wersja 28-znakowa traktuje NULjednakowo wszystkie znaki wejściowe (oprócz znaków nowej linii i ). W szczególności, jeśli dane wejściowe zawierają spacje, niektóre z nich pojawią się również w danych wyjściowych; wygodnie będą sortować przed innymi drukowalnymi znakami ASCII. Jednak wersja 34-znakowa ignoruje spacje (ponieważ okazuje się, że mogę to zrobić bez dodatkowych kosztów).

Wyjaśnienie:

  • Opcjonalny {95&}%przedrostek góruje wielkość wejściową, zerując szósty bit kodu ASCII każdego bajtu wejściowego ( ). To odwzorowuje małe litery ASCII na wielkie, spacje na puste bajty i pozostawia nowe wiersze bez zmian.95 = 64 + 31 = 10111112

  • n/dzieli dane wejściowe w znakach nowej linii i :aprzypisuje wynikową tablicę do zmiennej a. Następnie {|}*oblicza zestaw unii ciągów w tablicy, która (zakładając, że tablica ma co najmniej dwa elementy) daje ciąg zawierający wszystkie unikalne (nie-nowe znaki) dane wejściowe.

  • Następująca { }%pętla iteruje następnie każdy z tych unikalnych znaków. Wewnątrz korpusu pętli wewnętrzna pętla a{.[2$]--}%iteruje się po łańcuchach w tablicy a, usuwając z każdego łańcucha wszystkie znaki, które nie są równe temu, nad którym iteruje zewnętrzna pętla.

    Wewnętrzna pętla pozostawia kod ASCII bieżącego znaku na stosie, poniżej filtrowanej tablicy. Wykorzystujemy to, powtarzając filtrowaną tablicę tyle razy, ile wskazuje kod ASCII ( *) przed posortowaniem jej ( $) i wzięciem ostatniego elementu ( -1=). W efekcie daje to najdłuższy ciąg w filtrowanej tablicy (ponieważ wszystkie składają się z powtórzeń tego samego znaku, sortowanie leksykograficzne po prostu sortuje je według długości), z wyjątkiem sytuacji, gdy znak ma kod ASCII zero, w którym to przypadku nie daje nic.

  • Wreszcie, $na końcu sortuje dane wyjściowe alfabetycznie.

Ilmari Karonen
źródło
3
Niesamowity. DO ZROBIENIA: Naucz się golfa!
DLosc
1
Można nawet je zmniejszyć do 26: n/:a{|}*{{{=}+,}+a%$-1=}%$.
Howard
13

J - 37 char

Odczytuje ze standardowego wyjścia na konsolę.

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

1!:1]3jest wezwanie do stdin. tolower;._2wykonuje podwójną funkcję, dzieląc linie i czyniąc je jednocześnie małymi literami. Następnie zliczamy, ile razy znak występuje w każdym rzędzie +/"2=/&a., i przyjmujemy punktowe maksimum we wszystkich wierszach za pomocą >./.

Na koniec usuwamy tyle znaków z alfabetu za pomocą #&a.. Obejmuje to spacje - wszystkie znalezione z przodu ze względu na ich niską wartość ASCII - więc po prostu usuwamy wiodące spacje dlb.

algorytmshark
źródło
12

JavaScript (ECMAScript 6) - 148 139 135 znaków

Wersja 2:

Zaktualizowano w celu użycia zrozumienia tablic:

[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])]

Wersja 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])

Zakłada, że:

  • Łańcuch wejściowy znajduje się w zmiennej s;
  • Możemy zignorować wielkość liter wejściowych (jak określono w pytaniu - tzn. Wszystko jest pisane wielkimi lub małymi literami);
  • Dane wyjściowe to tablica znaków (która jest tak bliska, jak JavaScript może uzyskać wymaganie OP dotyczące listy znaków); i
  • Dane wyjściowe mają być wyświetlane na konsoli.

Z komentarzami:

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.

Jeśli chcesz:

  • Zwróć jako ciąg, a następnie dodaj .join('')na końcu;
  • Weź dane od użytkownika, a następnie zamień szmienną na prompt(); lub
  • Napisz jako funkcję, fa następnie dodaj f=s=>na początek.

Bieganie:

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])

Daje wynik:

["A","C","D","D","D","E","G","H","I","L","L","M","M","M","O","O","T","V","Y","Y"]
MT0
źródło
1
Miły! Można zapisać 3 bajty poprzez zmniejszenie /\s*/do / */i usuwanie nawiasów wokółj=0
nderscore
1
nie możesz użyć ...zamiast apply?
Ven
Dzięki wam obojgu - co oszczędza 9 znaków - operator spread ( ...) to taki, którego wcześniej nie spotkałem.
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 bajtów

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

Liczenie shebang jako 1. To jest luźne tłumaczenie poniższego rozwiązania Ruby.


Rubinowy 1,8 - 72 bajtów

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

Dane wejściowe są pobierane z stdin.

Przykładowe użycie:

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

$ ruby fridge-letters.rb < in.dat
ACDDDEGHILLMMMOOSTVYY
primo
źródło
Dane wyjściowe należy posortować.
Matt
@Matt został naprawiony.
primo
Miły. Jeśli twój Perl jest nieco nowy, będziesz potrzebować spacji między /ia for.
tobyink
8

Python - 206 204 199 177 145 129 117 94 88 znaków

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

Nie byłem pewien, jak mam uzyskać nazwę pliku, więc w tej chwili kod zakłada, że ​​jest zawarty w zmiennej o nazwie f. Daj mi znać, jeśli będę musiał to zmienić.

Tal
źródło
8
w duchu unixa - można czytać ze standardowego wejścia.
romaninsh,
5
zawsze
3
@Tal Jestem również nowy, ale jeśli zapisuje postacie, dlaczego nie?
1
Przyjmując fnazwę pliku wejściowego i używając wielkich liter (i tak wszystkie litery magnesów są duże), możesz sprowadzić ją do 91:print(''.join([chr(i)*max(l.upper().count(chr(i))for l in open(f))for i in range(65,91)]))
Gabe
1
@ njzk2 cóż, jeśli uruchomimy to w konsoli, teoretycznie po prostu wydrukuje wynik sam ...
Tal
6

Ruby 1.9+, 51 (lub 58 lub 60)

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

Zakłada, że ​​wszystko jest pisane małymi literami. Sprawa niewrażliwość kosztuje 7 znaków za pośrednictwem .upcase, natomiast przypadek niewrażliwość i małe wyjściowe koszty poprzez 9 znaków .downcase.

histocrat
źródło
4

R (156, w tym odczyt pliku)

Z tabeli tworzę tabelę częstotliwości liter dla każdego zdania. Następnie kończę przyjmowanie dla każdej litery maksymalnej wartości.

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

Nie golfowany:

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

Rozwiązanie:

acdddeghillmmmoooooostuvyy
lambruscoAcido
źródło
@lambruscoAcido możesz wektoryzować trzy pierwsze wiersze (kodu nie golfowego), które by ci dały 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=""), ale jest on tylko o 3 znaki krótszy
jkd
Innym podejściem tylko 112 znaków byłoby cat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")zakładając fto nazwa
JKD
4

Haskell, 109 108

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

Program odczytuje ze standardowego wejścia i zapisuje do sdtout.

Jest to dość proste: dzieli łańcuch na listę linii i odbudowuje go, iterując na liście i dodając nowe litery zawarte w każdej linii.

lortabak
źródło
Och, wow, dlaczego nigdy nie słyszałem (\\) wcześniej?
Flonk
4

Perl 6: 56 53 znaków; 58 55 bajtów

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

W przypadku każdego wiersza to przeczesuje go dla znaków spacji łańcucha o małych literach ( comb /\S/,.lc) i tworzy znak Baglub kolekcję każdego znaku i liczbę wystąpień. [∪]przejmuje sumę Bags we wszystkich wierszach, co daje maksymalną liczbę wystąpień postaci. .pick(*)jest tutaj hack-y, ale jest to najkrótszy sposób, aby uzyskać wszystkie postacie z Bagreplikowanej liczby razy.

EDYCJA: Aby sprawdzić, czy będzie krótsza, próbowałem przetłumaczyć Rubinową odpowiedź histokraty . Ma 63 znaki, ale nadal bardzo podoba mi się to podejście:

$!=lines».lc;->$c{print $c x max $!.map:{+m:g/$c/}} for"a".."z"
Mouq
źródło
3

Haskell, 183 162 159

Zakładając, że plik jest w 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

Jeśli plik.txt zawiera na przykład

abcde
abcdef
aaf

Skrypt wyświetli

aabcdef

Zasadniczo dołączam cały alfabet do każdej linii, więc podczas grupowania i sortowania jestem pewien, że otrzymam listę zawierającą 27 elementów. Następnie transponuję „tabelę częstotliwości”, tak aby każdy wiersz w tej tablicy składał się z częstotliwości jednej litery w każdej linii, np ["a","","aaa","aa","aaaa"]. Następnie wybieram maksimum każdej tablicy (która działa dokładnie tak, jak chcę z powodu działania Ord-instancji Ciągów) i upuszczam literę, którą dodałem na początku, pozbywam się spacji i wypisuję wynik.

Flonk
źródło
1
Zamiast tego po drop 1prostu użyjtail
Bergi,
@Bergi Haha derp, dzięki! Zmieniłem to w poście.
Flonk
3

C, 99 znaków

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

Występuje awaria, jeśli podano mniej niż jedną nową linię. Myślę, że można to łatwo naprawić.

zakk
źródło
Próbowałem, ale nie przyniosło to poprawnych wyników. gist.github.com/romaninsh/11159751
romaninsh
3

kdb (q / k): 59 znaków:

d:.Q.a! 26#0
.z.pi:{d|:.Q.a##:'=_y}.z.exit:{-1@,/.:[d]#'!:d}
  • generuje wstępnie posortowany słownik nasion z alfabetu .Qa
  • przetwarzaj każdy wiersz danych wejściowych, konwertuj na małe litery, pogrupuj w słownik, policz każdy element, pobieraj znaki alfabetyczne z wyniku (tj. spacje przycinania, znaki nowej linii itp. na tym etapie) i użyj max-przypisania do globalnego d, aby zachować sumę całkowitą.
  • Zdefiniuj moduł obsługi wyjścia, który jest przekazywany do pliku .z.pi w celu zapisania separatora, ale w przeciwnym razie nie jest tam używany. Weź z każdej klucz-wartość, aby wygenerować listę znaków, spłaszczyć, a na końcu wydrukować na standardowe wyjście.

-1 dodaje nowy wiersz, użycie 1 uratuje znak, ale nie wygeneruje określonego wyniku. Chciałbym móc pozbyć się płyty grzewczej .z.pi / .z.exit, która usunęłaby 14 znaków.

Edycja: unikaj używania inter / asc za pomocą słownika początkowego.

użytkownik20349
źródło
3

Perl, 46

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

Oto inne rozwiązanie Perla, czyta ze STDIN, wymaga -nprzełącznika (+1, by policzyć), wiąże się z wynikiem primo, ale działa bez skarg :-). Wykorzystuje fakt, że wynik bitowy orma dłuższą długość argumentu łańcucha.

użytkownik 2846289
źródło
1
próbowałem z moim testem i działało świetnie.
romaninsh
3

Dodaję własne rozwiązanie:

Bash - 72

Zakłada, że ​​dane wejściowe znajdują się w pliku „i”

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

Wyjaśnienie

Dla każdej możliwej litery odfiltrowuje ją tylko z pliku wejściowego, co daje coś takiego:

AAA
A
A

AAAA

A
AAAAAAAAAAAAAAAA

Następnie wynik jest sortowany i wybierana jest najdłuższa linia. echo -njest tam, aby usunąć nowe linie.

romaninsh
źródło
3

Bash, 171 159 158, 138 z wyjściem śmieci

Wymaga wprowadzania tylko małych liter. Zakłada, że ​​plik nazywa się _(podkreślenie). Maksymalnie 26 linii w pliku wejściowym z powodu irytujących nazw plików, które splittworzą (xaa, xab ... xaz, ???).

W bash, {a..z}wyjścia 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

Próbka wyjściowa

acdddeghillmmmoostvyy

Wyjaśnienie

touch {a..z}

Utwórz pliki, które będziemy czytać później, aby bash nie narzekał, że nie istnieją. Jeśli usuniesz ten wiersz, zaoszczędzisz 13 znaków, ale uzyskasz dużo niepotrzebnych danych wyjściowych.

split _ -1

Podziel plik wejściowy na sekcje, z których każda zawiera 1 linię. Pliki tworzone przez to polecenie mają nazwy xaa, xab, xac itd. Nie mam pojęcia, dlaczego.

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

Dla każdej litery $lprzeczytaj wszystkie wiersze zapisane w plikach xa$s.

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

Usuń -sprzełącznik, aby zapisać 1 znak i uzyskać dużo śmieci. Zapobiega grepnarzekaniu na nieistniejące pliki (wystąpi, chyba że masz 26 wierszy danych wejściowych). To przetwarza plik xa$s, usuwając wszystko oprócz wystąpień $li wysyłając dane wyjściowe do pliku b$l. Więc „kocham mamusiu” staje się „mmm” z nowymi wierszami po każdej literze, gdy $ljest m.

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

Jeśli liczba wierszy w właśnie utworzonym pliku jest większa lub równa (tj. Więcej liter, ponieważ jest jedna litera na linię), liczba wierszy w naszym dotychczasowym najwyższym wyniku (przechowywanym w $l) ...

then mv b$l $l

... zapisz nasz nowy rekord w pliku $l. Na końcu tej pętli, kiedy przejdziemy przez wszystkie linie, plik $lzapisze x linii, z których każda zawiera literę $l, gdzie x jest największą liczbą wystąpień tej litery w jednym wierszu.

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

Wypisz zawartość naszego pliku dla tej konkretnej litery, usuwając nowe wiersze. Jeśli nie chcesz usuwać nowych linii, zmień linię trna echo $l, oszczędzając 6 znaków.

done

źródło
Próbowałem z GNU bash, wersja 3.2.51 (jabłko), ale plik „-l1aa” w bieżącym folderze zawierającym dane wejściowe ..
romaninsh 21.04.2014
@romaninsh Możliwe, że masz inną wersję split(od coreutils). Obecnie używam GNU bash 4.3.8 i GNU coreutils 8.21 na Ubuntu 14.04 i działa dobrze (działało również na Ubuntu 13.10 przed aktualizacją). Jednak musiałem umieścić program i plik wejściowy w osobnym katalogu, aby działał poprawnie - podejrzewam, że było to tylko z powodu milionów niepotrzebnych plików w moim katalogu domowym .
@ romaninsh w rzeczywistości, jeśli spojrzysz na dokładne polecenie w skrypcie: split _ -l1i zauważysz, że dane wejściowe są zapisywane -l1aa, myślę, że twoja wersja split nie rozpoznaje -l1jako opcji i zamiast tego przyjmuje ją jako przedrostek dla danych wyjściowych . Spróbuj wstawić spację między -li 1, lub wstawić --lines=1, lub po prostu -1(wydaje się, że jest to przestarzała i bardziej golfowa składnia, którą teraz zaktualizuję posta).
3

C #, 172 bajty

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();
jzm
źródło
Sprytne ... sprytne ... Pomyślałem o zabawie z linq, ale wątpię, czy będzie tak krótki, jak te wykrzywione przedmieścia :)
Noctis
2

Python 2 - 129

Pomysł z @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)

Kilka innych sposobów na zrobienie tego samego w tej samej liczbie znaków:

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

Zakłada się, że plik jest zapisany jako f w dostępnym katalogu. Ten program można uruchomić bezpośrednio, bez konieczności wprowadzania dodatkowych danych.

isaacg
źródło
Dlaczego głosowanie w dół? Przepraszam, jeśli zrobiłem coś złego.
isaacg
2

Mathematica v10 - 110

Nie zostało jeszcze wydane, ale uważnie czytam nową dokumentację , myślę, że powinno to działać:

StringJoin@MapIndexed[#2~Table~{#1}&,Rest@Merge[Counts/@Characters@StringSplit[ToLowerCase@Input[],"\n"],Max]]
śmigać
źródło
2

Scala, 125 znaków

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

Najpierw czytam dane wejściowe, konwertując je na małe litery i dodając jedną pustą linię.

Następnie dla każdej litery od ado zpowtarzam tę literę maksymalną liczbę razy, gdy pojawia się ona w jednym z wierszy (dlatego potrzebuję pustego wiersza: maxnie można wywołać pustego wejścia). Następnie dołączam wyniki i drukuję na wydruku.

Aby odczytać z pliku, należy wymienić stdinz fromFile("FILENAME"), zwiększenie rozmiaru kodu do 132 znaków + plik długość nazwy.

Karol S.
źródło
2

JavaScript, 261 znaków

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

Usuń eval(...)i uruchom, aby uzyskać prawdziwy kod; to jest ( nieco ) skompresowane.

swielofunkcyjny jako tablica wierszy i jako ciąg wyjściowy, hzawiera histogram liter w wierszu i Hzawiera histogram z maksymalnymi wartościami do tej pory. Rozróżnia małe i duże litery i ignoruje tylko az i AZ (myślę, że ... Tablice JS są czasem dziwne).

Teraz poprawne :)

Tomsmeding
źródło
To tylko suma znaków, nie do końca to, o co pytano. Litery powinny być sumowane, aby być absolutnym minimum, aby utworzyć dowolne zdanie na wejściu, a nie wszystkie. Jednak podoba mi się twoje podejście do zapobiegania sortowaniu wyników.
Matt
@Matt oh właśnie tak ... Naprawię to później. Naprawdę nie mam teraz czasu.
Tomsmeding
1
Zastanawiałem się, co się działo, @dopóki nie dotarłem do końca. Podoba mi się :)
Mat.
2

JavaScript ( ES5 ) 141 bajtów

Zakładając, że zmienna sjest łańcuchem wejściowym bez wymagań sprawdzania wielkości liter i danych wyjściowych tablicy:

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()
nderscore
źródło
Przetestowałem twoje rozwiązanie i szukałem wyjścia „o”, ale nie wydaje się, aby zostało poprawnie posortowane. (patrz gist.github.com/romaninsh/11159751 )
romaninsh
@romaninsh dane wyjściowe, które widzę w twojej treści, wyglądają właściwie posortowane
nderscore 21.04.2014
Tak, to jest referencyjne / prawidłowe wyjście. Kiedy wypróbowałem twój kod, otrzymałem to: gist.github.com/romaninsh/11161018
romaninsh
Przepraszamy za niepoprawne wykonanie twojego przykładu.
romaninsh
@romaninsh ah, miałem zamiar uruchomić go w konsoli przeglądarki. Oto wersja sformatowana, która działa na węźle: gist.github.com/nderscore/96aa888c77d275c26c15
nderscore
2

PowerShell - 141

Czyta tekst z pliku o nazwie „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""
Rynant
źródło
2

Groovy, 113/127 102/116 znaków

Zakładając, że plik jest w jednym przypadku (102 znaki):

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

Zakładając, że plik jest wielowymiarowy (116 znaków):

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

Gruntownie:

  • t=new File('f').text Aby uzyskać tekst pliku.
  • t.findAll('[A-Z]').unique().sort().each{c-> Aby uzyskać unikalne postacie, posortuj je i iteruj.
  • print c*t.readLines()*.count(c).max() Uzyskaj maksymalną liczbę wystąpień w jednym wierszu i wydrukuj znak wiele razy.
dbramwell
źródło
2

Bash (głównie 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'

Tekst musi zostać przesłany do awk (lub określony jako plik).

Przykładowe dane wejściowe

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

Przykładowy wynik

ACDDDEGHILLMMMOOSTVYY

PHP (prawdopodobnie mogłoby być lepiej) - 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;

Zakłada, że ​​ciąg jest zawarty w zmiennej $ s

Przykładowe dane wejściowe

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

Przykładowy wynik

ACDDDEGHILLMMMOOSTVYY
Tyzoid
źródło
2

Zdaję sobie sprawę, że to prawdopodobnie nie jest najskuteczniejsza odpowiedź, ale i tak chciałem spróbować rozwiązać problem. Oto moja odmiana 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:)];
}    

Następnie możesz wywołać go dla dowolnego ciągu:

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

Myślałem o aplikacjach z większą ilością tekstu i wolałbym nie liczyć mojej tablicy. W tym celu dodałem do metody, aby uzyskać to:

- (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;
}

Działaj jak:

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

Da tobie:

{a = 2; b = 0; c = 1; d = 4; e = 5; f = 0; g = 1; h = 1; i = 3; j = 0; k = 0; l = 6; m = 6; n = 0; o = 8; p = 0; q = 0; r = 0; s = 1; t = 1; u = 0; v = 4; w = 0; x = 0; y = 3; z = 0; }

Myślę, że jest to lepsze, gdybym miał bardzo dużą ilość tekstu i potrzebowałem tylko wiedzieć, ile listów potrzebuję.

Logan
źródło
2

K, 34

{`$a@<a:,/(.:a)#'!:a:|/#:''=:'0:x}
tartin
źródło
2

Python 2, 154 bajty

import collections
c = collections.Counter()
for line in open("input.txt"):
    c |= collections.Counter(line.upper())
print "".join(sorted(c.elements()))
Frankfurt
źródło
Witamy w PCG! Ta strona obsługuje składnię Markdown, której można użyć do sformatowania kodu, aby wyglądał ładnie: wystarczy wciąć każdy wiersz 4 spacji.
algorytm
Musisz dodać znaki niezbędne do importowania kolekcji.
isaacg
1
nie odpowiada na pytanie, ponieważ potrzebujesz minimalnej ilości liter, aby napisać każde zdanie osobno. W swoim kodzie podajesz liczbę liter potrzebną do napisania wszystkich zdań jednocześnie.
njzk2
Brakuje znaku sna końcu importinstrukcji, a withblok nie ma wcięcia. A ponieważ jest to gra w golfa, bardzo przydatne byłoby usunięcie niepotrzebnych białych znaków w miarę możliwości.
Fraxtil
ponieważ jest to kod golfowy, usuń instrukcję with (po prostu zapętlić wywołanie, aby otworzyć) i nie sądzę, że elementy wymagają sortowania.
RemcoGerlich,
2

C, 298 bajtów

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);
}
}
}

Tablica D przechowuje sumę liter dla każdej linii, a następnie maksymalna liczba jest kopiowana do C.

Uwaga: Wstawiłem swoją odpowiedź wczoraj, ale nie ma jej na liście, może przez pomyłkę nacisnąłem delete zamiast edytować?

Bacchusbeale
źródło
To tylko 271 bajtów. Masz również wiele obcych linii. Można także można pominąć intz int main()i int j,n;.
nyuszika7h
Twoja poprzednia odpowiedź wciąż tam jest.
nyuszika7h
2

PHP, 143 bajty

Zakładając, że dane wejściowe są przekazywane w zmiennej $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));}

Wyjaśnienie

Dla każdej możliwej litery odwzorowuję tablicę zawierającą listę ciągów znaków za pomocą funkcji zdefiniowanej przez użytkownika, która zastępuje każdy wiersz liczbą użytych znaków. W przypadku litery „d” wiersz „Mamusia kocha tatusia” zostanie zamapowany na 3.

Potem tyle razy znajduję maksymalną wartość w tablicy i liście wyjściowej. Oto wersja wieloliniowa:

$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));
}
romaninsh
źródło
1

Python (209, z dołączoną próbką, 136 bez.):

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

Po południu opublikuję próbkę PYG.

.ıʇǝɥʇuʎs
źródło
Nie miałem pojęcia, że ​​ciągi Pythona mają metodę zliczania ... Nie sądzę, żeby zmiana mojej odpowiedzi na pytanie była uzasadniona? : p
Tal.
@tal Oni nie. Jest to metoda z listy, jeśli przyjrzysz się bliżej
ɐɔıʇǝɥʇu
1
Och, rozumiem ... ale w nieoczekiwanym zrządzeniu okazuje się, że struny najwyraźniej mają również tę metodę (w każdym razie w 3.x)
Tal