Una palabra compuesta es una palabra que contiene 2 o más palabras. Sin embargo, podemos hacerlo mejor que eso. Necesitamos que cree 1 palabra (sin sentido) que contenga cada palabra .
Sin embargo, queremos que esta palabra sea lo más breve posible. Podemos usar letras superpuestas para lograr esto.
Por ejemplo, si su lista de palabras era ["cat", "atom", "a"]
, desearía regresar "catom"
.
De entrada y salida
Su programa necesitará tomar una lista de palabras como entrada y devolver una palabra compuesta como salida.
La lista de palabras que usará son las 10000 palabras principales en inglés, según Google (si esta lista resulta ser demasiado fácil, puedo cambiarla por una más larga). Como referencia, simplemente agregar cada palabra le da un puntaje de 65888.
Su puntaje es el número de letras en su palabra final, menor es mejor. El desempate va al primer póster.
fuente
Respuestas:
C ++, longitud final de la palabra: 38272
(La versión optimizada tardó unos 20 minutos)
Verificación bash one-liner:
También produjo algunas palabras geniales en progreso. Aquí están algunos de mis favoritos:
Y:
El resultado final está en pastebin aquí: http://pastebin.com/j3qYb65b
fuente
max_word_length - overlap(word[i], word[j])
(dondeoverlap
verifica la superposición desde la derecha de la primer argumento a la izquierda del segundo). Resolver esto (¡buena suerte!) Y luego cortar el ciclo resultante al costo más alto (superposición más baja) dará una lista ordenada de palabras que se pueden combinar para dar una solución óptima.C ++ 11, 38272 letras, probado óptimo
Este algoritmo está garantizado para proporcionar un límite inferior en la solución. En este caso, puede lograr el límite inferior y generar una solución óptima de 38272 letras. (Esto coincide con la solución encontrada por el codicioso algoritmo de Dave. Me sorprendió y me decepcionó un poco descubrir que es óptimo, pero ahí estamos).
Funciona resolviendo el problema de flujo de costo mínimo en la red construida de la siguiente manera.
Cualquier cadena de longitud n que contenga cada palabra se puede convertir en un flujo en esta red con un costo máximo de n . Por lo tanto, el flujo de costo mínimo en esta red es un límite inferior en la longitud de la cadena más corta.
Si somos afortunados, y en este caso lo somos, entonces, después de redirigir el flujo que entra en w _1 fuera de w _0, encontraremos un flujo óptimo que solo tiene un componente conectado y que pasa a través del nodo para el vacío cuerda. Si es así, contendrá un circuito euleriano que comienza y termina allí. Tal circuito euleriano se puede volver a leer como una cadena de longitud óptima.
Si no tuvimos suerte, agregue algunos arcos adicionales entre la cadena vacía y las cadenas más cortas en los otros componentes conectados para asegurar que exista un circuito euleriano. La cadena ya no sería necesariamente óptima en ese caso.
Utilizo la biblioteca LEMON por su flujo de costo mínimo y algoritmos de circuito euleriano. (Esta fue la primera vez que usé esta biblioteca, y me impresionó, definitivamente la volveré a usar para futuras necesidades de algoritmos de gráficos). LEMON viene con cuatro algoritmos de flujo de costo mínimo diferentes; se puede tratar aquí con
--net
,--cost
,--cap
, y--cycle
(por defecto).El programa se ejecuta en 0,5 segundos , produciendo esta cadena de salida .
fuente
Java 8, ~ 5 minutos, duración de 39,279
Entrada:
Salida:
fuente
26,609
personajes.Python 2, 39254 caracteres
Tarda 1-2 minutos en ejecutarse en mi máquina, funciona tomando la palabra más larga y luego siempre agregando la palabra a la cadena de resultados que tiene la mayoría de las cadenas en común. (Antes de eso, todas las palabras que son subcadenas de otras palabras se eliminan para evitar adiciones innecesarias a la cadena).
Actualización: Intenté mirar en ambas direcciones, pero eso no mejora. (¿Tal vez está usando palabras que se pueden usar mejor más adelante?)
Enlace a la palabra en pastebin.
primeros 100 caracteres:
Código:
fuente
Ruby, 39222 caracteres
Utiliza un enfoque similar a @KarlKastor en su respuesta de Python, pero la cadena de inicio es una de las palabras más pequeñas en lugar de la más grande. Otra optimización (no sé cuánto ayuda) es que entre cada adición, elimina cualquier palabra que ya haya sido incluida en la cadena debido a la superposición de palabras.
Se ejecuta en poco más de 4 minutos en mi máquina, sin contar la solicitud web para recuperar la lista de palabras, pero no del todo 4:20.
La palabra sobre Pastebin.
fuente
PowerShell v2 +, 46152 caracteres
Toma la entrada como una lista, la convierte en una ArrayList (para que podamos manipularla). Nosotros
sort
porlength
en-des
orden cending. Entonces,while
todavía tenemos palabras en nuestra matriz de entrada, haga un ciclo. En cada iteración, configure Helper$x
para que sea igual a cuántos nos quedan, agregue el siguiente elemento de la lista a nuestra salida$o
y luego rastree todo lo que todavía está en nuestra lista. Si el.IndexOf
no es igual a-1
(es decir, la palabra se encontró en algún lugar$o
), eliminamos esa palabra de nuestra lista de palabras restantes. Finalmente, al final, salida$o
.No tengo acceso a un Pastebin o similar, así que aquí está el principio y el final de la palabra para temporal -
telecommunicationscharacterizationresponsibilitiessublimedirectory...fcmxvtwvfxwujmjsuhjjrxjdbkdxqc
. Lo que supongo que ha reducido unos 20,000 caracteres de la entrada, así que supongo que no está tan mal.Estoy trabajando en mejoras.
fuente
PHP 46612 caracteres
Esto es solo un comienzo. Espero mejorarlo. Todo lo que he hecho hasta ahora es eliminar cualquier palabra que sea una subcadena de otra palabra. Estoy trabajando en 3 copias de la matriz, pero la memoria no parece ser un problema.
fuente