wordsearch maker education answers string language-agnostic code-golf rosetta-stone

string - education - word puzzle maker



Code Golf: Word Search Solver (7)

Python: 491 - 353 caracteres

Todavía hay bastante espacio para mejorar, supongo, todos los comentarios son bienvenidos.

Estrategia: encontrar todas las apariciones de la primera letra y luego tratar de buscar la palabra en todas las direcciones.

import sys;r=range(-1,2);k=''''.join;q="row %s, column %s" a=[l[:-1:2]for l in sys.stdin] b=sys.argv[1];c=len(a[0]) for x,y in[(x/c,x%c)for x,h in enumerate(k(map(k,a)))]: for i,j in[(i,j)for i in r for j in r if i or j<>0]: if k([a[x+z*i][y+z*j]for z in range(len(b))if 0<=x+z*i<c and 0<=y+z*j<len(a)])==b:print q%(x+1,y+1)+" --> "+q%(x+z*i+1,y+z*j+1)

Ejemplo de uso:

cat input.txt | python test.py CODEGOLF

Ejemplo de salida:

fila 12, columna 8 -> fila 5, columna 1

Nota: Este es mi primer desafío / pregunta de Code Golf, por lo que podría no estar usando el formato correcto a continuación. No estoy realmente seguro de cómo etiquetar esta pregunta en particular, ¿y debería ser esto una wiki comunitaria? ¡Gracias!

¡Este desafío de Code Golf consiste en resolver búsquedas de palabras!

Una búsqueda de palabras, como lo define Wikipedia, es:

Un juego de palabras que es letras de una palabra en una cuadrícula, que generalmente tiene una forma rectangular o cuadrada, es un juego de palabras que consiste en letras de una palabra en una cuadrícula. El objetivo de este rompecabezas es encontrar y marcar todas las palabras escondidas dentro de la caja. Las palabras pueden ser horizontal, vertical o diagonal. A menudo se proporciona una lista de las palabras ocultas, pero los rompecabezas más desafiantes pueden permitir que el jugador los descubra. Muchos rompecabezas de búsqueda de palabras tienen un tema con el que se relacionan todas las palabras ocultas.

Las búsquedas de palabras para este desafío serán todas cuadrículas rectangulares con una lista de palabras que se encontrarán. Las palabras se pueden escribir verticalmente, horizontalmente o diagonalmente .

De entrada y salida

El usuario ingresa su búsqueda de palabras y luego ingresa una palabra que se encuentra en su cuadrícula. Estas dos entradas pasan a la función que va a escribir. Depende de usted cómo desea declarar y manejar estos objetos.

Usando una estrategia descrita a continuación o una propia, la función encuentra la palabra específica en la búsqueda y genera sus coordenadas iniciales (simplemente el número de fila y el número de columna) y las coordenadas finales. Si encuentra dos apariciones de la palabra, debe dar salida a ambos conjuntos de coordenadas. Si la palabra es un palíndromo, puede elegir arbitrariamente un extremo para que sea el "comienzo" de la palabra.

Ejemplo

Entrada:

A I Y R J J Y T A S V Q T Z E X B X G R Z P W V T B K U F O E A F L V F J J I A G B A J K R E S U R E P U S C Y R S Y K F B B Q Y T K O I K H E W G N G L W Z F R F H L O R W A R E J A O S F U E H Q V L O A Z B J F B G I F Q X E E A L W A C F W K Z E U U R Z R T N P L D F L M P H D F W H F E C G W Z B J S V O A O Y D L M S T C R B E S J U V T C S O O X P F F R J T L C V W R N W L Q U F I B L T O O S Q V K R O W G N D B C D E J Y E L W X J D F X M

Palabra para encontrar: codegolf

Salida:

row 12, column 8 --> row 5, column 1

Estrategias

Aquí hay algunas estrategias que podría considerar usar. Depende de usted decidir qué estrategia desea utilizar; no tiene que estar en esta lista

  • Buscando la primera letra de la palabra; en cada aparición, mire las ocho letras circundantes para ver si la siguiente letra de la palabra está allí.
  • Igual que el anterior, excepto buscar una parte de una palabra que tenga dos de la misma letra una al lado de la otra.
  • Contando la frecuencia con que cada letra del alfabeto está presente en toda la cuadrícula, luego seleccione una de las letras que menos ocurren de la palabra que tiene que encontrar y busque la letra. Cada vez que aparece la letra, observa sus ocho letras circundantes para ver si las letras siguientes y anteriores de la palabra están allí.

C ++ C, 411 400 388 367 caracteres

Mi primer intento en un código de golf.

#include<stdio.h> main(){char m[999],w[99];int r,c,l=-1,x=-1,y=-1,i=0,j,k;scanf("%s %d %d" ,w,&r,&c);for(;w[l+1];++l);for(;i<r*c;scanf("%s",&m[i++]));for(;y<2;++y) for(;x<2;++x)if(x|y)for(i=(y<0)*l;i<r-(y>0)*l;++i)for(j=(x<0)*l;j<c-(x>0 )*l;++j)for(k=0;k<=l&&w[k++]==m[(i+k*y)*c+j+k*x];)k>l?printf( "row %i, column %i --> row %i, column %i/n",i+1,j+1,i+y*l+1,j+x*l+1):0;}

Se compila sin advertencias en gcc sin banderas adicionales.

Aquí está la versión con espacios en blanco:

#include<stdio.h> main() { char m[999], w[99]; int r, c, l = -1, x = -1, y = -1, i = 0, j, k; scanf("%s %d %d", w, &r, &c); for (; w[l+1]; ++l); for (; i < r*c; scanf("%s", &m[i++])); for (; y < 2; ++y) for (; x < 2; ++x) if (x | y) for (i = (y<0) * l; i < r - (y>0) * l; ++i) for (j = (x<0) * l; j < c - (x>0) * l; ++j) for (k = 0; k <= l && w[k++] == m[(i+k*y) * c + j+k*x];) k > l ? printf("row %i, column %i --> row %i, column %i/n", i + 1, j + 1, i + y*l + 1, j + x*l + 1) : 0; }

La entrada esperada en stdin se ve como:

CODEGOLF 15 15 A I Y R J J Y T A S V Q T Z E X B X G R Z P W V T B K U F O ...

donde 15 15 son los números de filas y columnas, respectivamente.

Como esta es mi primera ronda de golf, y puedo encontrar preciosos trucos comunes en la web, enumeraré algunos de los que encontré:

  • Intente mantener los cuerpos de los bucles en una sola frase para guardarlos en los bigotes (2 caracteres).
    Ejemplo : cualquier cosa usando el operador de coma.

  • Use una expresión condicional ( ?: lugar de una if cuando pueda (1 carácter).
    Ejemplo : en lugar de if(x)printf(""); , escribe x?printf(""):0; . Esto funciona porque printf devuelve int .

  • Utilice el hecho de que los valores booleanos son 0 o 1 cuando se usan como int (? Chars).
    Ejemplo : en lugar de (y>0?rl:r) , escriba r-(y>0)*l . Los ahorros aquí están entre paréntesis, que fueron necesarios en esta situación.

  • while bucles nunca son más cortos que los bucles, y son más largos la mayor parte del tiempo (> = 0 caracteres).
    Ejemplo : while(x)y; es tan largo como for(;x;y); pero con for obtener el cuerpo del bucle para jugar también, sin pagar por el extra ; .

  • Ponga sus incrementos de bucle en la última expresión que usa el contador de bucles (1 carácter).
    Ejemplo : en lugar de for(;x<b;++x)printf("%i",x); , escriba for(;x<b;)printf("%i",x++); .

  • Deje fuera el tipo de retorno main (4 caracteres).

  • Deje fuera de la declaración de return main (9 caracteres).

  • Uso & y | en lugar de && y || siempre que sea posible (1 char).
    Ejemplo : en lugar de if(x||y) , escribe if(x|y) . Esto solo funciona si no depende del comportamiento de cortocircuito de && y || .

  • strlen función strlen y elimine #include<string.h> (11 caracteres).

Si no te importan las advertencias del compilador:

  • No incluya ningún encabezado (muchos caracteres).

AWK - 252 255

NF<2{l=split($1,w,"")}NF>1{for(i=1;i<=NF;)t[x=i++,y=NR]=$i}END{ for(i=1;i<=x;++i)for(j=0;++j<=y;)for(a=0;a<9;++a)if(t[I=i,J=j]==w[1]) for(k=1;k<l;){if(!(T=t[I+=int(a/3)-1,J+=a%3-1])||T!=w[++k])break;if(k==l) print"row "j (B=", column ")i" --> row "J B I}}

La entrada debe estar en la forma

.... B L T O O S Q V K R O W G N D B C D E J Y E L W X J D F X M CODEGOLF


Perl - 243

(No incluye saltos de línea, todos los cuales son opcionales)

El código de mayoría de golf se puede encontrar here .

$/="";@w=split//,pop;($b=<>)=~y/ //d;$W=1+index$b,"/n"; for(1,2){for(0,$W-2..$W){$p=join"."x$_,@w; push@m,[$-[0],$+[0]-1]while$b=~/$p/sg} @w=reverse@w;@m=map[reverse@$_],@m} $t="row %d, column %d"; printf"$t --> $t/n",map{1+$_/$W,1+$_%$W}@$_ for@m;

Uso: ejecutar como un script. Ya sea wordsearch.pl boardfile searchword para leer de un archivo, o wordsearch.pl searchword para leer la tabla de STDIN (hey, pop son dos caracteres más cortos que shift !)

La idea es que leemos el tablero en una cadena (tirando los espacios adicionales entre las letras), y también tomamos nota de su ancho (contando los caracteres hasta la primera línea). Luego hacemos una serie de coincidencias de expresiones regulares para encontrar la palabra, usando el modificador de expresiones regulares s para permitir que una coincidencia abarque las líneas. Dada una tabla que tiene 4 letras de ancho (por lo que cada línea tiene 5 caracteres, incluida la línea nueva), y la palabra de búsqueda "CAR", podemos hacer que los patrones /CAR/ coincidan hacia adelante, /C...A...R/ para el partido va hacia el sudoeste, /C....A....R/ para hacer coincidir hacia abajo, y /C.....A.....R/ para el partido hacia el sureste. Para cada partido, registramos las posiciones de inicio y final del partido.

Luego revertimos la palabra de búsqueda ("CAR" -> "RAC") y lo hacemos de nuevo, lo que nos permite hacer coincidir la palabra que va hacia la izquierda, hacia arriba, hacia el noroeste y hacia el noreste. Por supuesto, queremos asegurarnos de que las posiciones de inicio / final también se intercambien. Para guardar el código, cambio las posiciones de coincidencia dos veces ; las coincidencias para la palabra hacia adelante se intercambian ambas veces (por lo que salen sin cambiar), mientras que las coincidencias para la palabra hacia atrás solo se intercambian una vez, por lo que saldrán intercambiadas.

Finalmente, solo es cuestión de tomar las compensaciones de coincidencia en la cadena de la placa y convertirlas en pares de filas / columnas, y de formatear la salida de la forma en que el problema lo desea.


Perl, 226 char

sub h($){"row ",$%=1+($x=pop)/$W,", column ",1+$x%$W} @S=map/[^ ]/g,<STDIN>; B:for(@ARGV){ for$d(map{$_,-$_}1,$W=@S/$.,$W-1,$W+1){ A:for$s(0..$#S){ $t=$s-$d;for(/./g){next A if$S[$t+=$d]ne$_||$t<0} print h$s,'' --> '',h$t,$/; next B }}}

El recuento de caracteres excluye las líneas nuevas y la sangría, que se incluyen para facilitar la lectura. Supongo que la matriz de letras se especifica con entrada estándar y que las palabras de destino son argumentos de línea de comando.

La primera línea (después de la definición de sub h ) asigna todos los caracteres que no son espacios en una sola matriz @S . Luego itere sobre todas las palabras de destino, sobre las posibles direcciones en que pueden aparecer las palabras ( $W es el ancho del rompecabezas) y sobre todas las letras de la palabra de destino actual hasta que se encuentre una coincidencia.

$ perl wordsearch.pl CODEGOLF RACECAR BYKLHQU <<EOF A I Y R J J Y T A S V Q T Z E X B X G R Z P W V T B K U F O E A F L V F J J I A G B A J K R E S U R E P U S C Y R S Y K F B B Q Y T K O I K H E W G N G L W Z F R F H L O R W A R E J A O S F U E H Q V L O A Z B J F B G I F Q X E E A L W A C F W K Z E U U R Z R T R A C E C A R P H D F W H F E C G W Z B J S V O A O Y D L M S T C R B E S J U V T C S O O X P F F R J T L C V W R N W L Q U F I B L R A C E C A R R O W G N D B C D E J Y E L W X J D F X M EOF row 12, column 8 --> row 5, column 1 row 14, column 3 --> row 14, column 9 row 3, column 12 --> row 9, column 6


Python - 186 caracteres

def f(g,W):w=g.find("/n")+1;L=len(W);print" --> ".join("row %s, column %s"%(x/w+1 ,x%w+1)for i in range(len(g))for j in(-w-1,-w,-w+1,-1,1,w-1,w,w+1)for x in(i,i+(L -1)*j)if g[i::j][:L]==W)

código de prueba:

grid="""A I Y R J J Y T A S V Q T Z E X B X G R Z P W V T B K U F O E A F L V F J J I A G B A J K R E S U R E P U S C Y R S Y K F B B Q Y T K O I K H E W G N G L W Z F R F H L O R W A R E J A O S F U E H Q V L O A Z B J F B G I F Q X E E A L W A C F W K Z E U U R Z R T N P L D F L M P H D F W H F E C G W Z B J S V O A O Y D L M S T C R B E S J U V T C S O O X P F F R J T L C V W R N W L Q U F I B L T O O S Q V K R O W G N D B C D E J Y E L W X J D F X M """.lower().replace(" ","") f(grid,"codegolf") f(grid,"serverfault") f(grid,"superuser")

Esta versión tiene 196 caracteres y acepta la cuadrícula sin realizar ningún ajuste adicional

def f(g,W):w=g.find("/n")+1;L=len(W);print" --> ".join("row %s, column %s"%(x/w+1,x%w/2+1)for i in range(len(g))for j in(-w-2,-w,-w+2,-2,2,w-2,w,w+2)for x in(i,i+(L-1)*j)if g[i::j][:L].lower()==W)

código de prueba:

grid="""A I Y R J J Y T A S V Q T Z E X B X G R Z P W V T B K U F O E A F L V F J J I A G B A J K R E S U R E P U S C Y R S Y K F B B Q Y T K O I K H E W G N G L W Z F R F H L O R W A R E J A O S F U E H Q V L O A Z B J F B G I F Q X E E A L W A C F W K Z E U U R Z R T N P L D F L M P H D F W H F E C G W Z B J S V O A O Y D L M S T C R B E S J U V T C S O O X P F F R J T L C V W R N W L Q U F I B L T O O S Q V K R O W G N D B C D E J Y E L W X J D F X M """ f(grid,"codegolf") f(grid,"serverfault") f(grid,"superuser")


Python, 318 golpes.

from itertools import* f=lambda x,y,i,j,n:(x-i+1,y-j+1)*(not n)or all((2*i+j,x+1,y+1,x<c,y<d))and a[x][y*2]==n[0]and f(x+i,y+j,i,j,n[1:]) w=raw_input a=list(iter(w,'''')) c=len(a) d=len(a[0])/2 r=range z=r(-1,2) s=''row %d, column %d'' for x in product(r(c),r(d),z,z,[w()]): if f(*x):print s%(x[0]+1,x[1]+1),''-->'',s%f(*x) Ejemplo de entrada:

A I Y R J J Y T A S V Q T Z E X C O D E G O L F B K U F O Z E A F L V F J J I A G B A J K R E S U R E P U S C Y R S Y K F B B Q Y T K O I K H E W G N G L W Z F R F H L O R W A R E J A O S F U E H Q V L O A Z B J F B G I F Q X E E A L W A C F W K Z E U U R Z R T N P L D F L M P H D F W H F E C G W Z B J S V O A O Y D L M S T C R B E S J U V T C S O O X P F F R J T L C V W R N W L Q U F I B L T O O S Q V K R O W G N D B C D E J Y E L W X J D F X M CODEGOLF

Salida:

$ python wordsearch < wordsearchinput.txt row 2, column 2 --> row 2, column 9 row 12, column 8 --> row 5, column 1

Publicado bajo la licencia "editar-la-respuesta-en lugar de comentar-en-cómo-debería-arreglar-esto".