L'alphabet de ma fille

65

L'autre jour, nous écrivions des phrases avec ma fille avec une lettre d'aimant de réfrigérateur. Bien que nous ayons pu en faire ( I love cat), nous n’avions pas assez de lettres pour faire les autres ( I love you too) en raison du nombre insuffisant de lettres o(4)

J'ai ensuite découvert que si un jeu comprenait 3 elettres, il n'en avait que 2 o. Probablement inspiré par http://en.wikipedia.org/wiki/Letter_frequency, cela ne refléterait toujours pas la situation réelle "sur le réfrigérateur".

Problème

Étant donné le fichier texte dans lequel chaque ligne contient un "exemple de phrase", vous souhaitez écrire sur le réfrigérateur, proposez un jeu d’alphabets comprenant un minimum de lettres mais suffisant pour écrire chaque phrase individuellement.

Remarque: ignorez les cas, toutes les lettres magnétiques sont des majuscules.

Contribution

Le fichier contient des phrases séparées par une nouvelle ligne:

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

Sortie

Fournissez une liste de lettres triée en ordre, chaque lettre apparaissant autant de fois qu'il est suffisant pour écrire une phrase:

acdddeghillmmmoostvyy

(merci, isaacg!)

Gagnant

Mise en oeuvre la plus courte (code)

MISE À JOUR: Test

J'ai créé un test supplémentaire et essayé avec diverses réponses ici:

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

Romaninsh
la source
2
Il devrait y avoir une lettre vdans la sortie;)
Antonio Ragagnin
40
Sommes-nous autorisés / tenus de substituer un à l'envers Mpour un Wou un côté Npour un Z? ;-)
Ilmari Karonen
4
Fondamentalement, vous pouvez construire n'importe quelle lettre en utilisant Is.
swish
7
Plus sérieusement, quand vous dites "ignorer les cas", voulez-vous dire que nous pouvons supposer que l'entrée est déjà tous dans le même cas, ou que nous devons tout convertir dans le même cas? De plus, est-ce que la sortie peut inclure des espaces de début?
Ilmari Karonen
3
@Doorknob:_\¯
Ilmari Karonen

Réponses:

18

GolfScript, 28/34 caractères

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

Le programme de 28 caractères ci-dessus suppose que toutes les lettres entrées sont dans le même cas. Si ce n'est pas nécessairement le cas, nous pouvons les forcer en majuscules en ajoutant {95&}%le code au préalable , pour un total de 34 caractères:

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

Remarques:

  • Pour un fonctionnement correct, l'entrée doit inclure au moins une nouvelle ligne. Cela sera vrai pour les fichiers texte normaux avec des nouvelles lignes à la fin de chaque ligne, mais peut ne pas l'être si l'entrée est composée d'une seule ligne sans fin de ligne. Cela pourrait être fixé au prix de deux caractères supplémentaires, en ajoutant n+le code au début .

  • La majuscule utilisée dans la version à 34 caractères est très grossière: elle mappe les lettres ASCII minuscules en leurs équivalents majuscules (et les espaces en NULs), mais crée un fouillis complet de chiffres et de la plupart des signes de ponctuation. Je suppose que l'entrée ne comprendra aucun de ces caractères.

  • La version à 28 caractères traite tous les caractères saisis (à l'exception des sauts de lignes et des NULs). En particulier, si l'entrée contient des espaces, certains apparaîtront également dans la sortie. commodément, ils trieront avant tout autre caractère ASCII imprimable. La version à 34 caractères, cependant, ignore les espaces (car il s’avère que je peux le faire sans que cela ne me coûte aucun caractère supplémentaire).

Explication:

  • Le {95&}%préfixe facultatif majuscule l'entrée en mettant à zéro le sixième bit du code ASCII de chaque entrée byte ( ). Cela mappe les lettres ASCII minuscules en majuscules, les espaces en octets nuls et laisse les nouvelles lignes inchangées.95 = 64 + 31 = 10111112

  • n/divise l'entrée aux nouvelles lignes et :aaffecte le tableau résultant à la variable a. Puis {|}*calcule l’union des chaînes dans le tableau (qui suppose (si le tableau comporte au moins deux éléments)) une chaîne contenant tous les caractères uniques (autres que les caractères de nouvelle ligne) de l’entrée.

  • La { }%boucle suivante parcourt ensuite chacun de ces caractères uniques. À l'intérieur du corps de la boucle, la boucle interne a{.[2$]--}%parcourt les chaînes du tableau a, supprimant de chaque chaîne tous les caractères différents de celui sur lequel la boucle externe effectue une itération.

    La boucle interne laisse le code ASCII du caractère actuel sur la pile, sous le tableau filtré. Nous nous en servons en répétant le tableau filtré autant de fois que le indique le code ASCII ( *) avant de le trier ( $) et de prendre le dernier élément ( -1=). En effet, cela produit la chaîne la plus longue du tableau filtré (toutes les répétitions du même caractère étant triées par le même caractère, le tri lexicographique les trie simplement par longueur), sauf si le caractère a le code ASCII zéro, auquel cas il ne produit rien.

  • Enfin, la $fin trie simplement la sortie par ordre alphabétique.

Ilmari Karonen
la source
3
Incroyable. TODO: Apprenez GolfScript!
DLosc
1
Vous pouvez même le réduire à 26: n/:a{|}*{{{=}+,}+a%$-1=}%$.
Howard
13

J - 37 caractères

Lit à partir de stdin, sorties sur la console.

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

1!:1]3est l'appel à stdin. tolower;._2effectue une double tâche en scindant les lignes et en les minuscules simultanément. Ensuite, nous comptons le nombre de fois qu'un caractère apparaît dans chaque ligne +/"2=/&a.et prenons le maximum de point par point sur toutes les lignes >./.

Enfin, nous extrayons autant de caractères de chaque caractère de l'alphabet #&a.. Cela inclut les espaces - tous trouvés à l'avant en raison de leur faible valeur ASCII - nous supprimons donc simplement les espaces en début de ligne avec dlb.

algorithmeshark
la source
12

JavaScript (ECMAScript 6) - 148 139 135 caractères

Version 2:

Mis à jour pour utiliser la compréhension du tableau:

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

Suppose que:

  • La chaîne d'entrée est dans la variable s;
  • Nous pouvons ignorer le cas de l'entrée (comme spécifié par la question - c'est-à-dire tout en majuscule ou en minuscule);
  • La sortie est un tableau de caractères (ce qui est à peu près aussi proche que JavaScript peut obtenir l'exigence d'une liste de caractères imposée par l'OP); et
  • La sortie doit être affichée sur la console.

Avec des commentaires:

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.

Si tu veux:

  • Renvoyez-le sous forme de chaîne, puis ajoutez .join('')la fin.
  • Prenez les entrées d'un utilisateur puis remplacez la svariable par prompt(); ou
  • Écrivez-le comme une fonction fpuis ajoutez-le f=s=>au début.

Fonctionnement:

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

Donne la sortie:

["A","C","D","D","D","E","G","H","I","L","L","M","M","M","O","O","T","V","Y","Y"]
MT0
la source
1
Agréable! Vous pouvez enregistrer 3 octets en réduisant /\s*/à / */et enlever les parens autourj=0
nderscore
1
ne pourriez-vous pas utiliser ...au lieu de apply?
Ven.
Grâce à vous deux - cela sauve 9 caractères - L’ opérateur spread ( ...) est un opérateur que je n’ai jamais rencontré auparavant.
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 octets

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

Compter le shebang comme 1. Ceci est une traduction en vrac de la solution Ruby ci-dessous.


Ruby 1.8 - 72 octets

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

L'entrée est prise de stdin.

Exemple d'utilisation:

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

$ ruby fridge-letters.rb < in.dat
ACDDDEGHILLMMMOOSTVYY
primo
la source
La sortie doit être triée.
Matt
@Matt maintenant corrigé.
primo
Agréable. Si votre Perl est vaguement récent, vous voudrez un espace entre /iet for.
tobyink
8

Python - 206 204 199 177 145 129 117 117 94 88 caractères

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

Je ne savais pas comment je devais obtenir le nom du fichier, donc pour le moment le code suppose qu'il est contenu dans une variable nommée f. S'il vous plaît laissez-moi savoir si je dois changer cela.

Tal
la source
8
dans l'esprit d'Unix - vous pouvez lire stdin.
romaninsh
5
faites toujours le nom de fichier d'un caractère long ...
3
@Tal Je suis aussi nouveau, mais s'il enregistre des caractères, pourquoi pas?
1
En supposant fque le nom de fichier soit entré et en utilisant des majuscules (toutes les lettres de l'aimant sont majuscules, de toute façon), vous pouvez le réduire à 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 eh bien, si nous courons cela dans la console, en théorie, il ne ferait qu'imprimer le résultat lui-même ...
Tal
6

Ruby 1.9+, 51 (ou 58 ou 60)

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

Suppose que tout est en minuscule. L’insensibilité à la casse coûte 7 caractères via .upcase, tandis que l’insensibilité à la casse et les minuscules coûtent 9 caractères via .downcase.

histocrate
la source
4

R (156, y compris lecture de fichier)

Avec table, je construis la table de fréquence des lettres pour chaque phrase. Ensuite, je finis par prendre pour chaque lettre la valeur maximale.

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

Solution:

acdddeghillmmmoooooostuvyy
LambruscoAcido
la source
@lambruscoAcido vous pouvez vectoriser les trois premières lignes (du code non-golfé) qui vous donneraient 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=""), mais ce n'est que 3 caractères plus court
jkd
Une autre approche avec seulement 112 caractères serait cat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")partons du principe fest le nom du fichier
JKD
4

Haskell, 109 108

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

Le programme lit à partir de stdin et écrit à sdtout.

C'est assez simple: il divise la chaîne en une liste de lignes et la reconstruit en itérant sur la liste et en ajoutant les nouvelles lettres contenues dans chaque ligne.

lortabac
la source
Oh wow pourquoi je n'ai jamais entendu parler de (\\) avant?
Flonk
4

Perl 6: 56 53 caractères; 58 55 octets

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

Pour chaque ligne, cela passe au peigne fin pour les caractères sans espace de la chaîne ( comb /\S/,.lc) minuscule , et crée un Bagou une collection de chaque caractère et son nombre de fois. [∪]prend l'union du Bags sur toutes les lignes, ce qui donne le nombre maximum d'occurrences du caractère. .pick(*)hack-y est ici, mais c’est le moyen le plus rapide d’obtenir tous les caractères de la Bagréplique par le nombre de fois où elle s’est produite.

EDIT: Pour voir si ce serait plus court, j'ai essayé de traduire la réponse de histocrat à Ruby . C'est 63 caractères, mais j'aime toujours beaucoup l'approche:

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

Haskell, 183 162 159

En supposant que le fichier est dans 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

Si fichier.txt contient, par exemple

abcde
abcdef
aaf

Le script va sortir

aabcdef

Fondamentalement, j'ajoute l'alphabet entier à chaque ligne, de sorte que lors du regroupement et du tri, je suis sûr que je vais me retrouver avec une liste contenant 27 éléments. Ensuite, je transpose le "tableau des fréquences", de sorte que chaque ligne de ce tableau se compose des fréquences d'une seule lettre dans chaque ligne, par exemple ["a","","aaa","aa","aaaa"]. Je choisis ensuite le maximum de chaque tableau (ce qui fonctionne exactement comme je le souhaite en raison du fonctionnement de Ord-instance of Strings), puis supprime la lettre que j'ai ajoutée au début, supprime les espaces et affiche le résultat.

Flonk
la source
1
Au lieu de drop 1, utilisez simplementtail
Bergi
@ Bergi Haha derp, merci! Je l'ai changé dans le post.
Flonk
3

C, 99 caractères

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

Il se bloque si moins d'une nouvelle ligne est fournie. Je pense que cela pourrait être résolu assez facilement.

zakk
la source
J'ai essayé, mais cela n'a pas donné de bons résultats. gist.github.com/romaninsh/11159751
romaninsh
3

kdb (q / k): 59 caractères:

d:.Q.a! 26#0
.z.pi:{d|:.Q.a##:'=_y}.z.exit:{-1@,/.:[d]#'!:d}
  • générer un dictionnaire de semences pré-trié à partir de l'alphabet .Qa
  • traiter chaque ligne d'entrée, convertir en minuscule, grouper dans un dictionnaire, compter chaque élément, prendre les caractères alphabétiques du résultat (espaces de suppression, sauts de ligne, etc. à ce stade) et utiliser max-assign to global d pour conserver un total cumulé.
  • définir un gestionnaire de sortie, qui est transmis à .z.pi pour enregistrer un délimiteur mais qui n’est pas utilisé là-bas. Prenez dans chaque valeur-clé pour générer une liste de caractères, aplatissez et finalement imprimez sur la sortie standard.

-1 ajoute une nouvelle ligne, utiliser 1 enregistre un caractère mais ne génère pas la sortie spécifiée. Si seulement je pouvais me débarrasser du passe-partout .z.pi / .z.exit, qui enlèverait 14 caractères.

Edit: évitez d’utiliser inter / asc en utilisant un dictionnaire de base.

utilisateur20349
la source
3

Perl, 46

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

Voici une autre solution Perl, lue dans STDIN, nécessite un -ncommutateur (+1 pour compter), une égalité avec le score de primo mais fonctionne sans problème :-). Il exploite le fait que orle résultat de bitwise a une longueur d'argument de chaîne plus longue.

utilisateur2846289
la source
1
essayé avec mon test et cela a très bien fonctionné.
romaninsh
3

J'ajoute ma propre solution:

Bash - 72

Suppose que l'entrée est dans le fichier "i"

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

Explication

Pour chaque lettre possible, filtre uniquement du fichier d'entrée, ce qui donne un résultat similaire à celui-ci:

AAA
A
A

AAAA

A
AAAAAAAAAAAAAAAA

Ensuite, le résultat est trié et la ligne la plus longue est sélectionnée. echo -nest là pour supprimer les nouvelles lignes.

Romaninsh
la source
3

Bash, 171 159 158, 138 avec sortie indésirable

Nécessite une entrée en minuscule seulement. Suppose que le fichier est appelé _(trait de soulignement). Maximum de 26 lignes dans le fichier d'entrée en raison des noms de fichiers gênants qui splitcréent (xaa, xab ... xaz, ???).

Dans bash, {a..z}sorties 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

Échantillon de sortie

acdddeghillmmmoostvyy

Explication

touch {a..z}

Créez des fichiers que nous lirons plus tard pour que bash ne se plaint pas qu'ils n'existent pas. Si vous supprimez cette ligne, vous enregistrez 13 caractères, mais vous obtenez beaucoup de sorties indésirables.

split _ -1

Fractionner le fichier d'entrée en sections, chacune stockant 1 ligne. Les fichiers créés par cette commande sont nommés xaa, xab, xac, etc., je ne sais pas pourquoi.

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

Pour chaque lettre, $lparcourez toutes les lignes stockées dans les fichiers xa$s.

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

Supprimez le -scommutateur pour enregistrer 1 caractère et obtenir beaucoup de sortie indésirable. Cela empêche grepde se plaindre de fichiers inexistants (cela se produira sauf si vous avez 26 lignes d’entrée). Cela traite le fichier xa$s, en supprimant tout sauf les occurrences $let en envoyant une sortie au fichier b$l. Donc, "j'aime maman" devient "mmm" avec de nouvelles lignes après chaque lettre quand $lest m.

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

Si le nombre de lignes dans le fichier que nous venons de créer est supérieur ou égal à (c.-à-d. Plus de lettres puisqu'il y a une lettre par ligne), le nombre de lignes dans notre résultat le plus élevé jusqu'à présent (stocké dans $l) ...

then mv b$l $l

... enregistrez notre nouvel enregistrement dans le fichier $l. À la fin de cette boucle, lorsque nous avons parcouru toutes les lignes, le fichier $lstockera x lignes contenant chacune la lettre $l, x étant le nombre le plus élevé d'occurrences de cette lettre sur une seule ligne.

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

Exportez le contenu de notre fichier pour cette lettre en supprimant les nouvelles lignes. Si vous ne voulez pas supprimer les nouvelles lignes, changez la ligne en tren echo $lsauvegardant 6 caractères.

done

la source
Essayé avec GNU bash, version 3.2.51 (apple), mais le fichier '-l1aa' dans un dossier contenant des données d’entrée.
romaninsh
@romaninsh Il se peut que vous ayez une version différente de split(de coreutils). Je suis actuellement sous GNU bash 4.3.8 et GNU coreutils 8.21 sur Ubuntu 14.04 et cela fonctionne bien (cela fonctionnait également sur Ubuntu 13.10 avant la mise à niveau). Cependant, j'ai dû placer le programme et le fichier d'entrée dans un répertoire distinct pour que tout fonctionne correctement. Je suppose que cela était dû uniquement aux millions de fichiers indésirables de mon dossier personnel .
@romaninsh en fait, si vous regardez la commande exacte dans le script: split _ -l1et vous remarquez que votre entrée est sauvegardée sur -l1aa, je pense que votre version de split ne reconnaît pas l' -l1option comme une option , mais la considère plutôt comme un préfixe pour la sortie. . Essayez de mettre un espace entre -let 1, ou de mettre --lines=1ou tout simplement -1(cela semble être une syntaxe obsolète et plus golfy avec laquelle je vais maintenant mettre à jour le post).
3

C #, 172 octets

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
la source
Intelligent ... intelligent ... Je pensais jouer avec linq, mais je pense que ce sera aussi court que ces foreachs contorsionnées :)
Noctis
2

Python 2 - 129

Idée de @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)

Quelques autres façons de faire la même chose avec le même nombre de caractères:

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

Cela suppose que le fichier est enregistré en tant que f dans un répertoire accessible. Ce programme est directement exécutable, sans aucune entrée supplémentaire nécessaire.

isaacg
la source
Pourquoi le vote bas? Désolé si j'ai fait quelque chose de mal.
isaacg
2

Mathematica v10 - 110

Ce n'est pas encore sorti, mais en lisant la nouvelle documentation très attentivement, je pense que cela devrait fonctionner:

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

Scala, 125 caractères

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

J'ai d'abord lu l'entrée en la convertissant en minuscule et en ajoutant une ligne vide.

Ensuite, pour chaque lettre de aà, zje répète le nombre maximum de fois que cette lettre apparaît dans l'une des lignes (c'est pourquoi j'ai besoin de la ligne vide: maxne peut pas être appelée avec une entrée vide). Ensuite, je viens de joindre les résultats et imprimer sur la sortie.

Pour lire à partir d'un fichier, remplacez stdinpar fromFile("FILENAME"), en augmentant la taille du code à 132 caractères + longueur du nom de fichier.

Karol S
la source
2

Javascript, 261 caractères

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

Supprimez le eval(...)et exécutez pour obtenir le code réel; c'est ( un peu ) compressé.

smulti-fonctions en tant que tableau de lignes et en tant que chaîne de sortie, hcontient l'histogramme des lettres par ligne et Hcontient l'histogramme avec les valeurs maximales jusqu'à présent. Il est insensible à la casse et ignore tout sauf az et AZ (je pense ... les tableaux JS sont parfois bizarres).

Maintenant correct :)

tomsmeding
la source
Cela ne fait que totaliser les personnages, pas tout à fait la question posée. Les lettres doivent être totalisées pour constituer le strict minimum pour former une seule phrase dans l'entrée, pas toutes. J'aime bien votre approche pour éviter la nécessité de trier la sortie.
Matt
@ Matt oh c'est vrai ... je vais le réparer plus tard. Je n'ai pas vraiment le temps pour l'instant.
tomsmeding
1
@Je me demandais ce qui se passait jusqu'à la fin. J'aime ça :)
Matt
2

JavaScript ( ES5 ) 141 octets

La variable supposée sest la chaîne d'entrée sans exigence de vérification de la casse ni sortie de tableau:

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
la source
J'ai testé votre solution et je cherchais une sortie dans "o", mais elle ne semble pas être triée correctement. (voir gist.github.com/romaninsh/11159751 )
romaninsh le
@romaninsh la sortie que je vois dans votre résumé a l'air bien triée
nderscore
Oui, c'est une référence / sortie correcte. Lorsque j'ai essayé votre code, j'ai eu ceci: gist.github.com/romaninsh/11161018
romaninsh
Toutes mes excuses si j'ai mal exécuté votre exemple.
Romaninsh
@romaninsh ah, j'avais prévu qu'il soit simplement exécuté dans la console du navigateur. Voici une version reformatée qui fonctionne sur le noeud: gist.github.com/nderscore/96aa888c77d275c26c15
nderscore
2

PowerShell - 141

Lit le texte d'un fichier nommé '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
la source
2

Groovy, 113/127 102/116 caractères

En supposant que le fichier est dans un cas (102 caractères):

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

En supposant que le fichier soit en casse mixte (116 caractères):

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

Fondamentalement:

  • t=new File('f').text Pour obtenir le texte du fichier.
  • t.findAll('[A-Z]').unique().sort().each{c-> Pour obtenir les caractères uniques, triez-les et effectuez une itération.
  • print c*t.readLines()*.count(c).max() Obtenez le maximum d'occurrences sur une seule ligne et imprimez le caractère plusieurs fois.
Dbramwell
la source
2

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

Le texte doit être redirigé vers awk (ou spécifié en tant que fichier).

Exemple d'entrée

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

Exemple de sortie

ACDDDEGHILLMMMOOSTVYY

PHP (pourrait probablement être mieux) - 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;

Suppose que la chaîne est contenue dans la variable $ s

Exemple d'entrée

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

Exemple de sortie

ACDDDEGHILLMMMOOSTVYY
Tyzoid
la source
2

Je me rends compte que ce n’est probablement pas la solution la plus efficace, mais je voulais quand même essayer de résoudre le problème. Voici ma variante 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:)];
}    

Ensuite, vous pouvez l'appeler pour n'importe quelle chaîne:

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

Je pensais aux applications avec de plus grandes quantités de texte et je préférerais ne pas avoir à compter mon tableau. Pour cela, j'ai ajouté à la méthode pour obtenir ceci:

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

Courez comme:

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

Te donnera:

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

Ce qui, à mon avis, est préférable si j'ai une très grande quantité de texte et qu'il me suffit de savoir combien de lettres il me faut.

Logan
la source
2

K, 34

{`$a@<a:,/(.:a)#'!:a:|/#:''=:'0:x}
tmartin
la source
2

Python 2, 154 octets

import collections
c = collections.Counter()
for line in open("input.txt"):
    c |= collections.Counter(line.upper())
print "".join(sorted(c.elements()))
Francfort
la source
Bienvenue chez PCG! Ce site supporte la syntaxe Markdown, que vous pouvez utiliser pour formater votre code, afin qu’elle paraisse agréable: indente chaque ligne de code de 4 espaces.
algorithmshark
Vous devrez ajouter les caractères nécessaires pour importer des collections.
isaacg
1
ne répond pas à la question, car vous avez besoin du minimum de lettres pour écrire chaque phrase individuellement. Dans votre code, vous indiquez le nombre de lettres nécessaires pour écrire toutes les phrases en même temps.
njzk2
Vous manquez un sà la fin de la importdéclaration et le withbloc manque d'indentation. Et puisqu'il s'agit d'un code de golf, il vous serait très utile d'éliminer les blancs inutiles dans la mesure du possible.
Fraxtil
puisqu'il s'agit d'un code golf, supprimez l'instruction with (il suffit de passer en boucle sur un appel à ouvrir) et je ne pense pas que les éléments doivent être triés.
RemcoGerlich
2

C, 298 octets

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

Le tableau D contient le décompte des lettres pour chaque ligne, puis le compte maximum est copié dans C.

Remarque: je mets ma réponse hier mais ne figure pas dans la liste. Peut-être ai-je appuyé sur supprimer au lieu de modifier par erreur?

bacchusbeale
la source
C'est seulement 271 octets. Vous avez également beaucoup de nouvelles lignes superflues. En outre, vous pouvez omettre les éléments intfrom int main()et int j,n;.
nyuszika7h
En outre, votre réponse précédente est toujours là.
nyuszika7h
2

PHP, 143 octets

En supposant que l'entrée est passée dans la variable $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));}

Explication

Pour chaque lettre possible, je mappe un tableau contenant une liste de chaînes grâce à une fonction définie par l'utilisateur qui remplace chaque ligne par le nombre de caractères utilisés. Pour la lettre 'd', la ligne "Maman aime papa" sera mappée en 3.

Ensuite, je trouve la valeur maximale dans un tableau et une lettre en sortie autant de fois. Voici la version multi-ligne:

$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
la source
1

Python (209, avec l'échantillon inclus, 136 sans.):

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

Je posterai un échantillon de PYG cet après-midi.

ıʇǝɥʇuʎs
la source
Je ne savais pas que les chaînes Python avaient une méthode de comptage ... Je ne suppose pas qu'il soit considéré comme légitime de modifier ma réponse à la question d'utiliser cette nouvelle connaissance? : p
Tal
@tal Ils ne le font pas. C'est une méthode de liste, si vous regardez de plus près
mardi
1
Oh, je vois ... mais dans une tournure inattendue, il s'avère que les chaînes ont apparemment aussi cette méthode (en 3.x de toute façon)
Tal