Encuentra el mejor movimiento inmediato en un juego de "match-3"

11

Su desafío hoy es tomar aportaciones como esta:

fbcfbee
ffcabbe
debceec
bccabbe
edcfbcd
daeaafc
eebcbeb

Y produzca el mejor movimiento posible en un juego tipo Bejeweled que coincidirá con tres o más letras, como esta (tenga en cuenta la capital By C):

fbcfbee
ffcabbe
deBCeec
bccabbe
edcfbcd
daeaafc
eebcbeb

Especificaciones completas:

  • La entrada será nlíneas de nletras minúsculas cada una (donde npodría haber cualquier número).
  • La salida será el mejor movimiento que podrías hacer en un juego de combinar 3, con las dos letras que deseas intercambiar en mayúscula.
  • Las coincidencias deben tener la siguiente prioridad (en estos ejemplos, .indica un cuadrado que no importa):

    1. Cinco en una fila

      xxYxx
      ..X..
      
    2. Roto cinco en una fila

      X..
      Yxx
      x..
      x..
      

      o

      .X.
      xYx
      .x.
      .x.
      
    3. Cuatro en fila

      xYxx
      .X..
      
    4. Tres consecutivos

      xYx
      .X.
      

    Debe encontrar la coincidencia de la prioridad más alta y generarla.

  • Si hay varias coincidencias con la misma prioridad, puede generar cualquiera de ellas.
  • Siempre habrá al menos una coincidencia (su programa puede interrumpirse si no hay coincidencias o hacer lo que quiera).
  • La E / S puede estar en cualquier formato razonable (stdin / out, lectura y escritura de archivos, argumentos de función / valores de retorno, cuadros de diálogo, etc.) pero NO codificado (como x="[insert input here]").
  • Este es el por lo que el código más corto en bytes gana. Si utiliza algún acceso a la red por algún motivo, todos los bytes descargados de la red cuentan para su puntaje.
Pomo de la puerta
fuente
1
+1, pero protesto por el título; podría haber un mejor movimiento. Por ejemplo, uno que crea dos cinco, o uno que causa una caída para crear más cosas.
Justin
¿El cinco en raya roto también cubre ..x.\nxxYX\n..x.?
Peter Taylor
@ Peter Sí, lo hace.
Pomo de la puerta
Hay 2 patrones rotos de 5 en fila: el patrón L y el patrón T. ¿Requiere que ambos coincidan?
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@nhahtdh Sí, editaré para aclarar eso.
Pomo de la puerta

Respuestas:

2

Python3.4, 772

(Usando pestañas para sangría, en lugar de espacios).

import sys,itertools as I
B=[]
for l in sys.stdin:
    l=l.rstrip()
    B.append(list(l))
Z=len(B[0])
F=T=None
R=range
N=min
X=max
P=I.product
S=0
def C(I,J,K,L):
    global F,T,S
    if K<0 or K>=Z or L<0 or L>=Z: return
    B[I][J],B[K][L]=B[K][L],B[I][J]
    h=v=1
    m=B[K][L]
    for i in R(K+1,N(Z,K+5)):
        if B[i][L]!=m:break
        v+=1
    for i in R(K-1,X(0,K-5),-1):
        if B[i][L]!=m:break
        v+=1
    for j in R(L+1,N(Z,L+5)):
        if B[K][j]!=m:break
        h+=1
    for j in R(L-1,X(0,L-5),-1):
        if B[K][j]!=m:break
        h+=1
    c=X(h,v)*2
    if N(h,v)>=3:c+=N(h,v)
    if c>S:S=c;F=I,J;T=K,L
    B[I][J],B[K][L]=B[K][L],B[I][J]
for i,j in P(reversed(R(Z)),R(Z)):
    for d,e in (1,0),(0,-1),(0,1),(-1,0):
        C(i,j,i+d,j+e)
for i,j in P(R(Z),R(Z)):
    c=B[i][j]
    if (i,j)in(F,T):c=c.upper()
    print(c,end=('',"\n")[j==Z-1])
Austin Hastings
fuente
En lugar de [c for c in l], podrías simplemente hacer list(l).
Pomo de la puerta
Use (i, j) en (F, T) en lugar de dos comparaciones - 778
Austin Hastings
F = (i, j) -> F = i, j. Desglobalizar 2 r / o syms - 770
Austin Hastings
Error solucionado: broken-5 no debería vencer a true-5.
Austin Hastings