¿Qué tengo en mi bolsillo?

16

Sinopsis: Buscar caracteres encerrados por MYPOCKET.

Entrada de ejemplo

MYPHEIF
YFOCKVH
MBNDEIF
TEUFTMY
ESNDUWP
KBOVUVO
CENWFKC
OPYMTEB

Salida de ejemplo

F   
BND 
EUF   
SNDUW 
BOVUV 
ENWF  

¿Eh? ¿Cómo lo conseguimos como salida? El "bolsillo" a veces puede ser difícil de ver. Esto lo hará más claro:

MYP HEIF
 Y F OCK VH
 M BND E IF
 T EUF TMY 
E SNDUW P 
K BOVUV O 
C ENWF KC 
OPYMTE B

Las letras en negrita indican un anillo de caracteres conectados ortogonalmente entre sí que consiste en la cadena MYPOCKETrepetida una y otra vez. Su programa debería mostrar los caracteres que están dentro de ese anillo.

Notas:

  • Solo habrá un "bolsillo".
  • Trailing nuevas líneas o espacios después de que se permitan las líneas.
  • El resto de la cuadrícula también puede contener caracteres de MYPOCKET, pero no de una manera que haga que la forma del anillo sea ambigua.
  • El Mno siempre está en la esquina superior derecha.
  • El "bolsillo" puede moverse en sentido horario o antihorario.
  • El "bolsillo" no se moverá en direcciones diagonales, es decir, cada letra está conectada a la izquierda, derecha, arriba o abajo a la siguiente.

Aquí hay otra entrada con la que puede probar su programa.

Entrada de ejemplo

EKCYMOPD
KCOPHAYM
EKNDSEST
JETHACKE
KRMYPOBN

Salida de ejemplo

  HA
NDSES
 HA
Ajenjo
fuente
14
¿Qué tiene en sus pequeños bolsillos desagradables?
Pomo de la puerta
¿Fue esto inspirado por este desafío de Anarchy Golf?
xnor
@xnor No, no lo fue. (Aunque es algo similar ...)
ajenjo

Respuestas:

1

Perl 5, 414

map{$y=0;push@{$h{$_}},[$-,$y++]for@$_;$-++}@l=map[/./g],<>;sub n{($a,$b,$c,$d)=@_;$a==$c&&1==abs$b-$d||$b==$d&&1==abs$a-$c}sub c{my($x,$y,$n)=@_;for(grep{($f=defined$x)?n$x,$y,@$_:1}@{$h{(MYPOCKET=~/./g)[$n%8]}}){($m,$l)=@$_ if!$f;return@r=([@$_],@r)if$n>2&&n(@$_,$m,$l)||c(@$_,$n+1)}''}c;$l[$_->[0]][$_->[1]]=$" for@r;($l[$_]=join'',@{$l[$_]})=~s/^(\w+)\s|\s(\w+)$/$"x($1||$2)=~y%%%c/eg for 0..@l;print join$/,@l

Uso: guardar como pocket.pl y ejecutar con:

perl pocket.pl <<< '<grid>'

Fui por una función recursiva para forzar el camino con fuerza bruta, que podría no haber sido el mejor, pero fue el primer enfoque que consideré.

Si bien funciona para los dos casos de prueba actuales, hay algunas advertencias:

  • incluye espacios iniciales (que no vi mencionado en las reglas ...); y
  • definitivamente no funcionará con un 'bolsillo' que contenga caracteres en el medio (digamos en forma de U o similar).

Quiero seguir trabajando en esto, ¡pero quería mostrar que hay interés en la pregunta! Feliz de documentar mi proceso si es útil.

Dom Hastings
fuente
5

Python 2.7 571 542 509

import sys
o,l,v,k,w="MYPOCKET",[list(e)for e in sys.stdin],[],enumerate,len
def f(z,q,t):
 for r,c in(z,q+1),(z,q-1),(z+1,q),(z-1,q):
  if w(l)>r>=0 and 0<=c<w(l[r])and o[t]==l[r][c]:
    v.append((r,c))
    if f(r,c,(t+1)%w(o)):return 1
    else:v.pop()
 if z==1 and(0,q)in v or z==0 and(z,q+1)in v:return 1
for i,x in k(l[0]):
 v=[(0,i)]
 if x==o[0]and f(0,i,1):break
for i in range(1,w(l)-1):b=[y for x,y in sorted(v)if x==i];print"".join(["".join(e)if w(e)>0 else" "for e in[l[i][b[j-1]+1:y]for j,y in k(b)][1:]])

Funciona como un programa (contando con una función recursiva) y aceptando aportes de stdin.
Demostración aquí.
Probándolo ( ex1.txty ex2.txtson los ejemplos de la pregunta):

$ python pockets.py < ex1.txt
F
BND
EUF
SNDUW
BOVUV
ENWF
$ python pockets.py < ex2.txt 
  HA 
NDSES
 HA  

Versión sin golf con comentarios:

s="""
EKCYMOPD
KCOPHAYM
EKNDSEST
JETHACKE
KRMYPOBN
"""
li2=[list(e.strip()) for e in s.split("\n") if e.strip()!='']
buf=[]
def find_precious(row, col, c_ind):
    for r,c in[(row,col+1),(row,col-1),(row+1,col),(row-1,col)]:
        if len(li2)>r>=0 and 0<=c<len(li2[r]) and seq[c_ind]==li2[r][c]:
            if (r,c)in buf:return True
            buf.append((r,c))
            if find_precious(r,c,(c_ind+1)%len(seq)):return True
            else:buf.pop()
    if row==1 and (row-1,col) in buf or row==0 and (row,col+1) in buf:return True
    return False

for i,x in enumerate(li2[0]):
    if x==seq[0]:
        buf=[(0,i)]
        if find_precious(0,i,1):break
if len(buf)==1:
    exit("Failed")

#Calculate the middle men
for i in range(1,len(li2)-1):
    b=[y for x,y in sorted(buf)if x==i]
    print "".join(["".join(e)for e in [li2[i][b[j-1]+1:y]for j,y in enumerate(b)][1:]if len(e)>0])

Avíseme si hice algo estúpido o algo se puede hacer mejor.
Sé que es muy largo, pero es lo mejor que puedo hacer: P

Kamehameha
fuente
Eh, soy tan malo en Python que probablemente la fuerza bruta // No tengo ningún conocimiento de lambdas en Python ... // ¡pero buena solución! Aún mejor que ninguno.
Kurousagi