Buen día.
Hoy nos pondremos un poco mas "rudos", pero solo un poco; nos plantearemos el hecho de hacer un programa que pueda resolver sopas de letras, tendremos que examinar bien el funcionamiento y tratar de recrearlo en nuestro lenguaje de programación preferido, como ya lo saben, pueden leer la descripción del reto y detenerse allí, pues hay ciertas personas que prefieren afrontar el reto desde cero y de ser así nos pueden enviar sus respectivas soluciones alternas. Esperamos que les guste y ya saben, cualquier comentario, sugerencia, correcion o lo que sea, lo pueden comentar y les sera respondido con el mejor de los gustos.
Hoy nos pondremos un poco mas "rudos", pero solo un poco; nos plantearemos el hecho de hacer un programa que pueda resolver sopas de letras, tendremos que examinar bien el funcionamiento y tratar de recrearlo en nuestro lenguaje de programación preferido, como ya lo saben, pueden leer la descripción del reto y detenerse allí, pues hay ciertas personas que prefieren afrontar el reto desde cero y de ser así nos pueden enviar sus respectivas soluciones alternas. Esperamos que les guste y ya saben, cualquier comentario, sugerencia, correcion o lo que sea, lo pueden comentar y les sera respondido con el mejor de los gustos.
Descripción Sopa_de_Letras :
Realizar un
programa que resuelva una Sopa de Letras de tamaño MxN, lo que implicaría poder encontrar en dicha Sopa de Letras
todas las palabras que están contenidas en una lista P de tamaño cualquiera; Además de encontrar las palabras, el
programa debe definir la posición y dirección de la palabra encontrada en
la Sopa de Letras.
Datos de Entrada:
1.
Sopa de letras de MxN.
2.
Lista P de palabras clave.
Datos de Salida:
1.
Un mensaje indicando la palabra
encontrada, la posición y la dirección.
Ejemplo de uso:
Datos de Entrada:
1.
Sopa de letras:
VVCKRXDWIJ
ZANOAMIGGF
MLADDLNQHQ
OBAOAIRMFP
ACOCKCOAWO
SRUCUNSCEG
ERALJAEABI
MHOATRPSQP
IFAUFOVOFS
DADIRUGESE
2.
Lista P de palabras a buscar:
SEGURIDAD
HACKING
WEB
OCULTO
SCADA
Datos de
Salida:
1.
La palabra SEGURIDAD está ubicada partiendo de la posición (10,9) hacia la izquierda.
2.
La palabra HACKING está ubicada partiendo de la posición (8,2) en forma de diagonal superior derecha.
3.
La palabra WEB está ubicada partiendo de la posición (5,9) hacia abajo
4.
La palabra OCULTO está ubicada partiendo de la posición (4,1) en forma de diagonal inferior derecha.
5.
La palabra SCADA está ubicada partiendo de la posición (6,1) en forma de diagonal superior derecha.
-----------------------------------------------------------------------------------------------------------------
Ahora que ya
tenemos la descripción del reto que debemos afrontar, tendremos que suponer que
iniciaremos desde cero para hacer nuestro programa, esto con el ánimo de que
pensemos diferentes métodos para poder atacarlo así que no se asusten, vamos a
retomar el análisis desde cero y así verán que un reto de programación es 80%
análisis 20% programación, también conviene decir que si aún no has intentado
realizar este reto, puedes detenerte aquí e intentar realizarlo, y si así lo
quieres, tú solución podrá ser publicada en este post.
Bueno, para
poder ver más gráficamente este problema, vamos a construir una sopa de letras
(la del ejemplo) de la manera más común como nos la muestran, en este caso una
tabla.
¿Pero de que nos
ayuda ver la sopa de letras de esta manera?, En principio muchos pueden decir
que esta manera gráfica nos complica las cosas, pero no es así, dado que de
esta manera, podemos ver todo el sistema como una gran matriz de MxN y con esto, podemos acceder a cada
uno de las letras, especificando el número de la fila y el número de la columna
donde se encuentra dicha letra (Esto se explica mucho mejor en el post de “camino corto”). Un ejemplo de esto, es que si pedimos la letra
que se encuentra en la posición (1,1)
tendremos que en dicha posición se encuentra la letra V, y si pedimos la letra que está en la posición (6,6) y la letra en la posición (10,10) obtendremos respectivamente N y E, así que con esta información, ya sabemos que podemos definir
toda nuestra sopa de letras como array
bidimensional o como una lista
bidimensional, y solo basta con ir accediendo a cada posición que deseemos,
primero especificando la fila y
luego la columna donde se encuentra
(dado que solo utilizamos dos coordenadas filas y columnas, podemos ver esto
más gráficamente como un plano cartesiano, con x,y), teniendo esto claro, ya hemos definido nuestro sistema de
trabajo.
Como ya
definimos nuestro sistema de trabajo, ahora vamos a recordar un poco nuestra
infancia, y si tenemos buena memoria, podremos recordar que en una sopa de
letras hay varias maneras de encontrar una palabra o de buscarla, por ejemplo,
mi táctica era buscar no la palabra completa sino solo buscar su letra inicial,
y una vez la encontraba miraba a su alrededor haber si las demás coincidían con
toda la palabra que yo buscaba, de no ser así, simplemente seguía recorriendo
la sopa de letras hasta encontrar otra vez la letra inicial de la palabra que
estaba buscando, y repetía esto hasta revisar toda la sopa de letras o gran parte de ella;
Mis compañeros hacían lo mismo pero no solo con la primera letra, sino también
con la última, dado que una palabra podría estar tanto al derecho como al revés,
otros recorrían toda la sopa de letras
primero mirando fila por fila, o columna por columna; Bueno creo que esas son
todas las tácticas que utilice en mi infancia, así que no menosprecien la
curiosidad de un niño, ps todas esas tácticas son 100% viables para poder
resolver una sopa de letras, lo que haremos será simular cada uno de esos
pasos, y como utilizaremos una computadora, realizaremos la misma cantidad de
pasos, solo que en un tiempo record.
Y haciéndole
honor a nuestra querida infancia, vamos a utilizar dichas tácticas para nuestro
programa, pero primero debemos descomponerlas de una manera más concisa y
fiable, por ejemplo, primero miremos las posibles maneras de encontrar una
palabra, en este caso tenemos 8 posibilidades maneras.
1. Al derecho (normal)
2. Al revés
3. Hacia arriba
4. Hacia abajo
5. Diagonal Superior Izquierda
6. Diagonal Inferior Izquierda
7. Diagonal Superior Derecha
8. Diagonal Inferior Derecha
Como podemos
ver, si nos situamos en alguna letra, solo tendremos que verificar esas 8 posibles maneras, y en alguna de
ellas tendrá que estar la palabra que buscamos, y de no ser así, simplemente
cambiamos de L, ósea de letra y
repetimos el proceso. Bueno, entonces si recapitulamos nuevamente todo lo que
llevamos:
1. Recorrer toda la sopa de letras
1.
Si la letra, coincide con el primer carácter de la palabra a buscar
1.
verificamos las 8 posibles maneras de encontrar la palabra
2.
si la letra, NO coincide con el
primer carácter de la palabra a buscar
1.
seguimos recorriendo la sopa de letras hasta encontrar una que coincida
Un buen refrán
que me gusta a la hora de programar es ese que dice: “Divide y vencerás”, así que
siempre trato de estructurar todo el código tratando dividir todo el procedimiento
en funciones, por ejemplo, en este caso he divido todo lo que vamos a
hacer en 4 funciones:
- Matriz_y_palabras ()
- Posicion_inicial (b_palabra,matriz,M,N)
- Ocho_posibilidades (matriz,i,j,b_palabra)
- Verificando (op,i,j,matriz,palabra)
Iremos explicando el funcionamiento de cada función en particular, dado que como ya lo dijimos, tenemos claro cómo funciona todo el sistema general; En principio, no quiero que piensen que este código fue el primero o el que se realizo sin mayor apuro pues la realidad es distinta, se hicieron tres códigos diferentes pero el que expondremos aquí, fue el más “elegante” y por ende el mas entendible para poderlo explicar en su totalidad.
##</CODIGO>##
1. Matriz_y_palabras()
2.
Posicion_inicial (b_palabra,matriz,M,N)
3.
Ocho_posibilidades (matriz,i,j,b_palabra)
4. Verificando (op,i,j,matriz,palabra)
1. Matriz_y_palabras()
Bueno, para hacer que el programa sea un poco mas ordenado y mas
utilizable, definimos que todos los datos de entrada estarán contenidos en un
archivo .txt, y es con esta función
con la cual sacaremos los datos que en este caso, nos retornara la dimensión de
la sopa de letras, también nos retornara la sopa de letras y la lista de
palabras a buscar; esto lo hacemos suponiendo que el archivo .txt tiene los datos organizados de
cierta manera, así al momento de sacar los mismos, no nos generara ningún tipo
de error.
En principio lo que hacemos es algo básico de manejo de archivos, en
este caso, abrimos el archivo en modo lectura (read), y con la función de archivo.redlines() obtenemos los datos
del archivo en forma de lista y separado por cada renglón (\n), una vez tenemos esto, según la estructura del archivo .txt, sabemos que en la primera línea
ira la dimensión de la sopa de letras MxN,
pero para poderla sacar, es necesario quitar el carácter “\n” así que esto lo hacemos con datos[0].replace(“\n”,””) y también sabemos que la dimensión M y N está separada por un espacio, así que con el método datos[0].split(“ ”) retornamos y
guardamos la dimensión en las variables M
y N; Ahora crearemos la matriz
bidimensional que va a simular la sopa de letras, así que teniendo la dimensión
MxN recorreremos los datos hasta
allí y los almacenaremos primero en una lista llamada columna y después almacenaremos a columna en la variable matriz,
con lo cual crearemos la simulación de lista bidimensional [[columna]] o matriz.
Ahora solo nos falta sacar la lista de palabras a buscar, pero como
ya sabemos la estructura del archivo .txt,
sabemos que las palabras están en la ultima línea, por eso siempre estarán en datos[-1], pero como las delimitamos con
una coma (,) entonces tendremos que
separarlas con el método datos[-1].split(“,”)
y así obtendremos un lista con todas las palabras, que almacenaremos en la
variable palabras. Y una vez esto,
ya tenemos todos los datos que nos proporciona tanto el archivo como la sopa de
letras.
Como ya hemos planteamos
nuestra estrategia desde el principio, esta función será la encargada de buscar
en la matriz las letras que coincidan con el primer carácter de la palabra a
buscar, y en caso de que sea encontrada, posteriormente se intentara probar las
ocho posibles maneras de encontrar una palabra.
Como tenemos la dimensión de la sopa de letras (MxN), crearemos dos bucles for
uno contenido dentro del otro, y donde el primero partirá de desde 0 hasta M y el segundo partirá desde el 0 hasta el N; Esto lo
hacemos con el fin de poder recorrer toda la sopa de letras, dado que con M recorremos las i filas y con N recorremos
las j columnas, entonces realizamos
una verificación donde especificamos que si la letra contenida en la posición (i,j) es igual a la primera letra de la
palabra[0] a buscar, entonces
tendremos que verificar las ocho posibles formas de encontrar dicha palabra,
pero en caso de que no se cumpla esta igualdad, simplemente seguimos
recorriendo la sopa de letras hasta encontrar otra letra que coincida con el
primer carácter de la palabra a buscar y posteriormente llamamos a la función
que nos dice si se halla la palabra en alguna de las 8 maneras posibles. Esto
es un proceso simple y repetitivo, es cuestión de tener clara la forma general
de cómo va a ser nuestra estrategia general.
Bueno, esta función es fácil de entender, lo primero que hacemos es eliminar
la primera letra de la palabra que estamos buscando, dado que como ya pasamos
el filtro de la función Posicion_inicial(),
quiere decir que ya estamos parados en la primera letra de la palabra que
buscamos así que no es necesario seguirla buscando en alguna de las ocho
posibles maneras; también tenemos un bucle FOR
que va desde 1 hasta 9 (sin incluirlo), el cual representa que cada vez que
complete un ciclo, quiere decir que ya probamos la forma 1, la forma 2, la
forma3… de cómo hallar la posible palabra y para esto llamamos la función verificando() con un x variante según el bucle FOR.
En realidad esta función es la parte
“elegante” de todo el código y se
podría decir que la más importante del mismo; en principio para entender su
funcionamiento, tendremos que tener presente que para encontrar una palabra en
la sopa de letras, cada letra de dicha palabra va a estar en una posición (i,j) diferente de las demás, por
ejemplo, las ocho maneras de hallar la palabra oculto son estas:
Como podemos observar, cada letra de la
palabra (OCULTO), tiene una posición
(i,j) diferente lo que quiere decir
que para poder verificar si una palabra completa esta dentro de la sopa de
letras, tendremos que asignar cada letra a un (i,j); por ejemplo, si partimos desde el centro O para poder verificar si la palabra
completa esta en alguna de las ocho posibilidades, podemos observar que si
queremos realizar un movimiento en la forma 1, solo tendremos que alterar las
columnas, sumándole 1, quedando así la nueva posición (i,j+1). Y en general las ocho posibles maneras de encontrar la palabra
quedan resumidas en estas ocho posibles maneras de movimiento, una para cada
una.
Teniendo esto claro, podemos observar
que en la función verificando(),
hemos definido ocho sentencias IF y ELIF, los cuales van a resultar
verdaderos solo según la forma en que se esté buscando dicha palabra (1,2,3,4,5,6,7,8), dado que cada una de
las posibles formas implica un tipo especial de movimiento, y esto lo vemos
reflejado, alterando el valor de la variable i y la variable j, según
la forma que estemos probando.
Bueno, lo que hace especial a esta función
es que utiliza la recursividad de una manera muy creativa, en principio la función
verificando() se llama a si misma
dentro de ella pero cambiando los parámetros que se le pasan; Tenemos que
siempre se escoge el primer carácter de la palabra a buscar, y en cada nueva
llamada a si misma, vamos recortando la palabra carácter por carácter, y si
cada carácter coincide con las letras en la sopa de letras, quiere decir que al
final la palabra a buscar será de un carácter, y en dicho caso, la función no
se volverá a llamar a si misma, sino que retornara TRUE, indicando que hemos encontrado toda la palabra y que ya
podemos pasar a buscar la siguiente.
Si, sé que esto es algo confuso de
explicar pero pueden ver el código dado que está documentado, y así podrán entender
bien el funcionamiento de la misma.
Formato:
Salida:
Espero que haya sido de su agrado, se muy bien que me complico en muchas explicaciones, pero igualmente cualquier duda o mal entendido, puede ser reportado y sera debidamente atendido.
Al ejecutar el codigo genera un error que dice invalid syntax y señala la linea 47 donde esta print "ERROR [+]", queda señalando el cierre de la comilla doble.
ResponderEliminarBuen día.
ResponderEliminarRevisé de nuevo el código, pero no me aparece ningún error, yo creería que el error que ves se debe a un mal copiado del código, ps python reconoce las tabulaciones y los espacios, entonces te recomiendo revisar esa parte, y por si las moscas, recordar que el código esta hecho bajo python 2.7.. y utilizar unos datos correctos, siguiendo la sintaxis, primero el tamaño de la matriz, M N, después la sopa de letras y por último las palabras a buscar, pero separadas simplemente por una coma, tal como lo muestra la imagen..
Espero que tú inconveniente se solucione, de igual manera, cualquier cosa estaré muy pendiente.
Traceback (most recent call last):
ResponderEliminarFile "resolver_una_sopa_de_letras.py", line 81, in
M,N,matriz,palabras=Matriz_y_palabras() #int(M),int(N),matriz,palabras
File "resolver_una_sopa_de_letras.py", line 6, in Matriz_y_palabras
M,N=(datos[0].replace("\n","")).split(" ") #Sacamos el tamano de la matriz MxN
ValueError: need more than 1 value to unpack
Cómo lo soluciono?
Q onda
ResponderEliminarola q aseea
ResponderEliminardonde puedo correr el programa
ResponderEliminaramen!
ResponderEliminaramen, ¿que decias?
ResponderEliminarXXX
ResponderEliminarYNDECAERLIPATU
ResponderEliminarZPSVLMTEDVEBIO
NDRKIGMLLIDUTI
QNGTERRORACEAL
DBEYNSRDMHOLNA
VJULTRATUMBADX
SGTNEJGCUNTSZC
OGROSLBEVTIHON
?
EliminarHola xd
EliminarP H W Y E I E
ResponderEliminarE C J C Z T T
S A M A A N B
X M P B S B A
X E Z Z N U R
R L J L O T C
I O A O R N O
hola, el codigo esta perfectamente y lo que tienen que hacer es lo siguiente (si son novatos en la programacion como yo)
ResponderEliminar1. tener instalado python 2.7
2. tener instalado visual code estudio
3. ponen todo el codigo en el visual y lo guardan con extension .py
4. lo ponen todo en una carpeta (el txt y el codigo.py)
5. abren el shell de python 2.7 (lo pueden abrir desde la barra de busqueda)
6. lo ejecutan (a mi me aparecia con el texto de la version y me daba error por eso, asi que dejan solo el codigo)
7. disfrutar porque se saltaron una tarea B)
Santiago ayúdame 999892036, lo necesito para hoy urgente :'(
ResponderEliminarchj
ResponderEliminarᴀ ᴄ ᴀ ʟ ʟ ᴜ ᴠ ɪ ᴀ ꜱ
ResponderEliminarᴄ ᴀ ʀ ᴀ ᴅ ᴜ ʀ ᴀ ɴ ᴀ
ᴀ ɴ ᴇ ᴠ ᴄ ᴀ ꜱ ᴀ ꜰ ɢ
ᴍ ᴛ ᴍ ᴀ ᴀ ᴍ ʙ ᴛ ᴏ ᴜ
ᴀ ɪ ᴜ ᴠ ʙ ᴜ ɴ ᴇ ʀ ᴀ
ʀ ꜰ ɴ ᴀ ʀ ᴇ ᴄ ᴏ ᴄ ꜰ
ᴀ ᴀ ᴀ ᴊ ᴏ ꜱ ɪ ᴍ ᴀ ɪ
ɴ ᴢ ɢ ɪ ʀ ᴀ ꜱ ᴏ ʟ ᴇ
ᴛ ᴇ ɪ ʟ ᴄ ᴀ ʀ ᴛ ɪ ꜱ
ᴀ ᴛ ᴏ ʟ ᴇ ɴ ᴛ ʀ ꜱ ᴛ
ʟ ɪ ꜱ ᴀ ɴ ᴇ ɴ ᴜ ᴛ ᴀ
ꜱ ᴀ ʟ ᴠ ᴀ ᴠ ɪ ᴅ ᴀ ꜱ
Hola, me tome la libertad de modificarlo un poco porque note que no comprobaba la última letra de la palabra; se ve en las palabras cortas
ResponderEliminarque son más fáciles de generar y tienen más posibilidades, en las palabras largas simplemente acierta.
Además note que buscaba las palabras saliendo desde cualquier borde de la matriz y entrando desde el borde contrario.
Igual no se programar así que les dejo el código por si les sirve y para que lo revisen.
Justo estaba buscando un software para buscar palabras en una sopa de letras y encontre éste, gracias me fue muy útil.
No se si el código lo pego acá o en otro lugar.
E M P A T I A Q W R T
ResponderEliminarP I U Y T A S D F E O
D I A L O G O H G S T
S R A H C U C S E P E
V A L O R V A L O E P
H J K L Ñ Z X C V T S
N M A M O E L E B I E
C O N F L I C T O S R
C A S A H O L A Q R T
A S D F G H J B F R D
C O N V I V E N C I A
QUIERO QUE RESUELVAN MI SOPA DE LETRAS PORFA
ResponderEliminarBuenas, ¿Donde puedo encontrar el código?
ResponderEliminarM E R T Y U G F F G V H C N O D E V B F S
ResponderEliminarF M I A S F V R J K L Ñ O Z I O M I L O S
A P C R A E I E A I D A N A S S I C P D C
C E A A P O V C I K I T S P L P T O I E U
T R R R O E I I M E M O I A A X R O T S E
U C U B B L R B E E O E G T D T I C O B N
R R G L U S D O T L R L N E X G O V A T
A O O A S T E D E L D E A S I W O L C T A
D W P N E U Q E H C S C C F H M G S E M D
E A O C A R A C U L D O I C O T O M L O E
V D S A S N O A N I N A O L O Q U T E O A
E R A G A P U J A T I F N O M A L A S T H
N C F E O M J A A A O D F G U I P O R I O
T C O M P R O B A N T E I N G R E S O B R
A C P O K H L X E R F C X U R A D G E R
X A Q W E E F G H J J B B N J O J J H D O
F D F F S G H J J K L L Ñ ´S E S A F B A M
H G I L O T I D E R C E D A T E J R A T N
M C P Q R S T L Z H A D X N L R Ñ O P O S
H T R Q X W V A C D O M Z X S D G J O N C
L E T R A D E C A M B I O S D E F G R L V
1 FACTURA
2 CHEQUE
3 NOTA DEBITO
4 REPORTES CONTABLES
5 RECIBO DE CAJA
6 CONSIGNACION
7 EGRESO
8 TARJETA DE CREDITO
9 CUENTA DE AHORRO
10 COMPROBANTE INGRESO
11 LETRA DE CAMBIO
12 PAGARE
Si, seguro, el algoritmo es tan bueno que se da cuenta que faltan letras en la sopa y te sobra un apóstrofo después de la Ñ y pegado a la S. Es un algoritmo mentalista.
ResponderEliminarZ, O, L, O, E, L, N, A, D, E, R, O, T, S, K
ResponderEliminarT, A, M, S, D, F, G, H, J, K, L, O, P, U, I
R, A, A, L, I, N, E, A, C, I, O, N, X, Y, S
A, Z, R, Q, W, E, N, O, N, C, E, T, R, T, E
P, A, G, I, N, A, C, P, S, E, C, V, B, N, C
I, G, E, R, E, T, A, R, A, M, S, S, E, M, C
G, H, N, T, S, C, B, E, E, G, E, T, O, P, I
U, A, M, I, N, T, E, R, L, I, N, E, A, D, O
A, L, N, A, C, A, Z, A, S, E, R, A, C, L, N
R, O, B, V, B, R, A, L, U, E, S, E, C, A, B
D, P, T, A, X, P, D, F, K, J, T, N, T, Z, E
A, O, R, A, D, A, O, L, P, A, S, G, I, F, B
R, U, I, L, A, C, Z, F, O, R, N, U, R, G, U
N, M, U, L, T, I, N, I, V, E, L, N, I, N, C
L, A, P, I, V, W, Q, R, T, Y, U, I, O, O, N
ResponderEliminarC O M E R C I A N T E S X C T T A W S E M A J
A E T R O P S N A R T A D N A L O H C I V B K
P A S D F F G H J K E Z X C R E V B N A F J L
I Q E M N B V C X Z L A S O L D B E L G I C A
T Z N X A N O R E C A F T O S Q R S D F Ñ P I
A P E Q D Ñ Y T R E R O R A D I F G H T Y U R
L M R S A N I U Q A M T C O A G H L I T X E T
I A G X M O X C V F E S T A D O S U N I D O S
S D I C S Q H W E P C A S D D F R G T H J I U
M G A V M A F C A S A D F O L L O R R A S E D
O A E U I E C X U Z N F E R R O C A R R I L N
X Ñ L F T X C I S A I N D U S T R I A S F A I
A A E A H O F O R X C P O I E L H R A F V I N
I T C G R F M G N B O S Ñ L E T Ñ R Z E X N O
S E T F A R S O D O A R E V R S O C G P X A I
E R R B R D E O V C M F I O Y T S A R Z C M C
U B I T D A R T Z I O I C Q O A C E X O D E U
G N C H F R N E A N L Y A M U I K R L T P L L
R A A Ñ E R T C O L R D O H O E J N S D F A O
U R L I S D F G I N G C E N D G Z S H A D G V
B G H X C V B N E A O N A S D F G A P O R U E
H O R N O D E H U L L A I C A R B O N T J Z R