Qu'est-ce que j'ai dans ma poche?

16

Synopsis: recherchez les caractères entourés par MYPOCKET.

Exemple d'entrée

MYPHEIF
YFOCKVH
MBNDEIF
TEUFTMY
ESNDUWP
KBOVUVO
CENWFKC
OPYMTEB

Exemple de sortie

F   
BND 
EUF   
SNDUW 
BOVUV 
ENWF  

Hein? Comment avons-nous obtenu cela en sortie? La "poche" peut parfois être difficile à voir. Cela rendra plus clair:

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

Les lettres en gras indiquent un anneau de caractères connectés orthogonalement les uns aux autres, composé de la chaîne MYPOCKET répétée encore et encore. Votre programme devrait sortir les caractères qui se trouvent dans cet anneau.

Remarques:

  • Il n'y aura qu'une "poche".
  • Les nouvelles lignes ou espaces de fin après les lignes sont autorisés.
  • Le reste de la grille peut également contenir des caractères de MYPOCKET, mais pas d'une manière qui rend ambiguë la forme de l'anneau.
  • le M n'est pas toujours dans le coin supérieur droit.
  • La «poche» peut se déplacer dans le sens horaire ou antihoraire.
  • La "poche" ne se déplacera pas dans les directions diagonales - c'est-à-dire que chaque lettre est connectée à gauche, à droite, en haut ou en bas à la suivante.

Voici une autre entrée avec laquelle vous pouvez tester votre programme.

Exemple d'entrée

EKCYMOPD
KCOPHAYM
EKNDSEST
JETHACKE
KRMYPOBN

Exemple de sortie

  HA
NDSES
 HA
Absinthe
la source
14
Qu'a-t-il dans ses petites poches désagréables?
Poignée de porte
Était-ce inspiré par ce défi d'Anarchy Golf?
xnor
@xnor Non, ce n'était pas le cas. (Bien qu'il soit quelque peu similaire ...)
absinthe

Réponses:

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

Utilisation: enregistrez sous pocket.pl et exécutez avec:

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

J'ai opté pour une fonction récursive pour forcer brutalement le chemin, ce qui n'était peut-être pas le meilleur, mais c'était la première approche que j'ai envisagée.

Bien que cela fonctionne pour les deux cas de test actuels, il y a quelques mises en garde:

  • il comprend des espaces de tête (que je n'ai pas vu mentionnés dans les règles ...); et
  • cela ne fonctionnera certainement pas avec une «poche» qui contient des caractères au milieu (disons en forme de U ou similaire).

Je veux continuer à travailler là-dessus, mais je voulais montrer qu'il y a un intérêt pour la question! Heureux de documenter mon processus si utile.

Dom Hastings
la source
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:]])

Fonctionne comme un programme (mise sur une fonction récursive) et accepte les entrées de stdin.
Démo ici.
Le tester ( ex1.txtet ex2.txtsont les exemples de la question) -

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

Version non golfée avec commentaires -

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])

Faites-moi savoir si j'ai fait quelque chose de stupide ou si quelque chose peut être mieux fait.
Je sais que c'est long, mais c'est le mieux que je puisse faire: P

Kamehameha
la source
Eh, je suis tellement mauvais en Python que je l'aurais probablement brutalisé // Je n'ai aucune connaissance des lambdas en Python ... // mais une bonne solution! Encore mieux que rien.
Kurousagi