Das Alphabet meiner Tochter


65

Neulich haben wir mit meiner Tochter Sätze mit einem Kühlschrankmagneten geschrieben. Während wir einige ( I love cat) erstellen konnten , hatten wir nicht genügend Buchstaben, um die anderen ( I love you too) zu erstellen, da die Anzahl der Buchstaben nicht ausreicht o(4).

Ich fand dann heraus, dass ein Satz, der 3 eBuchstaben enthielt, nur 2 oBuchstaben hatte. Wahrscheinlich inspiriert von http://en.wikipedia.org/wiki/Letter_frequency würde dies immer noch nicht die tatsächliche Situation "auf dem Kühlschrank" widerspiegeln.

Problem

In Anbetracht der Textdatei, in der jede Zeile einen "Beispielsatz" enthält, den man auf den Kühlschrank schreiben möchte, schlagen Sie ein Alphabet mit einer Mindestanzahl von Buchstaben vor, das jedoch immer noch ausreicht, um jeden Satz einzeln zu schreiben.

Hinweis: Groß- und Kleinschreibung ignorieren, alle Magnetbuchstaben sind trotzdem Großbuchstaben.

Eingang

Die Datei enthält durch Zeilenumbrüche getrennte Sätze:

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

Ausgabe

Geben Sie eine sortierte Liste von Buchstaben an, wobei jeder Buchstabe nur so oft vorkommt, dass er ausreicht, um einen Satz zu schreiben:

acdddeghillmmmoostvyy

(danke isaacg!)

Gewinner

Kürzeste Implementierung (Code)

AKTUALISIERT: Testen

Ich habe einen extra Test erstellt und hier mit verschiedenen Antworten versucht:

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


2
vDie Ausgabe sollte einen Brief enthalten ;)
Antonio Ragagnin

40
Dürfen / müssen wir ein umgedrehtes Mfür ein Woder ein seitliches Nfür ein ersetzen Z? ;-)
Ilmari Karonen

4
Grundsätzlich können Sie jeden Buchstaben mit Is konstruieren .
Swish

7
Im Ernst, wenn Sie "Fälle ignorieren" sagen, meinen Sie damit, dass wir davon ausgehen können , dass die Eingabe bereits alle im selben Fall ist, oder dass wir alle in den selben Fall konvertieren müssen? Darf die Ausgabe auch führende Leerzeichen enthalten?
Ilmari Karonen

3
@Doorknob:_\¯
Ilmari Karonen

Antworten:


18

GolfScript, 28/34 Zeichen

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

Das obige 28-stellige Programm geht davon aus, dass alle eingegebenen Buchstaben gleich sind. Wenn dies nicht unbedingt der Fall sein muss, können wir sie durch Voranstellen {95&}%des Codes in Großbuchstaben umwandeln. Dies ergibt insgesamt 34 Zeichen:

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

Anmerkungen:

  • Für einen korrekten Betrieb muss die Eingabe mindestens eine neue Zeile enthalten. Dies gilt für normale Textdateien mit Zeilenumbrüchen am Ende jeder Zeile. Dies gilt jedoch möglicherweise nicht, wenn die Eingabe nur aus einer Zeile ohne abschließende Zeilenumbrüche besteht. Dies könnte auf Kosten von zwei zusätzlichen Zeichen durch Voranstellen n+des Codes behoben werden.

  • Die in der 34-stelligen Version verwendeten Großbuchstaben sind sehr grob - sie ordnen Kleinbuchstaben in ASCII-Zeichen den entsprechenden Großbuchstaben (und Leerzeichen in NULs) zu, führen jedoch zu einem völligen Durcheinander von Zahlen und den meisten Interpunktionszeichen. Ich gehe davon aus, dass die Eingabe keine solchen Zeichen enthält.

  • Die 28-stellige Version behandelt alle eingegebenen Zeichen (mit Ausnahme von Zeilenumbrüchen und NULs) gleich. Insbesondere wenn die Eingabe Leerzeichen enthält, werden einige auch in der Ausgabe angezeigt. Bequemerweise werden sie vor allen anderen druckbaren ASCII-Zeichen sortiert. Die 34-stellige Version ignoriert jedoch Leerzeichen (da sich herausstellt, dass ich das tun kann, ohne dass es mich zusätzliche Zeichen kostet).

Erläuterung:

  • Das optionale {95&}%Präfix übersteigt die Eingabe, indem das sechste Bit des ASCII-Codes jedes Eingangsbytes ( ) auf Null gesetzt wird . Dadurch werden ASCII-Kleinbuchstaben in Großbuchstaben, Leerzeichen in Nullbytes und Zeilenumbrüche unverändert übernommen.95 = 64 + 31 = 10111112

  • n/Teilt die Eingabe in Zeilenumbrüche und :aweist das resultierende Array der Variablen zu a. {|}*Berechnet dann die Mengenvereinigung der Zeichenfolgen im Array, die (unter der Annahme, dass das Array mindestens zwei Elemente enthält) eine Zeichenfolge ergibt, die alle eindeutigen Zeichen (ohne Zeilenumbruch) in der Eingabe enthält.

  • Die folgende { }%Schleife durchläuft dann jedes dieser eindeutigen Zeichen. Innerhalb des Schleifenkörpers durchläuft die innere Schleife a{.[2$]--}%die Zeichenfolgen im Array aund entfernt aus jeder Zeichenfolge alle Zeichen, die nicht mit den Zeichen übereinstimmen, über die die äußere Schleife iteriert.

    Die innere Schleife belässt den ASCII-Code des aktuellen Zeichens auf dem Stapel unterhalb des gefilterten Arrays. Wir machen uns das zunutze, indem wir das gefilterte Array so oft wiederholen, wie es durch den ASCII-Code ( *) angegeben ist, bevor $wir es sortieren ( ) und das letzte Element nehmen ( -1=). Tatsächlich ergibt dies die längste Zeichenfolge im gefilterten Array (da sie alle aus Wiederholungen desselben Zeichens bestehen, sortiert die lexikografische Sortierung sie nur nach Länge), es sei denn, das Zeichen hat den ASCII-Code Null. In diesem Fall ergibt sie nichts.

  • Schließlich $sortiert die am Ende nur die Ausgabe alphabetisch.


3
Tolle. TODO: GolfScript lernen!
DLosc

1
Sie können es sogar auf 26 reduzieren: n/:a{|}*{{{=}+,}+a%$-1=}%$.
Howard

13

J - 37 Zeichen

Liest von stdin, gibt auf Konsole aus.

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

1!:1]3ist der Ruf nach stdin. tolower;._2Führt eine doppelte Aufgabe aus, indem die Zeilen aufgeteilt und gleichzeitig in Kleinbuchstaben umgewandelt werden. Dann zählen wir mit, wie oft ein Zeichen in jeder Zeile vorkommt +/"2=/&a., und nehmen mit das punktweise Maximum über alle Zeilen >./.

Schließlich ziehen wir so viele Zeichen aus dem Alphabet mit #&a.. Dies schließt Leerzeichen ein, die alle aufgrund ihres niedrigen ASCII-Werts vorne zu finden sind. Deshalb löschen wir nur führende Leerzeichen mit dlb.


12

JavaScript (ECMAScript 6) - 148 139 135 Zeichen

Version 2:

Aktualisiert, um das Array-Verständnis zu verwenden:

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

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

Angenommen, dass:

  • Die Eingabezeichenfolge befindet sich in der Variablen s.
  • Wir können die Groß- und Kleinschreibung der Eingabe ignorieren (wie in der Frage angegeben).
  • Die Ausgabe ist ein Array von Zeichen (was ungefähr so ​​nahe kommt, wie JavaScript die Anforderung des OP an eine Liste von Zeichen erfüllen kann). und
  • Die Ausgabe soll auf der Konsole angezeigt werden.

Mit Kommentaren:

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.

Wenn du möchtest:

  • Geben Sie es als Zeichenfolge zurück und fügen Sie es .join('')am Ende hinzu.
  • Nehmen Sie die Eingaben eines Benutzers entgegen und ersetzen Sie die sVariable durch prompt(); oder
  • Schreiben Sie es als Funktion fund fügen Sie f=s=>es am Anfang hinzu.

Laufen:

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

Gibt die Ausgabe aus:

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

1
Nett! Sie können 3 Bytes einsparen /\s*/, / */indem Sie die Parens umj=0
nderscore

1
konntest du nicht ...anstelle von verwenden apply?
Ven

Dank euch beiden - das spart 9 Zeichen - ist der spread ( ...) -Operator einer, dem ich noch nie begegnet bin.
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``;
14 m²,

11

Perl - 46 Bytes

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

Zählen Sie den Shebang als 1. Dies ist eine lose Übersetzung der Ruby-Lösung unten.


Ruby 1,8 - 72 Bytes

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

Die Eingabe wird von übernommen stdin.

Beispielnutzung:

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

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

Die Ausgabe muss sortiert werden.
Matt

@Matt jetzt behoben.
Primo

Nett. Wenn Ihr Perl allerdings vage neu ist, möchten Sie ein Leerzeichen zwischen /iund for.
Tobyink

8

Python - 206 204 199 177 145 129 117 94 88 Zeichen

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

Ich war mir nicht sicher, wie ich den Dateinamen erhalten sollte, daher geht der Code im Moment davon aus, dass er in einer Variablen namens enthalten ist f. Bitte lassen Sie mich wissen, wenn ich das ändern muss.


8
im geiste von unix konnte man von stdin lesen.
Romaninsh

5
Machen Sie den Dateinamen immer ein Zeichen lang ...

3
@Tal Ich bin auch neu, aber wenn es Zeichen speichert, warum nicht?

1
Wenn Sie fden Dateinamen für die Eingabe übernehmen und Großbuchstaben verwenden (alle Magnetbuchstaben sind ohnehin Großbuchstaben), können Sie 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 gut, wenn wir dies in der Konsole ausführen, würde es theoretisch nur das Ergebnis von selbst drucken ...
Tal

6

Ruby 1.9+, 51 (oder 58 oder 60)

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

Nimmt an, dass alles in Kleinbuchstaben geschrieben ist. .upcaseGroß- und Kleinschreibung kostet 7 Zeichen via , während Groß- und Kleinschreibung 9 Zeichen via kostet .downcase.


4

R (156, inkl. Datei lesen)

Mit table konstruiere ich für jeden Satz die Buchstabenhäufigkeitstabelle. Am Ende nehme ich für jeden Buchstaben den Maximalwert.

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

Lösung:

acdddeghillmmmoooooostuvyy

@lambruscoAcido Sie könnten die drei ersten Zeilen (des ungolfed Codes), die Sie geben würden, vektorisieren 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=""), aber es ist nur 3 Zeichen kürzer
jkd

Ein anderer Ansatz mit nur 112 Zeichen würde cat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")annehmen , dass fder Dateiname
jkd

4

Haskell, 109 108

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

Das Programm liest von stdin und schreibt nach sdtout.

Es ist ganz einfach: Es zerlegt die Zeichenfolge in eine Liste von Zeilen und erstellt sie neu, indem es in der Liste iteriert und die neuen Buchstaben in jeder Zeile hinzufügt.


Oh wow, warum habe ich noch nie von (\\) gehört?
Flonk


4

Perl 6: 56 53 Zeichen; 58 55 Bytes

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

Für jede Zeile wird diese für die Nicht-Leerzeichen der Zeichenfolge in Kleinbuchstaben ( comb /\S/,.lc) durchkämmt , und es wird ein Bagoder eine Auflistung jedes Zeichens erstellt und wie oft es auftritt. [∪]Führt die Vereinigung der Bags über alle Zeilen aus, wodurch die maximale Häufigkeit des Auftretens des Zeichens ermittelt wird. .pick(*)ist hack-y hier, aber es ist der kürzeste Weg, um alle Zeichen aus dem Bagreplizierten zu bekommen, wie oft es aufgetreten ist.

EDIT: Um zu sehen, ob es kürzer wäre, habe ich versucht, die Ruby-Antwort des Histokraten zu übersetzen . Es sind 63 Zeichen, aber mir gefällt der Ansatz immer noch sehr gut:

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

3

Haskell, 183 162 159

Vorausgesetzt, die Datei ist in 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

Wenn file.txt zum Beispiel enthält

abcde
abcdef
aaf

Das Skript wird ausgegeben

aabcdef

Grundsätzlich hänge ich das gesamte Alphabet an jede Zeile an, sodass ich beim Gruppieren und Sortieren sicher eine Liste mit 27 Elementen erhalte. Als nächstes transponiere ich die "Häufigkeitstabelle", so dass jede Zeile in diesem Array aus den Häufigkeiten eines einzelnen Buchstabens in jeder Zeile besteht, z ["a","","aaa","aa","aaaa"]. Ich wähle dann das Maximum jedes Arrays (was genau so funktioniert, wie ich es möchte, weil die Ord-Instanz von Strings funktioniert), lasse den Buchstaben fallen, den ich am Anfang angehängt habe, entferne die Leerzeichen und gebe das Ergebnis aus.


1
drop 1Verwenden tail
Sie

@Bergi Haha derp, danke! Ich habe es in der Post geändert.
Flonk

3

C 99 Zeichen

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

Es stürzt ab, wenn weniger als eine neue Zeile angegeben wird. Ich denke, es könnte ganz einfach behoben werden.


Ich habe es versucht, aber es hat nicht zu korrekten Ergebnissen geführt. gist.github.com/romaninsh/11159751
romaninsh

3

kdb (q / k): 59 Zeichen:

d:.Q.a! 26#0
.z.pi:{d|:.Q.a##:'=_y}.z.exit:{-1@,/.:[d]#'!:d}
  • Generieren Sie ein vorsortiertes Startwörterbuch aus dem Alphabet .Qa
  • Verarbeiten Sie jede Eingabezeile, konvertieren Sie sie in Kleinbuchstaben, gruppieren Sie sie in ein Wörterbuch, zählen Sie jedes Element, nehmen Sie alphabetische Zeichen aus dem Ergebnis (dh Leerzeichen, Zeilenumbrüche usw. in diesem Stadium) und verwenden Sie max-assign to global d, um eine laufende Summe zu erhalten.
  • Definieren Sie einen Exit-Handler, der an .z.pi übergeben wird, um ein Trennzeichen zu speichern, das dort jedoch ansonsten nicht verwendet wird. Nehmen Sie aus jedem Schlüsselwert eine Liste von Zeichen, reduzieren Sie sie und drucken Sie sie schließlich auf stdout.

-1 fügt eine neue Zeile hinzu, mit 1 wird ein Zeichen gespeichert, die angegebene Ausgabe wird jedoch nicht generiert. Ich wünschte, ich könnte die .z.pi / .z.exit-Kesselplatte entfernen, die 14 Zeichen entfernt.

Bearbeiten: Vermeiden Sie die Verwendung von inter / asc, indem Sie das Startwörterbuch verwenden.


3

Perl, 46

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

Hier ist eine andere Perl-Lösung, die von STDIN gelesen wird, einen -nSchalter (+1 zum Zählen) erfordert , mit Primos Punktzahl in Verbindung steht, aber ohne Beschwerden läuft :-). Dabei wird die Tatsache ausgenutzt, dass ordas Ergebnis von bitwise eine längere Länge für Zeichenfolgenargumente hat.


1
habe es mit meinem test versucht und es hat super geklappt.
Romaninsh

3

Ich füge meine eigene Lösung hinzu:

Bash - 72

Angenommen, die Eingabe befindet sich in der Datei "i".

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

Erläuterung

Filtert es für jeden möglichen Buchstaben nur aus der Eingabedatei heraus, was ungefähr so ​​aussieht:

AAA
A
A

AAAA

A
AAAAAAAAAAAAAAAA

Das Ergebnis wird sortiert und die längste Zeile ausgewählt. echo -nist da, um Zeilenumbrüche zu entfernen.


3

Bash, 171 159 158, 138 mit Junk-Ausgabe

Benötigt nur Kleinbuchstaben. Angenommen, die Datei heißt _(Unterstrich). Maximal 26 Zeilen in der Eingabedatei aufgrund der lästigen Dateinamen split(xaa, xab ... xaz, ???).

In bash, {a..z}Ausgänge 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

Beispielausgabe

acdddeghillmmmoostvyy

Erläuterung

touch {a..z}

Erstellen Sie Dateien, die wir später lesen werden, damit sich Bash nicht beschwert, dass sie nicht existieren. Wenn Sie diese Zeile entfernen, sparen Sie 13 Zeichen, erhalten aber viel Junk-Ausgabe.

split _ -1

Teilen Sie die Eingabedatei in Abschnitte auf, in denen jeweils 1 Zeile gespeichert ist. Die Dateien, die dieser Befehl erstellt, heißen xaa, xab, xac usw. Ich habe keine Ahnung, warum.

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

$lLesen Sie für jeden Buchstaben alle in Dateien gespeicherten Zeilen durch xa$s.

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

Entfernen Sie den -sSchalter, um 1 Zeichen zu sparen und viel Junk-Output zu erhalten. Es verhindert, dass Sie grepsich über nicht vorhandene Dateien beschweren (dies geschieht, wenn Sie nicht über 26 Eingabezeilen verfügen). Dadurch wird die Datei verarbeitet xa$s, alles andere als Vorkommen entfernt $lund die Ausgabe an die Datei gesendet b$l. Also wird "i love mommy" zu "mmm" mit neuen Zeilen nach jedem Buchstaben, wenn $lm ist.

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

Wenn die Anzahl der Zeilen in der soeben erstellten Datei größer oder gleich der Anzahl der Zeilen in unserem höchsten Ergebnis ist (gespeichert in $l) ...

then mv b$l $l

... speichern Sie unseren neuen Datensatz in der Datei $l. Am Ende dieser Schleife, wenn wir alle Zeilen durchlaufen haben, werden in der Datei $lx Zeilen gespeichert, die jeweils den Buchstaben enthalten $l, wobei x die höchste Anzahl von Vorkommen dieses Buchstabens in einer einzelnen Zeile ist.

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

Geben Sie den Inhalt unserer Datei für diesen bestimmten Buchstaben aus und entfernen Sie dabei neue Zeilen. Wenn Sie die neuen Zeilen nicht entfernen möchten, ändern Sie die Zeile mit trauf echo $l, und sparen Sie 6 Zeichen.

done

Versucht mit GNU Bash, Version 3.2.51 (Apfel), aber Datei '-l1aa' in einem aktuellen Ordner mit Eingabedaten ..
Romaninsh

@romaninsh Möglicherweise haben Sie eine andere Version von split(als coreutils). Ich verwende derzeit GNU bash 4.3.8 und GNU coreutils 8.21 unter Ubuntu 14.04 und es funktioniert einwandfrei (es hat auch unter Ubuntu 13.10 funktioniert, bevor ich ein Upgrade durchgeführt habe). Allerdings musste ich das Programm und die Eingabedatei in einem separaten Verzeichnis ablegen, damit es ordnungsgemäß funktioniert. Ich vermute, dass dies nur auf die Millionen von Junk-Dateien in meinem privaten Ordner zurückzuführen war .

@romaninsh Wenn Sie sich den genauen Befehl im Skript ansehen split _ -l1und feststellen, dass Ihre Eingabe in gespeichert -l1aawird, wird Ihre Version von meiner Meinung nach split nicht -l1als Option erkannt , sondern als Präfix für die Ausgabe . Versuchen Sie, ein Leerzeichen zwischen -lund 1, oder Putting --lines=1oder einfach nur -1(dies scheint eine veraltete und mehr Golf-Syntax zu sein, mit der ich den Beitrag jetzt aktualisieren werde).

3

C # 172 Bytes

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

Clever ... clever ... Ich dachte darüber nach, mit Linq zu spielen, aber bezweifle, dass es so kurz sein wird wie diese verdrehten Foreachs :)
Noctis

2

Python 2 - 129

Idee von @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)

Ein paar weitere Möglichkeiten, um dasselbe mit der gleichen Anzahl von Zeichen zu tun:

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

Dies setzt voraus, dass die Datei als f in einem Verzeichnis gespeichert ist, auf das zugegriffen werden kann. Dieses Programm kann direkt ausgeführt werden, ohne dass zusätzliche Eingaben erforderlich sind.


Warum die Abwahlen? Tut mir leid, wenn ich etwas falsch gemacht habe.
Isaacg

2

Mathematica v10 - 110

Es ist noch nicht fertig, aber ich lese die neue Dokumentation sehr sorgfältig durch. Ich denke, das sollte funktionieren:

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

2

Scala, 125 Zeichen

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

Zuerst las ich die Eingabe, wandelte sie in Kleinbuchstaben um und fügte eine leere Zeile hinzu.

Dann wiederhole ich diesen Buchstaben für jeden Buchstaben von abis zmaximal so oft, wie er in einer der Zeilen vorkommt (deshalb brauche ich die leere Zeile: maxkann bei einer leeren Eingabe nicht aufgerufen werden). Dann verbinde ich einfach die Ergebnisse und drucke auf die Ausgabe.

Zum Lesen aus einer Datei, ersetzen stdinmit fromFile("FILENAME"), die Erhöhung der Größe des Codes zu 132 Zeichen + Dateiname Länge.


2

Javascript, 261 Zeichen

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

Entfernen Sie den Befehl eval(...)und führen Sie ihn aus, um den tatsächlichen Code zu erhalten. das ist ( etwas ) komprimiert.

sMultifunktional als Zeilenarray und als ausgegebener String, henthält das Histogramm der Buchstaben pro Zeile und Henthält das Histogramm mit den bisherigen Maximalwerten. Die Groß- und Kleinschreibung wird nicht beachtet und alles außer az und AZ wird ignoriert (ich denke ... JS-Arrays sind manchmal komisch).

Jetzt richtig :)


Dies summiert sich nur auf die Zeichen, nicht ganz das, was die Frage gestellt hat. Die Buchstaben sollten als absolutes Minimum addiert werden, um einen einzelnen Satz in der Eingabe zu bilden, nicht alle. Ich mag Ihren Ansatz, um zu verhindern, dass die Ausgabe sortiert werden muss.
Matt

@Matt oh das stimmt ... Ich werde es später beheben. Ich habe gerade keine Zeit.
Tomsmeding

1
Ich fragte mich, was mit dem los war, @bis ich zum Ende kam. Ich mag es :)
Matt

2

JavaScript ( ES5 ) 141 Byte

Angenommen, die Variable sist die Eingabezeichenfolge ohne Anforderungen für die Fallprüfung und Array-Ausgabe:

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

Ich habe Ihre Lösung getestet und habe in "o" nach einer Ausgabe gesucht, aber sie scheint nicht richtig sortiert zu sein. (siehe gist.github.com/romaninsh/11159751 )
romaninsh

@ Romaninsh die Ausgabe, die ich in Ihrem Gist sehe, sieht richtig sortiert
nderscore

Ja, das ist eine Referenz / korrekte Ausgabe. Als ich Ihren Code ausprobiert habe, habe ich Folgendes erhalten
romaninsh

Entschuldigung, wenn ich Ihr Beispiel falsch ausgeführt habe.
Romaninsh

@romaninsh ah, ich hatte vor, dass es nur in der Konsole des Browsers ausgeführt wird. Hier ist eine neu formatierte Version, die auf dem Knoten funktioniert: gist.github.com/nderscore/96aa888c77d275c26c15
nderscore

2

PowerShell - 141

Liest Text aus einer Datei mit dem Namen '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

Groovy, 113/127 102/116 Zeichen

Angenommen, die Datei ist alles in einem Fall (102 Zeichen):

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

Angenommen, die Datei enthält gemischte Groß- / Kleinschreibung (116 Zeichen):

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

Grundsätzlich gilt:

  • t=new File('f').text Um den Text der Datei zu erhalten.
  • t.findAll('[A-Z]').unique().sort().each{c-> Um die eindeutigen Zeichen zu erhalten, sortieren Sie sie und wiederholen Sie sie.
  • print c*t.readLines()*.count(c).max() Holen Sie sich die maximalen Vorkommen in einer einzigen Zeile und drucken Sie das Zeichen so oft.

2

Bash (meistens 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'

Text muss an awk weitergeleitet werden (oder als Datei angegeben werden).

Beispiel Eingabe

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

Beispielausgabe

ACDDDEGHILLMMMOOSTVYY

PHP (könnte wahrscheinlich besser sein) - 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;

Angenommen, die Zeichenfolge ist in der Variablen $ s enthalten

Beispiel Eingabe

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

Beispielausgabe

ACDDDEGHILLMMMOOSTVYY

2

Mir ist klar, dass dies wahrscheinlich nicht die effizienteste Antwort ist, aber ich wollte trotzdem versuchen, das Problem zu lösen. Hier ist meine ObjC-Variante:

- (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:)];
}    

Dann können Sie es für eine beliebige Zeichenfolge aufrufen:

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

Ich habe über Anwendungen mit größeren Textmengen nachgedacht und möchte mein Array lieber nicht zählen müssen. Dazu habe ich die Methode folgendermaßen erweitert:

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

Laufen Sie wie folgt:

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

Werde dir geben:

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

Was ich für besser halte, wenn ich sehr viel Text hätte und nur wissen müsste, wie viele von jedem Buchstaben ich brauchen würde.



2

Python 2, 154 Bytes

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

Willkommen bei PCG! Diese Site unterstützt die Markdown-Syntax, mit der Sie Ihren Code so formatieren können, dass er ansprechend aussieht: rücken Sie einfach jede Codezeile mit vier Leerzeichen ein.
Algorithmushai

Sie müssen die Zeichen hinzufügen, die zum Importieren von Sammlungen erforderlich sind.
Isaacg

1
beantwortet die Frage nicht, da Sie die Mindestanzahl an Buchstaben benötigen, um jeden Satz einzeln zu schreiben. In Ihrem Code geben Sie die Anzahl der Buchstaben aus, die erforderlich sind, um alle Sätze gleichzeitig zu schreiben.
njzk2

sAm Ende der importAnweisung fehlt ein und im withBlock fehlt die Einrückung. Und da es sich um Codegolf handelt, ist es von großem Vorteil, unnötige Leerzeichen zu entfernen, wenn dies möglich ist.
Fraxtil

Da dies Codegolf ist, entfernen Sie die with-Anweisung (durchlaufen Sie einfach einen Aufruf zum Öffnen), und ich glaube, die Elemente müssen nicht sortiert werden.
RemcoGerlich

2

C 298 Bytes

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

Array D enthält eine Buchstabenliste für jede Zeile, dann wird die maximale Anzahl nach C kopiert.

Hinweis: Ich habe meine Antwort gestern eingegeben, sie ist jetzt jedoch nicht aufgeführt. Vielleicht habe ich versehentlich auf Löschen geklickt, anstatt sie zu bearbeiten.


Es sind nur 271 Bytes. Sie haben auch eine Menge irrelevanter Zeilenumbrüche. Auch können Sie das intvon int main()und weglassen int j,n;.
nyuszika7h

Auch deine bisherige Antwort ist noch da.
nyuszika7h

2

PHP, 143 Bytes

Angenommen, die Eingabe wird in Variable übergeben $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));}

Erläuterung

Für jeden möglichen Buchstaben ordne ich ein Array mit einer Liste von Zeichenfolgen durch eine benutzerdefinierte Funktion zu, die jede Zeile durch die Anzahl der verwendeten Zeichen ersetzt. Für den Buchstaben 'd' wird die Zeile "Mama liebt Papa" in 3 abgebildet.

Danach finde ich den Maximalwert innerhalb des Arrays und des Ausgabebuchstabens nur so oft. Hier ist eine mehrzeilige Version:

$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, einschließlich Beispiel, 136 ohne.):

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

Ich werde heute Nachmittag eine PYG-Probe veröffentlichen.


Ich hatte keine Ahnung, dass Python-Strings eine Zählmethode haben ... Ich nehme nicht an, dass es legitim ist, meine Antwort auf die Frage zu ändern, um dieses neu gefundene Wissen zu nutzen? : p
Tal

Sie tun es nicht. Es ist eine Methode einer Liste, wenn Sie genauer
hinsehen

1
Oh, ich verstehe ... aber in einer unerwarteten Wendung stellt sich heraus, dass Strings anscheinend auch diese Methode haben (auf jeden Fall in 3.x)
Tal
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.