Desbloqueando los secretos de un laberinto unidimensional

41

Fondo

¡Despierta para encontrarse perdido en un laberinto unidimensional! Aparece un genio místico (o algo así) y explica que la salida se encuentra frente a usted, pero que entre usted y la salida hay una serie de desafíos. A medida que avanzas, te das cuenta de que todos los llamados desafíos son simplemente puertas cerradas. Primero ve una puerta con un orificio para llave en forma de T, y al no tener esa llave usted mismo, vuelva sobre sus pasos, buscando una llave con Tforma.

Frustrado, encuentras una sopa de llaves del alfabeto en el suelo, ninguna de las cuales coincide con la puerta que has encontrado. Por algún golpe de genio (o idiotez), decides que la ttecla en forma de minúscula podría caber en la ranura si la atascas con suficiente fuerza. Cuando te acercas a la puerta con la tllave en minúscula en la mano, el Tagujero se ilumina en verde y la puerta se disuelve frente a ti.

Uno menos, quedan muchos más ...

Reto

El objetivo de este desafío es marcar cuántos pasos te lleva salir del laberinto.

La entrada de este desafío es el laberinto: una cadena que contiene solo caracteres [A-Za-z^$ ]. Glosario:

  • ^- El espacio de inicio. La entrada contendrá exactamente uno ^.
  • $- La salida (¡libertad!). La entrada contendrá exactamente uno $.
  • [A-Z]- Las letras mayúsculas significan puertas. Solo puede pasar por esta puerta si ya ha recogido la clave requerida.
  • [a-z]- Las letras minúsculas significan claves. Recoge estas llaves caminando sobre el espacio que contiene la llave.

Habrá como máximo una de cada letra mayúscula en la entrada. Esto significa que el número total de puertas estará entre 0 y 26 inclusive.

Cada puerta cerrada [A-Z]tendrá exactamente una tecla de minúscula correspondiente [a-z]. Puede haber cualquier número de espacios ( ) en la entrada.

Todas las puertas estarán a la derecha del inicio y a la izquierda de la salida. Por lo tanto, no habrá puertas superfluas. Todas las entradas serán solucionables.

La salida para este desafío será un número, el número de pasos que tomó para salir del laberinto.

Algoritmo

Su enfoque metódico para salir de este miserable lugar es el siguiente:

  • Comience desde el principio ( ^) y avance (derecha) recogiendo las claves que encuentre.
  • Cuando cruzas una puerta, si tienes la llave correcta, avanzas hacia la puerta. Si no tiene la llave correcta, camina hacia atrás (izquierda) recogiendo las llaves que encuentra hasta que encuentra la llave de la puerta más reciente que no pudo abrir.
  • Una vez que recoja la llave de la puerta problemática actual, gire hacia la derecha y continúe.
  • Repita este proceso hasta que salga a la salida ( $).

Los golfistas experimentados entenderán que su código no tiene que implementar este algoritmo específico siempre que genere el mismo resultado que si hubiera ejecutado este algoritmo.

Contando

Cada vez que pasas de un cuadro a otro, eso cuenta como un paso. Girar 180º no implica ningún paso adicional. No puede avanzar hacia una puerta sin la llave requerida. Debes pisar una llave para recogerla, y debes pisar la salida para ganar. Después de su primer movimiento, el espacio de inicio ( ^) se comporta como cualquier otro espacio regular.

Ejemplos

En estos ejemplos, dejé los espacios como subrayados para la legibilidad humana.

Entrada es _a_^_A__$__. La salida es 11. Da un 1paso adelante, nota que no tiene llave para la Apuerta, y luego sobre la cara. Camina hacia atrás hasta que ocupe el espacio que contiene los a( 3pasos hacia atrás, ahora 4total). Luego camina hacia adelante hasta que ocupe el espacio que contiene la salida ( 7pasos hacia adelante, 11total).

Entrada es b__j^__a_AJB_$. La salida es 41: Realiza dos viajes separados a la parte posterior del laberinto, uno para obtener la jclave y el siguiente para obtener la bclave.

Entrada es __m__t_^__x_T_MX_$____. La salida es 44. No hará ningún viaje adicional para obtener la xllave, ya que la recogió en su camino desde el principio hasta la puerta T.

Entrada es g_t_^G_T$. La salida es 12. No puedes moverte al Gespacio sin una llave, e inmediatamente sobre la cara. Tienes la suerte de recoger la tllave en el camino a la gllave, y así abrir ambas puertas en tu camino hacia la libertad.

Entrada es _^_____$. La salida es 6. Eso fue fácil.

Pautas de E / S y criterio ganador

Se aplican las reglas estándar de E / S. Este es un desafío de .

turbulencia también
fuente
17
Además del agradable desafío, me gustaría comentar cuán buenas son la redacción y la explicación
Luis Mendo
44
"Por lo tanto, no habrá puertas superfluas". Creo Aen bA^aB$que no sería superfluo tampoco. ;)
Martin Ender
44
@orlp Estoy más interesado en ver cómo la gente juega golf este algoritmo errante en la oscuridad. Parece trivial hacer la solución óptima de "ir a buscar todas las llaves y luego abrir todas las puertas".
turbulencetoo
2
@PeterTaylor y turbulencetoo No, no lo es, ¿quién puede decir que todas las llaves están en el lado izquierdo y todas las puertas a la derecha? Y las llaves / puertas superfluas también serían interesantes. Sería bastante interesante, ya que significaría resolver un gráfico de dependencia.
orlp
55
Cada puerta tiene una llave. ¿Cada llave tiene una puerta?
user2357112 es compatible con Monica

Respuestas:

3

CJam, 45

1q_'$#<'^/~\W%:A;ee{~32+A#)_T>{:T+2*+}&]0=)}/

Pruébalo en línea

Explicación:

1         initial step count; this 1 is actually for the last step :)
q_'$#<    read the input and only keep the part before the '$'
'^/~      split by '^' and dump the 2 pieces on the stack
\W%:A;    take the first piece, reverse it and store it in A
ee        enumerate the other piece (making [index char] pairs)
{…}/      for each [index char] pair
  ~32+    dump the index and character on the stack, and add 32 to the character;
           uppercase letters become lowercase and other chars become garbage
  A#)     find the index of this character in A and increment it (not found -> 0)
  _T>     check if this index (number of steps from '^' back to the key)
           is greater than T (which is initially 0)
  {…}&    if that's true (we need to go back), then
    :T    store that index in T (keeping track of how far we go back before '^')
    +     add to the other index (from the pair, number of steps we took after '^')
    2*    double the result (going back and forth)
    +     add it to the step count
  ]0=     keep only the first value from the bottom of the stack (step count)
           (if the condition above was false, we'd have 2 extra values)
  )       increment the step count (for the current step)
aditsu
fuente
7

Pyth, 51 bytes

JxQ"^"K-xQ"$"JVQI&}NrG1>JxQrN0=JxQrN0=+K*2t-xQNJ;pK

Sume la distancia entre la puerta y su llave (doblada, para hacer el viaje de ida y vuelta), ignorando las llaves "anidadas" y la distancia desde el principio hasta el final:

JxQ"^"                                              #Initialize the farther point with the starting position
      K-xQ"$"J                                      #Initialize the step counter with the difference between the exit and the start
              VQ                                    #iterate over the input
                I&}NrG1>JxQrN0                      #check if is upper and if the keys is father than one stored (to eliminate nested keys)
                              =JxQrN0               #update the farther key
                                     =+K*2t-xQNJ;   #update step counter with the round trip door<>key
                                                 pK #print the step counter

mismo algoritmo en python2.7:

lab=raw_input()
farther_key=lab.index('^')
steps = lab.index('$') - farther_key
for i in lab:
    if i.isupper():
        if farther_key> lab.index(i.lower()):
            farther_key=lab.index(i.lower())
            steps+=((lab.index(i) - farther_key)-1)*2
print steps
Barra
fuente
5

Python 2, 155 154 134 128 bytes

Editar: ¡Gracias a @ user2357112 y @loovjo por sus comentarios que me ayudaron a eliminar otros 20 26 bytes de mi solución!

def f(l):
 i=l.index;b=i('^');t=i('$')-b
 for d in filter(str.isupper,l):
  k=i(d.lower())
  if k<b:b=k;t+=2*(i(d)-k-1)
 print t
Ken 'Joey' Mosher
fuente
1
Puede combinar la segunda y tercera línea con un punto y coma, ahorrando un byte. Además, la variable i parece innecesaria en el bucle.
Loovjo
De acuerdo en la segunda y tercera línea, @Loovjo, pero ¿por qué dices que ies innecesario? irastrea la posición de la puerta que se está procesando actualmente, y se requiere si su llave aún no se ha recogido (es decir, si kla posición de la llave es menor que fla más a la izquierda que hemos caminado, entonces debemos agregar 2*(i-k-1)pasos a nuestro total (caminando a la izquierda para obtener la llave, y caminando de regreso a la puerta) ...
Ken 'Joey' Mosher
1
Pero, ¿no podría iser reemplazado por l.index(d)en la quinta línea y la tarea eliminada en la cuarta?
Loovjo
Las variables separadas ey fparecen redundantes. Además, puede guardar un montón de caracteres al guardar l.indexen una variable.
user2357112 es compatible con Monica
@loovjo: Sí, tienes razón ... Al principio no entendí bien tu comentario. @ user2357112: absolutamente correcto. xes redundante también. Supongo que mi novato de golf está mostrando :) ¡Gracias por la ayuda!
Ken 'Joey' Mosher
4

C, 136 bytes

q,x,p[300],z,c,k;main(i){for(;p[c=getchar()]=++i,c-36;z&&(k+=(x=p[c+32])&&x<q?(q=q>x?x:q,2*i-2*x-1):1))z=p[94],q||(q=z);printf("%d",k);}
milIbyte
fuente
4

PHP 5.3, 123 bytes

Esta es mi primera publicación en Code Golf, espero que sea de una calidad de golf lo suficientemente alta como para una primera publicación. ¡Definitivamente un desafío divertido y una pregunta increíble!

function n($m){while('$'!=$o=$m[$i++])$o=='^'?$b=$i+$c=0:$o>'Z'||$b<=$k=stripos($m,$o))?$c++:$c+=2*$i-3-2*$b=$k;return$c;}

Este programa abusa del hecho de que PHP no necesita que declare previamente ninguna variable antes de usarla.

También resultó ser un par de bytes más corto en mi solución final para comenzar en 0 y restablecer el conteo de pasos cuando se encuentra el carácter de inicio, en lugar de comenzar en '^'.

¡Cualquier sugerencia es definitivamente bienvenida!

Xanderhall
fuente
3

JavaScript (ES6), 110 bytes

s=>(i=c=>s.indexOf(c),p=i`^`,l=i`$`-p,s.replace(/[A-Z]/g,(c,j)=>p>(t=i(c.toLowerCase()))?l+=j-(p=t)-1<<1:0),l)

Puerto de la respuesta de @ Rob's Pyth.

Neil
fuente
2

Python 2.7, 234 199 179

a=raw_input()
x=a.index
v=x('^')
b=x('$')-v
l=filter(str.islower,a[:v])[::-1]
for i in filter(str.isupper,a):
 k=i.lower()
 if k in l:b+=(x(i)-x(k)-1)*2;l=l[l.index(k)+1:]
print b
Skyler
fuente
1

AWK, 174 Bytes

func f(xmS){x+=S
c=a[x]
if(c~/^[A-Z]/&&!k[c]){C=c
S=-S
s--}else{c=toupper(c)
k[c]=1
s++
if(c==C){S=-S;C=9}}if(c=="$"){print s}else f(x,S)}{split($0,a,"")
f(index($0,"^"),1)}

Probablemente haya un algoritmo más estricto, pero esto es lo que se me ocurrió.

Tenga en cuenta que estoy usando gawk. Algunas implementaciones de AWKpueden no dividir una cadena de ""esta manera.

Robert Benson
fuente
1

C #, 309 bytes

class P{static void Main(string[]a){string m=Console.ReadLine(),k="";var f=true;char b,c=b=' ';int j=m.IndexOf('^'),t=0;for(;m[j]!='$';j+=f?1:-1){c=m[j];if(char.IsUpper(c)){if(k.IndexOf(char.ToLower(c))<0){f=!f;b=c;t--;}}if(char.IsLower(c)){k+=c;if(char.ToUpper(c)==b){f=!f;t--;}}t++;}Console.WriteLine(t);}}

Versión sin golf:

    class P
{
    static void Main(string[] a)
    {
        string m = Console.ReadLine(), k = "";
        var f = true;
        char b, c = b = ' ';
        int j = m.IndexOf('^'), t = 0;
        for (; m[j] != '$'; j += f ? 1 : -1)
        {
            c = m[j];
            if (char.IsUpper(c))
            {
                if (k.IndexOf(char.ToLower(c)) < 0)
                {
                    f = !f; b = c; t--;
                }
            }

            if (char.IsLower(c))
            {
                k += c;
                if (char.ToUpper(c) == b) { f = !f; t--; }
            }


            t++;
        }
        Console.WriteLine(t);
        Console.ReadKey();

    }
}

No hay nada lujoso aquí, solo recorre la cadena y cambia la dirección según el carácter y si la clave está contenida en una cadena de teclas.

m = la cadena del laberinto

k = la cadena de teclas

f = la dirección (verdadero es hacia adelante en el laberinto)

b = la clave para buscar al retroceder

c = marcador de posición para m [j] para guardar algunos bytes debido al uso frecuente

j = el índice de caracteres de la cadena para mirar

t = el recuento

Todavía es relativamente nuevo en el golf, así que si ves en algún lugar puedo adelgazar, ¡házmelo saber!

Faraón del cielo
fuente