La semana pasada, trabajamos para crear la cadena 1-D más corta usando las primeras 10,000 palabras en inglés . ¡Ahora, intentemos el mismo desafío en 2D!
Lo que debe hacer es tomar todas las palabras anteriores y colocarlas en un rectángulo lo más pequeño posible, permitiendo superposiciones. Por ejemplo, si sus palabras fueran ["ape","pen","ab","be","pa"]
, entonces un posible rectángulo sería:
.b..
apen
El rectángulo anterior daría una puntuación de 5.
Reglas:
- La superposición de varias letras en una palabra está permitida
- Las palabras pueden ir en cualquiera de las 8 direcciones
- Las palabras no pueden envolverse
- Puedes usar cualquier personaje para las ubicaciones vacías
Debe crear una búsqueda de palabras que contenga estas 10.000 palabras principales en inglés (según Google). Su puntaje es igual al número de caracteres en su búsqueda de palabras (excluyendo los caracteres no utilizados). Si hay un empate, o si se demuestra que una presentación es óptima, entonces la presentación que se publica primero gana.
fuente
Respuestas:
Rust,
3143030081 caracteres usadosEste es un algoritmo codicioso: comenzamos con una cuadrícula vacía y agregamos repetidamente la palabra que se puede agregar con la menor cantidad de letras nuevas, con lazos rotos al preferir palabras más largas. Para que esto se ejecute rápidamente, mantenemos una cola prioritaria de ubicaciones de palabras candidatas (implementado como un vector de vectores de deques, con un vector para cada número de letras nuevas, que contiene un deque para cada longitud de palabra). Para cada carta recién agregada, colocamos en cola todas las ubicaciones de candidatos que se ejecutan en esa carta.
Compilar y ejecutar con
rustc -O wordsearch.rs; ./wordsearch < google-10000-english.txt
. En mi computadora portátil, esto se ejecuta en 70 segundos, usando 531 MiB RAM.La salida cabe en un rectángulo con 248 columnas y 253 filas.
Código
fuente
C ++, cuadrícula de 27243 caracteres (248x219, relleno 50.2%)
(Publicar esto como una nueva respuesta porque me gustaría mantener el 1D encuadernado que originalmente publiqué como referencia)
Esta
estafa descaradamenteestá fuertemente inspirada en la respuesta de @ AndersKaseorg en su estructura principal, pero tiene un par de ajustes. Primero, uso mi programa original para fusionar cadenas hasta que la mejor superposición disponible sea de solo 3 caracteres. Luego uso el método que AndersKaseorg describe para llenar progresivamente una cuadrícula 2D utilizando estas cadenas generadas. Las restricciones también son un poco diferentes: todavía intenta agregar la menor cantidad de caracteres cada vez, pero los lazos se rompen al favorecer primero las cuadrículas cuadradas, luego las cuadrículas pequeñas y, finalmente, al agregar la palabra más larga.El comportamiento que muestra es alternar entre períodos de llenado de espacio y expansión rápida de la cuadrícula (desafortunadamente se quedó sin palabras justo después de una etapa de expansión rápida, por lo que hay mucho espacio en blanco alrededor de los bordes). Sospecho que con algunos ajustes de la función de costo se podría lograr que supere el 50% de espacio.
Aquí hay 2 ejecutables (para evitar la necesidad de volver a ejecutar todo el proceso al mejorar iterativamente el algoritmo). La salida de uno se puede canalizar directamente al otro:
Y finalmente, el resultado:
Resultado alternativo (después de corregir un par de errores en el programa que sesgaban ciertas direcciones y ajustaban la función de costo, obtuve una solución más compacta pero menos óptima): 29275 caracteres, 198x195 (75.8% de relleno):
Nuevamente, no he hecho mucho para optimizar estos programas, por lo que lleva un tiempo. Pero puedes ver cómo se llena la cuadrícula, lo cual es bastante hipnótico.
fuente
C ++, "cuadrícula" de 34191 caracteres (con mínima intervención humana, 6 o 7 se pueden guardar fácilmente)
Esto debería tomarse más como un límite para el caso 2D, porque la respuesta sigue siendo una cadena 1D. Es solo mi código del desafío anterior, pero con la nueva capacidad de revertir cualquier cadena. Esto nos da mucho más margen para combinar palabras (particularmente porque limita el peor de los casos de supercuerdas no superpuestas a 26; una para cada letra del alfabeto).
Para un ligero atractivo visual en 2D, pone saltos de línea en el resultado si puede hacerlo de forma gratuita (es decir, entre palabras con superposición de 0).
Bastante lento (aún sin almacenamiento en caché). Aquí está el código:
Resultado: http://pastebin.com/UTe2WMcz (4081 caracteres menos que el desafío anterior)
Está bastante claro que se pueden hacer algunos ahorros triviales colocando las líneas
xd
ywv
verticalmente, intersectando la línea monstruosa. Entonceshhidetautisbneudui
puede intersectarse cond
, ylxwwwowaxocnnaesdda
conw
. Esto ahorra 4 caracteres.nbcllilhn
puede sustituirse por unas
superposición existente (si se puede encontrar una) para guardar otras 2 (o solo 1 si no existe dicha superposición y debe agregarse verticalmente). Finalmente,mjjrajaytq
se puede agregar verticalmente en algún lugar para guardar 1. Esto significa que con una intervención humana mínima, se pueden guardar 6–7 caracteres del resultado.Me gustaría llevar esto a 2D con el siguiente método, pero estoy luchando por encontrar una manera de implementarlo sin hacer que el algoritmo O (n ^ 4), que es bastante poco práctico de calcular.
fuente
PHP
éste hace el trabajo teóricamente; pero 10000 son probablemente demasiadas palabras para la recursividad. El script se está ejecutando ahora. (todavía se ejecutó 24 horas después)
funciona bien en directorios pequeños, pero puedo hacer una versión iterativa la próxima semana.
$f=array("pen","op","po","ne","pro","aaa","abcd","dcba"); will output
abcdalthough this is not an optimal result (scoring was changed ... I´m working on a generator). One optimal result is this:
abiertoTampoco es muy rápido; solo elimina las subcadenas y clasifica los restos por longitud,
el resto es fuerza bruta: intente encajar las palabras en un rectángulo, intente con un rectángulo más grande si falla.
por cierto: la parte de la subcadena necesita 4,5 minutos en mi máquina para el directorio grande
y lo reduce a 6,190 palabras; el tipo de ellos lleva 11 segundos.
fuente