El alfabeto de mi hija

65

El otro día estábamos escribiendo oraciones con mi hija con una carta de imán de nevera. Si bien pudimos hacer algunas ( I love cat), no teníamos suficientes letras para hacer las otras ( I love you too) debido a una cantidad insuficiente de letras o(4)

Luego descubrí que si bien un juego incluía 3 eletras, solo tenía 2 oletras. Probablemente inspirado por http://en.wikipedia.org/wiki/Letter_frequency esto todavía no reflejaría la situación real "en la nevera".

Problema

Dado el archivo de texto donde cada línea contiene una "oración de muestra" que uno quisiera escribir en el refrigerador, proponga un conjunto de alfabeto con una cantidad mínima de letras pero aún suficiente para escribir cada oración individualmente.

Nota: ignore los casos, todas las letras magnéticas son mayúsculas de todos modos.

Entrada

El archivo contiene oraciones separadas por nueva línea:

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

Salida

Proporcione una lista ordenada de letras, donde cada letra aparece tantas veces como sea suficiente para escribir cualquier oración:

acdddeghillmmmoostvyy

(gracias, isaacg!)

Ganador

Implementación más corta (código)

ACTUALIZADO: Pruebas

He creado una prueba adicional y probé con varias respuestas aquí:

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

romaninsh
fuente
2
Debería haber una carta ven la salida;)
Antonio Ragagnin
40
¿Se nos permite / requiere sustituir un revés Mpor un W, o uno de lado Npor un Z? ;-)
Ilmari Karonen
44
Básicamente puedes construir cualquier letra usando Is.
swish
77
Más en serio, cuando dice "ignorar casos", ¿quiere decir que podemos suponer que la entrada ya está en el mismo caso, o que debemos convertir todo en el mismo caso? Además, ¿está bien que la salida incluya algunos espacios iniciales?
Ilmari Karonen
3
@Doorknob:_\¯
Ilmari Karonen

Respuestas:

18

GolfScript, 28/34 caracteres

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

El programa de 28 caracteres anterior supone que todas las letras de entrada están en el mismo caso. Si esto no es necesariamente así, podemos forzarlos a mayúsculas anteponiendo {95&}%el código, para un total de 34 caracteres:

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

Notas:

  • Para un funcionamiento correcto, la entrada debe incluir al menos una nueva línea. Esto será cierto para los archivos de texto normales con líneas nuevas al final de cada línea, pero podría no ser cierto si la entrada consta de una sola línea sin línea nueva. Esto podría arreglarse a costa de dos caracteres adicionales, anteponiéndose n+al código.

  • El uso de mayúsculas en la versión de 34 caracteres es realmente crudo: asigna letras minúsculas ASCII a sus equivalentes en mayúsculas (y espacios a NULs), pero crea un lío completo de números y la mayoría de los signos de puntuación. Supongo que la entrada no incluirá ninguno de esos caracteres.

  • La versión de 28 caracteres trata todos los caracteres de entrada (excepto las nuevas líneas y NULs) por igual. En particular, si la entrada contiene espacios, algunos también aparecerán en la salida; convenientemente, se ordenarán antes que cualquier otro carácter ASCII imprimible. La versión de 34 caracteres, sin embargo, ignora los espacios (porque resulta que puedo hacerlo sin que me cueste caracteres adicionales).

Explicación:

  • El {95&}%prefijo opcional pone en mayúscula la entrada poniendo a cero el sexto bit del código ASCII de cada byte de entrada ( ). Esto asigna letras minúsculas ASCII a mayúsculas, espacios a bytes nulos y deja nuevas líneas sin cambios.95 = 64 + 31 = 10111112

  • n/divide la entrada en las nuevas líneas y :aasigna la matriz resultante a la variable a. Luego {|}*calcula la unión establecida de las cadenas en la matriz, que (suponiendo que la matriz tenga al menos dos elementos) produce una cadena que contiene todos los caracteres únicos (no de nueva línea) en la entrada.

  • El siguiente { }%ciclo itera sobre cada uno de estos caracteres únicos. Dentro del cuerpo del bucle, el bucle interno a{.[2$]--}%itera sobre las cadenas de la matriz a, eliminando de cada cadena todos los caracteres que no son iguales al que está iterando el bucle externo.

    El bucle interno deja el código ASCII del carácter actual en la pila, debajo de la matriz filtrada. Hacemos uso de esto repitiendo la matriz filtrada tantas veces como lo indique el código ASCII ( *) antes de ordenarla ( $) y tomar el último elemento ( -1=). En efecto, esto produce la cadena más larga en la matriz filtrada (ya que todas consisten en repeticiones del mismo carácter, la clasificación lexicográfica solo las ordena por longitud), excepto si el carácter tiene código ASCII cero, en cuyo caso no produce nada.

  • Finalmente, $al final solo ordena la salida alfabéticamente.

Ilmari Karonen
fuente
3
Asombroso. TODO: ¡Aprende GolfScript!
DLosc
1
Usted puede incluso reducirla a 26: n/:a{|}*{{{=}+,}+a%$-1=}%$.
Howard
13

J - 37 char

Lee desde stdin, salidas a consola.

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

1!:1]3es la llamada a stdin. tolower;._2realiza una doble tarea dividiendo las líneas y haciéndolas minúsculas simultáneamente. Luego contamos cuántas veces ocurre un personaje en cada fila con +/"2=/&a., y tomamos el máximo puntual sobre todas las líneas con >./.

Finalmente, sacamos muchos de cada carácter del alfabeto con #&a.. Esto incluye espacios, todos encontrados en el frente debido a su bajo valor ASCII, por lo que simplemente eliminamos los espacios en blanco iniciales con dlb.

Algoritmo de tiburón
fuente
12

JavaScript (ECMAScript 6) - 148 139 135 caracteres

Versión 2:

Actualizado para usar la comprensión de matriz:

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

Versión 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])

Asume que:

  • La cadena de entrada está en la variable s;
  • Podemos ignorar el caso de la entrada (como se especifica en la pregunta, es decir, todo en mayúscula o minúscula);
  • El resultado es una matriz de caracteres (que es lo más cerca que JavaScript puede llegar al requisito del OP de una lista de caracteres); y
  • La salida se mostrará en la consola.

Con comentarios:

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 quieres:

  • Devuélvelo como una cadena y luego agrégalo .join('')al final;
  • Tome la entrada de un usuario y luego reemplace la svariable con prompt(); o
  • Escríbelo como una función y fluego agrégalo f=s=>al principio.

Corriendo:

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

Da la salida:

["A","C","D","D","D","E","G","H","I","L","L","M","M","M","O","O","T","V","Y","Y"]
MT0
fuente
1
¡Agradable! Puede guardar 3 bytes mediante la reducción /\s*/de / */y la eliminación de los parens alrededorj=0
nderscore
1
¿no podrías usar en ...lugar de apply?
Ven
Gracias a ambos, eso ahorra 9 caracteres. El operador spread ( ...) es uno que no he encontrado antes.
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 bytes

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

Contando el shebang como 1. Esta es una traducción suelta de la solución de Ruby a continuación.


Ruby 1.8 - 72 bytes

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

La entrada se toma de stdin.

Uso de la muestra:

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

$ ruby fridge-letters.rb < in.dat
ACDDDEGHILLMMMOOSTVYY
primo
fuente
La salida necesita ser ordenada.
Matt
@Matt ahora corregido.
primo
Agradable. Sin embargo, si tu Perl es vagamente reciente, querrás un espacio entre /iy for.
tobyink
8

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

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

No estaba seguro de cómo se suponía que debía obtener el nombre del archivo, por lo que en este momento el código supone que está contenido en una variable llamada f. Avíseme si necesito cambiar eso.

Tal
fuente
8
en el espíritu de Unix, puedes leer de stdin.
romaninsh
55
siempre haga que el nombre del archivo tenga un carácter largo ...
3
@Tal también soy nuevo, pero si salva personajes, ¿por qué no?
1
Asumiendo fel nombre de archivo de entrada y usando mayúsculas (todas las letras magnéticas son mayúsculas de todos modos), puede reducirlo a 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 bueno, si ejecutamos esto en la consola, en teoría solo imprimiría el resultado por sí mismo ...
Tal
6

Ruby 1.9+, 51 (o 58 o 60)

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

Asume que todo está en minúsculas. La insensibilidad a .upcasemayúsculas y minúsculas cuesta 7 caracteres , mientras que la insensibilidad a mayúsculas y minúsculas cuesta 9 caracteres a través .downcase.

histocrat
fuente
4

R (156, incl. Lectura de archivo)

Con la tabla construyo la tabla de frecuencia de letras para cada oración. Luego termino tomando para cada letra el valor máximo.

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

Sin golf:

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

Solución:

acdddeghillmmmoooooostuvyy
lambruscoAcido
fuente
@lambruscoAcido, podría vectorizar las tres primeras líneas (del código no codificado) que le daría 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=""), pero es solo 3 caracteres más corto
jkd
Otro enfoque con sólo 112 caracteres sería cat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")Suponiendo fes el nombre del archivo
Jkd
4

Haskell 109 108

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

El programa lee desde stdin y escribe en sdtout.

Es bastante sencillo: divide la cadena en una lista de líneas y la reconstruye iterando en la lista y agregando las nuevas letras contenidas en cada línea.

lortabac
fuente
Oh wow, ¿por qué nunca he oído hablar de (\\) antes?
Flonk
4

Perl 6: 56 53 caracteres; 58 55 bytes

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

Para cada línea, esta se peina a través de ella para los caracteres que no son espacios de la cadena en minúsculas ( comb /\S/,.lc), y hace Baguna colección de cada carácter y cuántas veces ocurre. [∪]toma la unión de la Bags sobre todas las líneas, lo que obtiene el número máximo de veces que ocurrió el carácter. .pick(*)es hack-y aquí, pero es la forma más corta de obtener todos los caracteres del Bagreplicado por la cantidad de veces que ocurrió.

EDITAR: Para ver si sería más corto, traté de traducir la respuesta Ruby de histocrat . Tiene 63 caracteres, pero todavía me gusta mucho el enfoque:

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

Haskell, 183 162 159

¡Suponiendo que el archivo esté adentro 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 file.txt contiene, por ejemplo

abcde
abcdef
aaf

El script saldrá

aabcdef

Básicamente, estoy agregando el alfabeto completo a cada línea, de modo que al agrupar y ordenar, estoy seguro de que terminaré con una lista que contiene 27 elementos. A continuación, transpongo la "tabla de frecuencias", de modo que cada fila de esta matriz consta de las frecuencias de una sola letra en cada línea, por ejemplo ["a","","aaa","aa","aaaa"]. Luego elijo el máximo de cada matriz (que funciona como quiero debido a cómo funciona la Ordinstancia de cadenas), y descarto la letra que agregué al principio, elimino los espacios y produzco el resultado.

Flonk
fuente
1
En lugar de drop 1, solo usetail
Bergi
@ Bergi Jaja derp, gracias! Lo cambié en la publicación.
Flonk
3

C, 99 caracteres

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

Se bloquea si se proporciona menos de una nueva línea. Creo que podría solucionarse con bastante facilidad.

zakk
fuente
Lo intenté, pero no produjo resultados correctos. gist.github.com/romaninsh/11159751
romaninsh
3

kdb (q / k): 59 caracteres:

d:.Q.a! 26#0
.z.pi:{d|:.Q.a##:'=_y}.z.exit:{-1@,/.:[d]#'!:d}
  • generar un diccionario semilla previamente ordenado del alfabeto .Qa
  • procese cada línea de entrada, convierta a minúsculas, agrupe en diccionario, cuente cada elemento, tome caracteres alfabéticos del resultado (es decir, pode espacios, líneas nuevas, etc. en esta etapa) y use max-asignar a d global para mantener un total acumulado.
  • defina el controlador de salida, que se pasa a .z.pi para guardar un delimitador, pero que no se utiliza allí. Tome de cada valor clave para generar una lista de caracteres, aplanar y finalmente imprimir en stdout.

-1 agrega una nueva línea, el uso de 1 guardaría un carácter pero no genera la salida especificada. Ojalá pudiera deshacerme de la repetitiva .z.pi / .z.exit, que eliminaría 14 caracteres.

Editar: evite el uso de inter / asc utilizando el diccionario semilla.

usuario20349
fuente
3

Perl, 46

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

Aquí hay otra solución de Perl, lee de STDIN, requiere un -ncambio (+1 para contar), se vincula con la puntuación de primo pero se ejecuta sin quejas :-). Explota el hecho de que orel resultado de bit a bit tiene una longitud de argumento de cadena más larga.

usuario2846289
fuente
1
Probé con mi prueba y funcionó muy bien.
romaninsh
3

Estoy agregando mi propia solución:

Golpe - 72

Asume que la entrada está en el archivo "i"

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

Explicación

Para cada letra posible, la filtra solo del archivo de entrada que resulta en algo como esto:

AAA
A
A

AAAA

A
AAAAAAAAAAAAAAAA

Luego se ordena el resultado y se selecciona la línea más larga. echo -nestá ahí para eliminar nuevas líneas.

romaninsh
fuente
3

Bash, 171 159 158, 138 con salida de basura

Requiere entrada solo en minúsculas. Asume que el archivo se llama _(subrayado). Máximo de 26 líneas en el archivo de entrada debido a los molestos nombres de archivo que splitcrea (xaa, xab ... xaz, ???).

En bash, {a..z}salidas 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

Salida de muestra

acdddeghillmmmoostvyy

Explicación

touch {a..z}

Cree archivos que leeremos más adelante para que bash no se queje de que no existen. Si elimina esta línea, ahorrará 13 caracteres pero obtendrá una gran cantidad de basura.

split _ -1

Divida el archivo de entrada en secciones, cada una almacenando 1 línea. Los archivos que crea este comando se denominan xaa, xab, xac, etc. No tengo idea de por qué.

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

Para cada letra, $llea todas las líneas almacenadas en los archivos xa$s.

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

Retire el -sinterruptor para guardar 1 carácter y obtener una gran cantidad de basura. Evita grepquejarse de archivos inexistentes (ocurrirá a menos que tenga 26 líneas de entrada). Esto procesa el archivo xa$s, elimina cualquier cosa menos las ocurrencias $ly envía la salida al archivo b$l. Entonces "amo a mami" se convierte en "mmm" con nuevas líneas después de cada letra cuando $les m.

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

Si el número de líneas en el archivo que acabamos de crear es mayor o igual que (es decir, más letras ya que hay una letra por línea), el número de líneas en nuestro resultado más alto hasta ahora (almacenado en $l) ...

then mv b$l $l

... almacena nuestro nuevo registro en el archivo $l. Al final de este ciclo, cuando hayamos pasado por todas las líneas, el archivo $lalmacenará x líneas, cada una de las cuales contiene la letra $l, donde x es el mayor número de ocurrencias de esa letra en una sola línea.

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

Imprima el contenido de nuestro archivo para esa letra en particular, eliminando nuevas líneas. Si no desea eliminar las nuevas líneas, cambie la línea con tra echo $l, guardando 6 caracteres.

done

fuente
Probado con GNU bash, versión 3.2.51 (apple), pero el archivo '-l1aa' en una carpeta actual que contiene datos de entrada ...
romaninsh
@romaninsh Puede ser que tenga una versión diferente de split(de coreutils). Actualmente estoy ejecutando GNU bash 4.3.8 y GNU coreutils 8.21 en Ubuntu 14.04 y funciona bien (también funcionó en Ubuntu 13.10 antes de actualizar). Sin embargo, tuve que colocar el programa y el archivo de entrada en un directorio separado para que funcione correctamente; sospecho que esto se debió solo a los millones de archivos basura en mi carpeta de inicio .
@romaninsh, de hecho, si observa el comando exacto en el script: split _ -l1y nota que su entrada se está guardando -l1aa, creo que su versión de split no se reconoce -l1como una opción y, en cambio, la toma como un prefijo para la salida . Intente poner un espacio entre -ly 1, o poner --lines=1, o simplemente -1(esto parece ser una sintaxis obsoleta y más golfística con la que ahora actualizaré la publicación).
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();
jzm
fuente
Inteligente ... inteligente ... Pensé en jugar con linq, pero dudo que sea tan corto como estos foreachs retorcidos :)
Noctis
2

Python 2 - 129

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

Un par de formas más de hacer lo mismo en la misma cantidad de caracteres:

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

Esto supone que el archivo se guarda como f en un directorio accesible. Este programa es directamente ejecutable, sin necesidad de entrada adicional.

isaacg
fuente
¿Por qué el voto negativo? Lo siento si hice algo mal.
isaacg
2

Mathematica v10 - 110

Todavía no está disponible, pero al leer la nueva documentación con mucho cuidado, creo que esto debería funcionar:

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

Scala, 125 caracteres

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

Primero leo la entrada, la convierto en minúsculas y agrego una línea vacía.

Luego, para cada letra de aa z, repito esa letra el número máximo de veces que aparece en cualquiera de las líneas (es por eso que necesito la línea vacía: maxno se puede invocar en una entrada enpy). Luego solo me uno a los resultados e imprimo a la salida.

Para leer un archivo, reemplácelo stdincon fromFile("FILENAME"), aumentando el tamaño del código a 132 caracteres + longitud del nombre del archivo.

Karol S
fuente
2

Javascript, 261 caracteres

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

Elimine eval(...)y ejecute para obtener el código real; esto está ( algo ) comprimido.

sMulti-funciones como la matriz de líneas y como la cadena de salida, hcontiene el histograma de las letras por línea y Hcontiene el histograma con los valores máximos hasta ahora. No distingue entre mayúsculas y minúsculas, e ignora todo menos az y AZ (creo que ... las matrices JS a veces son extrañas).

Ahora correcto :)

tomsmeding
fuente
Esto solo suma los caracteres, no exactamente lo que hizo la pregunta. Las letras deben sumarse para que sean el mínimo establecido para formar una sola oración en la entrada, no todas. Sin embargo, me gusta mucho su enfoque para evitar la necesidad de ordenar la salida.
Matt
@ Matt, eso es correcto ... lo arreglaré más tarde. Realmente no tengo tiempo en este momento.
tomsmeding
1
@Me preguntaba qué estaba pasando con el hasta que llegué al final. Me gusta :)
Matt
2

JavaScript ( ES5 ) 141 bytes

Suponiendo que la variable ses la cadena de entrada sin requisitos de verificación de casos y salida de matriz:

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
fuente
Probé su solución y buscaba una salida dentro de "o", pero no parece estar ordenada correctamente. (ver gist.github.com/romaninsh/11159751 )
romaninsh
@romaninsh, la salida que veo en tu esencia se ve correctamente ordenada
nderscore
Sí, esa es una referencia / salida correcta. Cuando probé su código, obtuve esto: gist.github.com/romaninsh/11161018
romaninsh
Disculpas si ejecuté tu ejemplo incorrectamente.
romaninsh
@romaninsh ah, tenía la intención de que solo se ejecutara en la consola del navegador. Aquí hay una versión reformateada que funciona en el nodo: gist.github.com/nderscore/96aa888c77d275c26c15
nderscore
2

PowerShell - 141

Lee el texto de un archivo llamado '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
fuente
2

Groovy, 113/127 102/116 caracteres

Suponiendo que el archivo es todo en un caso (102 caracteres):

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

Suponiendo que el archivo está en mayúsculas y minúsculas (116 caracteres):

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

Básicamente:

  • t=new File('f').text Para obtener el texto del archivo.
  • t.findAll('[A-Z]').unique().sort().each{c-> Para obtener los caracteres únicos, ordénelos e itere.
  • print c*t.readLines()*.count(c).max() Obtenga las ocurrencias máximas en una sola línea e imprima el personaje tantas veces.
dbramwell
fuente
2

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

El texto debe ser canalizado a awk (o especificado como un archivo).

Entrada de ejemplo

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

Salida de ejemplo

ACDDDEGHILLMMMOOSTVYY

PHP (probablemente podría ser mejor) - 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;

Asume que la cadena está contenida en la variable $ s

Entrada de ejemplo

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

Salida de ejemplo

ACDDDEGHILLMMMOOSTVYY
Tyzoid
fuente
2

Me doy cuenta de que probablemente esta no sea la respuesta más eficiente, pero de todos modos quería intentar resolver el problema. Aquí está mi variación de 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:)];
}    

Entonces puedes llamarlo para cualquier cadena:

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

Estaba pensando en aplicaciones con grandes cantidades de texto y prefiero no tener que contar mi matriz. Para esto, agregué al método para obtener esto:

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

Corre como:

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

Te regalaré:

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

Lo que creo que es mejor si tuviera una gran cantidad de texto y solo necesitara saber cuántas de cada letra necesitaría.

Logan
fuente
2

K, 34

{`$a@<a:,/(.:a)#'!:a:|/#:''=:'0:x}
tmartin
fuente
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()))
Frankfurt
fuente
¡Bienvenido a PCG! Este sitio admite la sintaxis de Markdown, que puede usar para formatear su código, de modo que parezca agradable: simplemente sangra cada línea de código 4 espacios.
algorithmshark
Deberá agregar los caracteres necesarios para importar colecciones.
isaacg
1
no responde la pregunta, ya que necesita la cantidad mínima de letras para escribir cada oración individualmente. En su código, genera la cantidad de letras necesarias para escribir todas las oraciones al mismo tiempo.
njzk2
Te falta un sal final de la importdeclaración y el withbloque carece de sangría. Y como se trata de un código de golf, sería de gran beneficio eliminar espacios en blanco innecesarios cuando sea posible.
Fraxtil
Como se trata de un código de golf, elimine la instrucción with (simplemente repita una llamada para abrir) y no creo que los elementos necesiten ser ordenados.
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);
}
}
}

La matriz D contiene el recuento de letras para cada línea, luego el conteo máximo se copia a C.

Nota: puse mi respuesta ayer pero ahora no aparece en la lista, ¿tal vez presioné eliminar en lugar de editar por error?

bacchusbeale
fuente
Son solo 271 bytes. También tienes muchas líneas nuevas extrañas. Además, puede omitir intdesde int main()y int j,n;.
nyuszika7h
Además, su respuesta anterior sigue ahí.
nyuszika7h
2

PHP, 143 bytes

Suponiendo que la entrada se pasa en 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));}

Explicación

Para cada letra posible, estoy mapeando una matriz que contiene una lista de cadenas a través de una función definida por el usuario que reemplaza cada línea con el número de caracteres utilizados. Para la letra 'd', la línea "Mami ama a papi" se mapeará en 3.

Luego encuentro el valor máximo dentro de la matriz y la letra de salida solo esto muchas veces. Aquí está la versión de varias líneas:

$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
fuente
1

Python (209, con la muestra incluida, 136 sin.):

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

Publicaré una muestra de PYG esta tarde.

ɐɔıʇǝɥʇuʎs
fuente
No tenía idea de que las cadenas de Python tenían un método de conteo ... ¿No creo que se considere legítimo cambiar mi respuesta a la pregunta para usar este nuevo conocimiento encontrado? : p
Tal
@tal No lo hacen. Es un método de una lista, si miras más de cerca
Aprıʇǝɥʇuʎs
1
Oh, ya veo ... pero en un giro inesperado resulta que las cuerdas aparentemente también tienen este método (en 3.x de todos modos)
Tal