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 e
litery, ma tylko 2 o
litery. 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:
v
Wyjście powinno zawierać literę ;)M
naW
, czy na bokiN
naZ
? ;-)I
s._\¯
Odpowiedzi:
GolfScript, 28/34 znaków
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: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
NUL
s), 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
NUL
jednakowo 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:a
przypisuje wynikową tablicę do zmienneja
. 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ętlaa{.[2$]--}%
iteruje się po łańcuchach w tablicya
, 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.źródło
n/:a{|}*{{{=}+,}+a%$-1=}%$
.J - 37 char
Odczytuje ze standardowego wyjścia na konsolę.
1!:1]3
jest wezwanie do stdin.tolower;._2
wykonuje 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 spacjedlb
.źródło
JavaScript (ECMAScript 6) -
148139135 znakówWersja 2:
Zaktualizowano w celu użycia zrozumienia tablic:
Wersja 1:
Zakłada, że:
s
;Z komentarzami:
Jeśli chcesz:
.join('')
na końcu;s
zmienną naprompt()
; lubf
a następnie dodajf=s=>
na początek.Bieganie:
Daje wynik:
źródło
/\s*/
do/ */
i usuwanie nawiasów wokółj=0
...
zamiastapply
?...
) to taki, którego wcześniej nie spotkałem.[].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 bajtów
Liczenie shebang jako 1. To jest luźne tłumaczenie poniższego rozwiązania Ruby.
Rubinowy 1,8 - 72 bajtów
Dane wejściowe są pobierane z
stdin
.Przykładowe użycie:
źródło
/i
afor
.Python -
2062041991771451291179488 znakówNie 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ć.źródło
f
nazwę 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)]))
Ruby 1.9+, 51 (lub 58 lub 60)
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
.źródło
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.
Nie golfowany:
Rozwiązanie:
źródło
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ótszycat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")
zakładającf
to nazwaHaskell,
109108Program 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.
źródło
Perl 6:
5653 znaków;5855 bajtówW przypadku każdego wiersza to przeczesuje go dla znaków spacji łańcucha o małych literach (
comb /\S/,.lc
) i tworzy znakBag
lub kolekcję każdego znaku i liczbę wystąpień.[∪]
przejmuje sumęBag
s 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 zBag
replikowanej 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:
źródło
Haskell,
183 162159Zakładając, że plik jest w
file.txt
!Jeśli plik.txt zawiera na przykład
Skrypt wyświetli
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łaniaOrd
-instancji Ciągów) i upuszczam literę, którą dodałem na początku, pozbywam się spacji i wypisuję wynik.źródło
drop 1
prostu użyjtail
C, 99 znaków
Występuje awaria, jeśli podano mniej niż jedną nową linię. Myślę, że można to łatwo naprawić.
źródło
kdb (q / k): 59 znaków:
-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.
źródło
Perl, 46
Oto inne rozwiązanie Perla, czyta ze STDIN, wymaga
-n
przełącznika (+1, by policzyć), wiąże się z wynikiem primo, ale działa bez skarg :-). Wykorzystuje fakt, że wynik bitowyor
ma dłuższą długość argumentu łańcucha.źródło
Dodaję własne rozwiązanie:
Bash - 72
Zakłada, że dane wejściowe znajdują się w pliku „i”
Wyjaśnienie
Dla każdej możliwej litery odfiltrowuje ją tylko z pliku wejściowego, co daje coś takiego:
Następnie wynik jest sortowany i wybierana jest najdłuższa linia.
echo -n
jest tam, aby usunąć nowe linie.źródło
Bash,
171159158, 138 z wyjściem śmieciWymaga 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óresplit
tworzą (xaa, xab ... xaz, ???).W
bash
,{a..z}
wyjściaa b c d e f ...
.Próbka wyjściowa
Wyjaśnienie
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.
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.
Dla każdej litery
$l
przeczytaj wszystkie wiersze zapisane w plikachxa$s
.Usuń
-s
przełącznik, aby zapisać 1 znak i uzyskać dużo śmieci. Zapobiegagrep
narzekaniu na nieistniejące pliki (wystąpi, chyba że masz 26 wierszy danych wejściowych). To przetwarza plikxa$s
, usuwając wszystko oprócz wystąpień$l
i wysyłając dane wyjściowe do plikub$l
. Więc „kocham mamusiu” staje się „mmm” z nowymi wierszami po każdej literze, gdy$l
jest m.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
) ...... zapisz nasz nowy rekord w pliku
$l
. Na końcu tej pętli, kiedy przejdziemy przez wszystkie linie, plik$l
zapisze x linii, z których każda zawiera literę$l
, gdzie x jest największą liczbą wystąpień tej litery w jednym wierszu.Wypisz zawartość naszego pliku dla tej konkretnej litery, usuwając nowe wiersze. Jeśli nie chcesz usuwać nowych linii, zmień linię
tr
naecho $l
, oszczędzając 6 znaków.źródło
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 .split _ -l1
i zauważysz, że dane wejściowe są zapisywane-l1aa
, myślę, że twoja wersjasplit
nie rozpoznaje-l1
jako opcji i zamiast tego przyjmuje ją jako przedrostek dla danych wyjściowych . Spróbuj wstawić spację między-l
i1
, 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).C #, 172 bajty
źródło
Python 2 - 129
Pomysł z @Tal
Kilka innych sposobów na zrobienie tego samego w tej samej liczbie znaków:
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.
źródło
Mathematica v10 - 110
Nie zostało jeszcze wydane, ale uważnie czytam nową dokumentację , myślę, że powinno to działać:
źródło
Scala, 125 znaków
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
a
doz
powtarzam tę literę maksymalną liczbę razy, gdy pojawia się ona w jednym z wierszy (dlatego potrzebuję pustego wiersza:max
nie można wywołać pustego wejścia). Następnie dołączam wyniki i drukuję na wydruku.Aby odczytać z pliku, należy wymienić
stdin
zfromFile("FILENAME")
, zwiększenie rozmiaru kodu do 132 znaków + plik długość nazwy.źródło
JavaScript, 261 znaków
Usuń
eval(...)
i uruchom, aby uzyskać prawdziwy kod; to jest ( nieco ) skompresowane.s
wielofunkcyjny jako tablica wierszy i jako ciąg wyjściowy,h
zawiera histogram liter w wierszu iH
zawiera 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 :)
źródło
@
dopóki nie dotarłem do końca. Podoba mi się :)JavaScript ( ES5 ) 141 bajtów
Zakładając, że zmienna
s
jest łańcuchem wejściowym bez wymagań sprawdzania wielkości liter i danych wyjściowych tablicy:źródło
PowerShell - 141
Czyta tekst z pliku o nazwie „a”.
źródło
Groovy,
113/127102/116 znakówZakładając, że plik jest w jednym przypadku (102 znaki):
Zakładając, że plik jest wielowymiarowy (116 znaków):
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.źródło
Bash (głównie awk) -
172163157Tekst musi zostać przesłany do awk (lub określony jako plik).
Przykładowe dane wejściowe
Przykładowy wynik
PHP (prawdopodobnie mogłoby być lepiej) -
174210Zakłada, że ciąg jest zawarty w zmiennej $ s
Przykładowe dane wejściowe
Przykładowy wynik
źródło
Zdaję sobie sprawę, że to prawdopodobnie nie jest najskuteczniejsza odpowiedź, ale i tak chciałem spróbować rozwiązać problem. Oto moja odmiana ObjC:
Następnie możesz wywołać go dla dowolnego ciągu:
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:
Działaj jak:
Da tobie:
Myślę, że jest to lepsze, gdybym miał bardzo dużą ilość tekstu i potrzebowałem tylko wiedzieć, ile listów potrzebuję.
źródło
K, 34
źródło
Python 2, 154 bajty
źródło
s
na końcuimport
instrukcji, awith
blok 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.C, 298 bajtów
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ć?
źródło
int
zint main()
iint j,n;
.PHP, 143 bajty
Zakładając, że dane wejściowe są przekazywane w zmiennej
$s
: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:
źródło
Python (209, z dołączoną próbką, 136 bez.):
Po południu opublikuję próbkę PYG.
źródło