Escriba una expresión regular que coincida con cualquier solución de sudoku válida y no con ninguna solución de sudoku no válida. La entrada es una versión desenrollada del sudoku, es decir, no hay delimitadores de línea. Por ejemplo, el siguiente tablero:
7 2 5 8 9 3 4 6 1
8 4 1 6 5 7 3 9 2
3 9 6 1 4 2 7 5 8
4 7 3 5 1 6 8 2 9
1 6 8 4 2 9 5 3 7
9 5 2 3 7 8 1 4 6
2 3 4 7 6 1 9 8 5
6 8 7 9 3 5 2 1 4
5 1 9 2 8 4 6 7 3
se daría como:
725893461841657392396142758473516829168429537952378146234761985687935214519284673
Las reglas son probablemente de conocimiento común por ahora, pero por si acaso ... un tablero de sudoku es válido si y solo si:
- Cada fila contiene los dígitos desde
1
hasta9
exactamente una vez. - Cada columna contiene los dígitos desde
1
hasta9
exactamente una vez. - Cada uno de los nueve subcuadrículas 3x3 contenga los dígitos de
1
a9
exactamente una vez.
Reglas
Su respuesta debe consistir en una única expresión regular, sin ningún código adicional (excepto, opcionalmente, una lista de modificadores de expresión regular necesarios para que su solución funcione). No debe usar las características de la expresión regular de su idioma que le permiten invocar código en el idioma de alojamiento (por ejemplo, el e
modificador de Perl ).
Puede usar cualquier sabor regex que existiera antes de este desafío, pero especifique el sabor.
No asuma que la expresión regular está anclada implícitamente. Por ejemplo, si está usando Python, suponga que su expresión regular se usa con re.search
y no con re.match
. Su expresión regular no necesita coincidir con toda la cadena. Solo necesita hacer coincidir al menos una subcadena (que puede estar vacía) para soluciones válidas y no producir coincidencias para soluciones no válidas.
Puede suponer que la entrada siempre será una cadena de 81 dígitos positivos.
Esto es regex golf, por lo que gana la expresión regular más corta en bytes. Si su lenguaje requiere delimitadores (generalmente /.../
) para denotar expresiones regulares, no cuente los delimitadores. Si su solución requiere modificadores, agregue un byte por modificador.
Casos de prueba
Tableros válidos:
123456789456789123789123456231564897564897231897231564312645978645978312978312645
725893461841657392396142758473516829168429537952378146234761985687935214519284673
395412678824376591671589243156928437249735186738641925983164752412857369567293814
679543182158926473432817659567381294914265738283479561345792816896154327721638945
867539142324167859159482736275398614936241587481756923592873461743615298618924375
954217683861453729372968145516832497249675318783149256437581962695324871128796534
271459386435168927986273541518734269769821435342596178194387652657942813823615794
237541896186927345495386721743269158569178432812435679378652914924813567651794283
168279435459863271273415986821354769734692518596781342615947823387526194942138657
863459712415273869279168354526387941947615238138942576781596423354821697692734185
768593142423176859951428736184765923572389614639214587816942375295837461347651298
243561789819327456657489132374192865926845317581673294162758943735914628498236571
243156789519847326687392145361475892724918653895263471152684937436729518978531264
498236571735914628162758943581673294926845317374192865657489132819327456243561789
978531264436729518152684937895263471724918653361475892687392145519847326243156789
341572689257698143986413275862341957495726831173985426519234768734869512628157394
Tableros inválidos:
519284673725893461841657392396142758473516829168429537952378146234761985687935214
839541267182437659367158924715692843624973518573864192298316475941285736456729381
679543182158926473432817659567381294914256738283479561345792816896154327721638945
867539142324167859159482736275398684936241517481756923592873461743615298618924375
754219683861453729372968145516832497249675318983147256437581962695324871128796534
271459386435168927986273541518734269769828435342596178194387652657942813823615794
237541896186927345378652914743269158569178432812435679495386721924813567651794283
168759432459613278273165984821594763734982516596821347615437829387246195942378651
869887283619214453457338664548525781275424668379969727517385163319223917621449519
894158578962859187461322315913849812241742157275462973384219294849882291119423759
123456789456789123564897231231564897789123456897231564312645978645978312978312645
145278369256389147364197258478512693589623471697431582712845936823956714931764825
243561789829317456657489132374192865916845327581673294162758943735924618498236571
243156789529847316687392145361475892714928653895263471152684937436719528978531264
498236571735924618162758943581673294916845327374192865657489132829317456243561789
978531264436719528152684937895263471714928653361475892687392145529847316243156789
342571689257698143986413275861342957495726831173985426519234768734869512628157394
345678192627319458892451673468793521713524986951862347179246835534187269286935714
341572689257698143986413275862341957495726831173985426519234768734869512628517394
Para otros casos de prueba, puede usar este script CJam que toma un tablero válido como entrada y lo baraja aleatoriamente para dar un nuevo tablero válido (formato de entrada irrelevante siempre que contenga solo dígitos y opcionalmente espacios en blanco).
Si su expresión regular es compatible con el sabor .NET, puede probarlo en línea con Retina. Se debe imprimir una solución válida 0
para tableros no válidos y algún número entero positivo para tableros válidos. Para ejecutar todos los casos de prueba a la vez, use esta plantilla e inserte la expresión regular en la segunda línea. Si necesita modificadores de expresiones regulares, anteponga a `
a la expresión regular y coloque las letras modificadoras estándar delante de ella.
fuente
valid boards
?Respuestas:
Ruby regex,
717873 bytesRealmente no conozco a Ruby, pero aparentemente no se queja de los cuantificadores en cascada.
Pruébalo aquí
.NET regex,
797875 o 77 bytesPorque Martin piensa que esto es posible ... Pero supongo que también incorporará estos cambios también.
Requiere una nueva línea final en la entrada para funcionar. No estoy seguro de si se me permite hacer esto (probablemente no).
Pruébalo aquí
La versión sana de 77 bytes:
Gracias Neil por señalar el error en mi versión anterior y jugar golf 1 byte (para el
(...)*
).Pruébalo aquí
PCRE,
7778 bytesSolo por completo.
Pruébalo aquí
Otra versión, también 78 bytes:
Pruébalo aquí
Explicación
fuente
PCRE, 117
119 130 133 147bytesTambién debería funcionar en sabores Python, Java, etc.Ahora con recursividad! Y la función de "recursión" se usa de forma no recursiva para las "subrutinas", que olvidé por completo hasta que tuve que usar la recursión real.fuente
.{27}*
.^(?!(.{27})*(.{9})?(...){0,2}.?.?(.).?.?(?=(...)*$)(.{9})?.{6,8}\4.{0,17}(.{27})*$|.*(.)((.{9})+|((?!(.{9})*$).)+)(<=\8))
(<=\8)
no parece una sintaxis válida (le falta una?
). Además, el único sabor que sé que admite referencias posteriores en lookbehinds es .NET..NET regex, 8339 bytes
Sí, sé que mi solución es muy ingenua, ya que Martin me dijo que lo hizo en 130 bytes. De hecho, la URL para probarlo en línea es tan larga que no pude encontrar un acortador de URL que lo aceptara.
El siguiente enlace no funciona en IE, pero sí funciona en Chrome y Firefox.
Pruébelo en línea : todos los casos de prueba a la vez, con la ayuda de
!`
al principio, no incluidos en el recuento de bytes.Aquí está el script de Python que usé para generarlo (código a continuación):
fuente
.NET regex, 121 bytes
Explicación:
fuente
PCRE, 3579 bytes
Una solución de fuerza bruta absolutamente terrible. Miradas negativas ahoy!
Pasé demasiado tiempo en esto para abandonarlo, así que aquí está, por el bien de la posteridad.
En el lado positivo, si Sudoku de repente comienza a usar un conjunto diferente de 9 caracteres, supongo que esto seguirá funcionando ...
http://pastebin.com/raw/CwtviGkC
No sé cómo operar Retina, pero también puede pegarlo en https://regex101.com o similar y coincidirá.
Código Ruby utilizado para generar la expresión regular:
fuente
Sabor a rubí,
7574 bytesGracias a jimmy23013 por guardar 1 byte.
Pruébalo aquí.
Ahora que finalmente está vencido, puedo compartir mi propia solución. :) Descubrí una técnica de expresiones regulares interesante (¿quizás nueva?) En el proceso (la
(.|(.)){,8}\3
parte), que probablemente sería inmejorable en los casos en que esto no se pueda combinar con otras partes de la expresión regular (como fue el caso en la respuesta de jimmy23013) .Explicación
Al igual que las otras respuestas cortas, estoy usando una búsqueda anticipada negativa que busca duplicados en filas, columnas o bloques. El componente básico de la solución es este:
Tenga en cuenta que
\3
se reutiliza entre tres alternativas diferentes (que utilizan el grupo3
para la detección de duplicados).Ese grupo a la izquierda (que es grupo
2
, que contiene grupo3
) se usa para cualquier posición que pueda contener la primera mitad de un dígito duplicado (dentro de un grupo que no debe contener dígitos duplicados). Entonces,...
es algo que nos lleva a la siguiente posición en la que podría ocurrir dicho dígito (si es necesario) e\3
intenta encontrar la segunda mitad del duplicado mediante referencia inversa. La razón por la que esto funciona es retroceder. Cuando el motor coincide por primera(.|(.))
vez, simplemente se usará.
cada vez y no capturará nada. Ahora el\3
al final falla. Pero ahora el motor intentará usarlo gradualmente en(.)
lugar de.
partidos individuales. Finalmente, si hay un duplicado, encontrará la combinación donde(.)
se utilizó por última vez en el primer dígito del duplicado (de modo que la captura no se sobrescriba más tarde), y luego usa un poco más.
para cerrar la brecha con la referencia inversa. Si hay un duplicado, el rastreo siempre lo encontrará.Veamos las tres partes diferentes donde se usa esto:
Esto busca duplicados en alguna fila. Primero saltamos a cualquier fila con
.{9}*
. Luego emparejamos hasta 8 caracteres (es decir, cualquier cosa en esa fila, excepto el último dígito) utilizando la captura duplicada opcional e intentamos encontrar la\3
siguiente.Esto busca duplicados en alguna columna. Primero, tenga en cuenta que
\g<2>
es una llamada de subrutina, por lo que es lo mismo que:donde los dos grupos que acabamos de insertar todavía se conocen como
2
y3
.Aquí,
.*
simplemente salta todo lo que sea necesario (sería suficiente hacer coincidir hasta 8 caracteres aquí, pero eso cuesta más bytes). Luego, el grupo externo coincide con una fila completa (que puede ajustarse en dos filas físicas) a la vez, opcionalmente capturando el primer carácter. Se\3
buscará justo después de esto, lo que garantiza la alineación vertical entre la captura y la referencia inversa.Finalmente, revisando los bloques:
Nuevamente,
\g<2>
es una llamada de subrutina, por lo que es lo mismo que:Para verificar los bloques, tenga en cuenta que dado que ya hemos verificado todas las filas y columnas, solo necesitamos verificar cuatro de los bloques 3x3. Cuando sabemos que todas las filas y columnas, así como estos bloques 3x3 son correctos:
Entonces sabemos que no puede haber duplicados en los bloques restantes. Por lo tanto, solo estoy revisando estos cuatro bloques. Además, tenga en cuenta que no tenemos que buscar duplicados dentro de la misma fila de un bloque 3x3. Es suficiente encontrar la primera mitad del duplicado en una fila y buscar la segunda mitad en una fila más abajo.
Ahora, para el código en sí, primero saltamos al comienzo de uno de los cuatro bloques con
.{27}?.{3}?
(opcionalmente salteamos tres filas, opcionalmente salteamos tres columnas). Luego intentamos hacer coincidir hasta dos de las filas del bloque 3x3 con el mismo truco que usamos para las filas anteriores:Permitimos, pero no requerimos, capturar ninguna de las 3 celdas en la fila actual del bloque 3x3 y luego saltar a la siguiente fila con
.{6}
. Finalmente, tratamos de encontrar un duplicado en cualquiera de las 3 celdas de la fila en la que terminamos:Y eso es.
fuente
^(?!(.*((.|(.)).{8})*|.{9}*\g<3>{,8}|.{27}?.{3}?(\g<3>{3}.{6}){,2}.?.?)\4)
:; 73:^(?!(.*((.|(.)|\4()).{8})*|.{9}*\g<3>{9}|.{27}?.{3}?(\g<3>{3}.{6}){3})\5)
.\4()
truco en una versión anterior para los bloques de 3x3, pero terminé por deshacerme de él, porque era más largo. : D341572689257698143986413275862341957495726831173985426519234768734869512628517394
Javascript regex,
532530481463 caracteresValidar filas:
Validar columnas:
Valide la casilla desde su primer carácter:
Establecer vista previa al inicio del cuadrado:
Y toda la expresión:
Coincide con toda la cadena.
Prueba en Javascript ES6:
fuente
.
aparece entre(.{9})
paréntesis debido a lo siguiente{0,8}
. ¿Por qué crees que las columnas deberían ser más cortas?