Sbloccare i segreti in un labirinto monodimensionale


41

sfondo

Ti svegli per ritrovarti perso in un labirinto monodimensionale! Un genio mistico (o qualcosa del genere) appare e spiega che l'uscita si trova di fronte a te, ma che tra te e l'uscita è una serie di sfide. Mentre avanzi, ti rendi conto che tutte le cosiddette sfide sono semplicemente porte chiuse. Per prima cosa vedi una porta con un buco della serratura a forma di T, e non avendo tale chiave tu stesso, ripercorri i tuoi passi, cercando una chiave con una Tforma.

Frustrato, trovi una zuppa di chiavi dell'alfabeto a terra, nessuna delle quali corrisponde alla porta che hai incontrato. Con un colpo di genio (o idiozia), decidi che la tchiave a forma di minuscolo potrebbe essere in grado di adattarsi allo slot se la incepphi abbastanza forte. Mentre ti avvicini alla porta con la tchiave minuscola in mano, il Tbuco si illumina di verde e la porta si dissolve davanti a te.

Uno in basso, molti altri per andare ...

Sfida

L'obiettivo di questa sfida è quello di segnare quanti passi ci vogliono per uscire dal labirinto.

L'input di questa sfida è il labirinto: una stringa contenente solo caratteri [A-Za-z^$ ]. Glossario:

  • ^- Lo spazio iniziale. L'input conterrà esattamente uno ^.
  • $- L'uscita (libertà!). L'input conterrà esattamente uno $.
  • [A-Z]- Le lettere maiuscole indicano le porte. Puoi attraversare questa porta solo se hai già raccolto la chiave richiesta.
  • [a-z]- Le lettere minuscole indicano i tasti. Raccogli queste chiavi camminando nello spazio che contiene la chiave.

Ci sarà al massimo una lettera maiuscola nell'input. Ciò significa che il numero totale di porte sarà compreso tra 0 e 26 inclusi.

Ogni porta chiusa [A-Z]avrà esattamente una chiave in minuscolo corrispondente [a-z]. Potrebbe esserci un numero qualsiasi di spazi ( ) nell'input.

Tutte le porte saranno a destra dell'inizio ea sinistra dell'uscita. Quindi non ci saranno porte superflue. Tutti gli ingressi saranno risolvibili.

L'output per questa sfida sarà un numero, il numero di passaggi necessari per uscire dal labirinto.

Algoritmo

Il tuo approccio metodico all'uscita da questo disgraziato posto è il seguente:

  • Inizia da inizio ( ^) e vai avanti (a destra) raccogliendo tutte le chiavi che incontri.
  • Quando ti imbatti in una porta, se hai la chiave corretta, procedi in avanti sulla porta. Se non si dispone della chiave corretta, si cammina all'indietro (a sinistra) raccogliendo le chiavi che si incontrano fino a quando non si trova la chiave per la porta più recente che non è possibile aprire.
  • Dopo aver raccolto la chiave per l'attuale porta problematica, si gira di nuovo a destra e si procede in avanti.
  • Ripeti questo processo finché non passi all'uscita ( $).

I golfisti esperti capiranno che il tuo codice non deve implementare questo algoritmo specifico purché produca lo stesso risultato come se avessi eseguito questo algoritmo.

Conteggio

Ogni volta che passi da un quadrato ad un altro quadrato, questo conta come un passo. La rotazione di 180º non comporta alcun passaggio aggiuntivo. Non è possibile avanzare su una porta senza la chiave necessaria. È necessario salire su una chiave per raccoglierla e per vincere è necessario uscire all'uscita. Dopo la tua prima mossa, lo spazio iniziale ( ^) si comporta come qualsiasi altro spazio normale.

Esempi

In questi esempi ho lasciato gli spazi come caratteri di sottolineatura per la leggibilità umana.

L'input è _a_^_A__$__. L'output è 11. Fai un 1passo avanti, noti che non hai la chiave per la Aporta, e poi per il viso. Cammini all'indietro fino ad occupare lo spazio contenente il a( 3passi indietro, ora 4totale). Quindi si cammina in avanti fino ad occupare lo spazio contenente l'uscita ( 7passi avanti, 11totale).

L'input è b__j^__a_AJB_$. L'output è 41che fai due viaggi separati sul retro del labirinto, uno per ottenere la jchiave e il successivo per ottenere la bchiave.

L'input è __m__t_^__x_T_MX_$____. L'output è 44. Non farai alcun viaggio extra per ottenere la xchiave, mentre la prendevi sulla strada dall'inizio alla porta T.

L'input è g_t_^G_T$. L'output è 12. Non puoi spostarti nello Gspazio senza una chiave e immediatamente in faccia. Sei abbastanza fortunato da ritirare la tchiave sulla strada per la gchiave, e quindi aprire entrambe le porte sulla strada per la libertà.

L'input è _^_____$. L'output è 6. È stato facile.

Linee guida I / O e criterio vincente

Si applicano le regole I / O standard. Questa è una sfida di .


17
A parte la bella sfida, vorrei sottolineare quanto siano buoni il testo e la spiegazione
Luis Mendo,

4
"Quindi non ci saranno porte superflue." Credo che Ain bA^aB$non sarebbe superfluo neanche. ;)
Martin Ender il

4
@orlp Sono più interessato a vedere come la gente gioca a golf con questo algoritmo errante nel buio. Sembra banale fare la soluzione ottimale di "vai a prendere tutte le chiavi e poi apri tutte le porte".
turbulencetoo

2
@PeterTaylor e turbulencetoo No, non lo è, chi può dire che tutte le chiavi sono sul lato sinistro e tutte le porte sulla destra? E anche le chiavi / porte superflue sarebbero interessanti. Sarebbe piuttosto interessante, poiché significherebbe risolvere un grafico delle dipendenze.
orlp

5
Ogni porta ha una chiave. Ogni chiave ha una porta?
user2357112 supporta Monica

Risposte:


3

CJam, 45

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

Provalo online

Spiegazione:

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)

7

Pyth, 51 byte

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

sommare la distanza tra la porta e la sua chiave (raddoppiata, per fare il giro), ignorando le chiavi "annidate" e la distanza dall'inizio alla fine:

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

stesso algoritmo in 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

5

Python 2, 155 154 134 128 byte

Modifica: grazie a @ user2357112 e @loovjo per i loro commenti che mi hanno aiutato a radere altri 20 26 byte dalla mia soluzione!

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

1
È possibile combinare la seconda e la terza riga con un punto e virgola, salvando un byte. Inoltre, la variabile i sembra non necessaria nel ciclo.
Loovjo

Concordato sulla seconda e terza linea, @Loovjo, ma perché dici che inon è necessario? itiene traccia della posizione della porta attualmente in fase di elaborazione ed è necessario se la sua chiave non è stata ancora presa (ovvero se k- la posizione della chiave - è inferiore a f- la più lontana che abbiamo camminato - quindi dobbiamo aggiungere 2*(i-k-1)passi verso il nostro totale (camminando a sinistra per ottenere la chiave, e camminando a destra verso la porta) ...?
Ken 'Joey' Mosher

1
Ma non potrebbe iessere sostituito da l.index(d)sulla quinta riga e l'assegnazione rimossa alla quarta?
Loovjo

Il separato ee le fvariabili sembrano ridondanti. Inoltre, è possibile salvare un gruppo di caratteri salvando l.indexin una variabile.
user2357112 supporta Monica

@loovjo: Sì, hai ragione ... All'inizio ho frainteso il tuo commento. @ user2357112: assolutamente corretto. xè anche ridondante. Immagino che il mio golf noob-iness stia mostrando. :) Grazie per l'aiuto!
Ken 'Joey' Mosher,

4

C, 136 byte

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);}

4

PHP 5.3, 123 byte

Questo è il mio primo post su Code Golf, si spera che sia di qualità golfistica abbastanza alta per un primo post. Sicuramente una sfida divertente e una domanda fantastica!

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;}

Questo programma abusa bene del fatto che PHP non ha bisogno che tu pre-dichiari alcuna variabile prima di usarle.

Si è anche rivelato essere un paio di byte più breve nella mia soluzione finale per iniziare da 0 e reimpostare il conteggio dei passi quando viene trovato il carattere iniziale, piuttosto che iniziare da '^'.

Tutti i suggerimenti sono sicuramente benvenuti!


3

JavaScript (ES6), 110 byte

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)

Risposta Port of @ Rob's Pyth.


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

1

AWK, 174 byte

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

Probabilmente c'è un algoritmo più stretto, ma è quello che mi è venuto in mente.

Nota che sto usando gawk. Alcune implementazioni di AWKnon possono dividere una stringa in ""questo modo.


1

C #, 309 byte

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);}}

Versione non golfata:

    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();

    }
}

Niente di speciale qui, basta scorrere la stringa e cambiare direzione in base al carattere e se la chiave è contenuta in una stringa di chiavi.

m = la stringa del labirinto

k = la stringa di chiavi

f = la direzione (vero è in avanti nel labirinto)

b = la chiave da cercare durante il backtracking

c = segnaposto per m [j] per salvare alcuni byte a causa dell'uso frequente

j = l'indice dei caratteri della stringa da guardare

t = il conteggio

Ancora relativamente nuovo nel golf, quindi se vedi da qualche parte posso dimagrire, fammelo sapere!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.