Ver si una determinada configuración de cuadrícula coincide con una determinada receta es simple si codifica la cuadrícula de 3x3 como una cadena y utiliza una coincidencia de expresión regular . Acelerar la búsqueda es un asunto diferente, del que hablaré al final. Siga leyendo para obtener más información.
Paso 1) Codificar la cuadrícula como cadena
Simplemente asigne una identificación de carácter a cada tipo de celda y concatene todo lado a lado en este orden:
123
456 => 123456789
789
Y como un ejemplo más concreto, considere la receta del palo, donde W representa madera y E es una celda vacía (simplemente podría usar un carbón vacío ''):
EEE
WEE => EEEWEEWEE
WEE
Paso 2) Haga coincidir la receta con expresión regular (o cadena. Contiene un poco de procesamiento en los datos)
Continuando con el ejemplo anterior, incluso si movemos la formación, todavía hay un patrón en la cadena (WEEW rellenado por E en ambos lados):
EEW
EEW => EEWEEWEEE
EEE
Entonces, no importa dónde mueva el palo, seguirá coincidiendo con la siguiente expresión regular: /^E*WEEWE*$/
Las expresiones regulares también le permiten realizar el comportamiento condicional que mencionó. Por ejemplo (receta inventada), si desea un pico hecho de hierro o piedra para dar el mismo resultado, es decir:
III SSS
EWE or EWE
EWE EWE
Puede combinar ambos en la expresión regular: /^(III)|(SSS)EWEEWE$/
Los volteos horizontales también se pueden agregar con la misma facilidad (utilizando también el operador |).
Editar: De todos modos, la parte regex no es estrictamente necesaria. Es solo una forma de encapsular el problema en una sola expresión. Pero para el problema de ubicación variable, también podría recortar la cadena de la cuadrícula de cualquier espacio de relleno (o E en este ejemplo) y hacer un String.Contains (). Y para el problema de ingredientes múltiples o las recetas duplicadas, puede manejarlas todas como recetas múltiples (es decir, separadas) con el mismo resultado.
Paso 3) Acelerar la búsqueda
En cuanto a la reducción de la búsqueda, deberá crear una estructura de datos para agrupar las recetas y ayudar con la búsqueda. Tratar la cuadrícula como una cadena tiene algunas ventajas aquí también :
Podría definir la "longitud" de una receta como la distancia entre el primer carácter no vacío y el último carácter no vacío. Un simple Trim().Length()
le daría esta información. Las recetas pueden agruparse por longitud y almacenarse en un diccionario.
o
Una definición alternativa de "longitud" podría ser el número de caracteres no vacíos. Nada más cambia. También podría agrupar recetas por este criterio.
Si el punto número 1 no es suficiente, las recetas también se pueden agrupar por el tipo del primer ingrediente que aparece en la receta. Esto sería tan simple como hacerlo Trim().CharAt(0)
(y evitar que Trim resulte en una cadena vacía).
Entonces, por ejemplo, almacenaría recetas en:
Dictionary<int, Dictionary<char, List<string>>> _recipes;
Y realice la búsqueda como algo así como:
// A string encode of your current grid configuration
string grid;
// Get length and first char in our grid
string trim = grid.Trim();
int length = trim.Length();
char firstChar = length==0 ? ' ' : trim[0];
foreach(string recipe in _recipes[length][firstChar])
{
// Check for a match with the recipe
if(Regex.Match(grid, recipe))
{
// We found a matching recipe, do something with it
}
}