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 e
letras, solo tenía 2 o
letras. 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í:
v
en la salida;)M
por unW
, o uno de ladoN
por unZ
? ;-)I
s._\¯
Respuestas:
GolfScript, 28/34 caracteres
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: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
NUL
s), 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
NUL
s) 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:a
asigna la matriz resultante a la variablea
. 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 internoa{.[2$]--}%
itera sobre las cadenas de la matriza
, 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.fuente
n/:a{|}*{{{=}+,}+a%$-1=}%$
.J - 37 char
Lee desde stdin, salidas a consola.
1!:1]3
es la llamada a stdin.tolower;._2
realiza 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 condlb
.fuente
JavaScript (ECMAScript 6) -
148139135 caracteresVersión 2:
Actualizado para usar la comprensión de matriz:
Versión 1:
Asume que:
s
;Con comentarios:
Si quieres:
.join('')
al final;s
variable conprompt()
; of
luego agrégalof=s=>
al principio.Corriendo:
Da la salida:
fuente
/\s*/
de/ */
y la eliminación de los parens alrededorj=0
...
lugar deapply
?...
) es uno que no he encontrado antes.[].concat(...s.split`N`.map(x=>x.split(/ */).map((x,i,a)=>x+(a[x]=a[x]?++j:j=1)))).sort().map((x,i,a)=>a[i-1]<x?x[0]:'').join``;
Perl - 46 bytes
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
La entrada se toma de
stdin
.Uso de la muestra:
fuente
/i
yfor
.Python -
2062041991771451291179488 caracteresNo 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.fuente
f
el 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)]))
Ruby 1.9+, 51 (o 58 o 60)
Asume que todo está en minúsculas. La insensibilidad a
.upcase
mayúsculas y minúsculas cuesta 7 caracteres , mientras que la insensibilidad a mayúsculas y minúsculas cuesta 9 caracteres a través.downcase
.fuente
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.
Sin golf:
Solución:
fuente
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 cortocat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")
Suponiendof
es el nombre del archivoHaskell
109108El 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.
fuente
Perl 6:
5653 caracteres;5855 bytesPara 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 haceBag
una colección de cada carácter y cuántas veces ocurre.[∪]
toma la unión de laBag
s 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 delBag
replicado 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:
fuente
Haskell,
183 162159¡Suponiendo que el archivo esté adentro
file.txt
!Si file.txt contiene, por ejemplo
El script saldrá
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 laOrd
instancia de cadenas), y descarto la letra que agregué al principio, elimino los espacios y produzco el resultado.fuente
drop 1
, solo usetail
C, 99 caracteres
Se bloquea si se proporciona menos de una nueva línea. Creo que podría solucionarse con bastante facilidad.
fuente
kdb (q / k): 59 caracteres:
-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.
fuente
Perl, 46
Aquí hay otra solución de Perl, lee de STDIN, requiere un
-n
cambio (+1 para contar), se vincula con la puntuación de primo pero se ejecuta sin quejas :-). Explota el hecho de queor
el resultado de bit a bit tiene una longitud de argumento de cadena más larga.fuente
Estoy agregando mi propia solución:
Golpe - 72
Asume que la entrada está en el archivo "i"
Explicación
Para cada letra posible, la filtra solo del archivo de entrada que resulta en algo como esto:
Luego se ordena el resultado y se selecciona la línea más larga.
echo -n
está ahí para eliminar nuevas líneas.fuente
Bash,
171159158, 138 con salida de basuraRequiere 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 quesplit
crea (xaa, xab ... xaz, ???).En
bash
,{a..z}
salidasa b c d e f ...
.Salida de muestra
Explicación
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.
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é.
Para cada letra,
$l
lea todas las líneas almacenadas en los archivosxa$s
.Retire el
-s
interruptor para guardar 1 carácter y obtener una gran cantidad de basura. Evitagrep
quejarse de archivos inexistentes (ocurrirá a menos que tenga 26 líneas de entrada). Esto procesa el archivoxa$s
, elimina cualquier cosa menos las ocurrencias$l
y envía la salida al archivob$l
. Entonces "amo a mami" se convierte en "mmm" con nuevas líneas después de cada letra cuando$l
es m.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
) ...... almacena nuestro nuevo registro en el archivo
$l
. Al final de este ciclo, cuando hayamos pasado por todas las líneas, el archivo$l
almacenará 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.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
tr
aecho $l
, guardando 6 caracteres.fuente
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 .split _ -l1
y nota que su entrada se está guardando-l1aa
, creo que su versión desplit
no se reconoce-l1
como una opción y, en cambio, la toma como un prefijo para la salida . Intente poner un espacio entre-l
y1
, 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).C #, 172 bytes
fuente
Python 2 - 129
Idea de @Tal
Un par de formas más de hacer lo mismo en la misma cantidad de caracteres:
Esto supone que el archivo se guarda como f en un directorio accesible. Este programa es directamente ejecutable, sin necesidad de entrada adicional.
fuente
Mathematica v10 - 110
Todavía no está disponible, pero al leer la nueva documentación con mucho cuidado, creo que esto debería funcionar:
fuente
Scala, 125 caracteres
Primero leo la entrada, la convierto en minúsculas y agrego una línea vacía.
Luego, para cada letra de
a
az
, 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:max
no 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
stdin
confromFile("FILENAME")
, aumentando el tamaño del código a 132 caracteres + longitud del nombre del archivo.fuente
Javascript, 261 caracteres
Elimine
eval(...)
y ejecute para obtener el código real; esto está ( algo ) comprimido.s
Multi-funciones como la matriz de líneas y como la cadena de salida,h
contiene el histograma de las letras por línea yH
contiene 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 :)
fuente
@
Me preguntaba qué estaba pasando con el hasta que llegué al final. Me gusta :)JavaScript ( ES5 ) 141 bytes
Suponiendo que la variable
s
es la cadena de entrada sin requisitos de verificación de casos y salida de matriz:fuente
PowerShell - 141
Lee el texto de un archivo llamado 'a'.
fuente
Groovy,
113/127102/116 caracteresSuponiendo que el archivo es todo en un caso (102 caracteres):
Suponiendo que el archivo está en mayúsculas y minúsculas (116 caracteres):
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.fuente
Bash (principalmente awk) -
172163157El texto debe ser canalizado a awk (o especificado como un archivo).
Entrada de ejemplo
Salida de ejemplo
PHP (probablemente podría ser mejor) -
174210Asume que la cadena está contenida en la variable $ s
Entrada de ejemplo
Salida de ejemplo
fuente
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:
Entonces puedes llamarlo para cualquier cadena:
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:
Corre como:
Te regalaré:
Lo que creo que es mejor si tuviera una gran cantidad de texto y solo necesitara saber cuántas de cada letra necesitaría.
fuente
K, 34
fuente
Python 2, 154 bytes
fuente
s
al final de laimport
declaración y elwith
bloque 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.C, 298 bytes
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?
fuente
int
desdeint main()
yint j,n;
.PHP, 143 bytes
Suponiendo que la entrada se pasa en variable
$s
: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:
fuente
Python (209, con la muestra incluida, 136 sin.):
Publicaré una muestra de PYG esta tarde.
fuente