Dare indicazioni


15

Sfida

Hai dato una mappa a un amico che assomiglia un po 'a questo:

      |
      /
     |
     /
    |
    \
     |
     \
      D

Una semplice mappa che inizia in alto e termina in basso. Purtroppo, il tuo amico non lo capisce. Puoi decodificare la mappa in modo che possa leggerla?

Ingresso

L'ingresso è una stringa di caratteri costituiti |, /, \, D, ^, Y, (spazio) e ritorni a capo.

  • | dice di rimanere nella stessa colonna.
  • \ indica di spostarsi sulla colonna a destra e in basso 1.
  • / indica di spostarsi sulla colonna a sinistra e in basso 1.
  • D segna la destinazione.
    • ^ (se presente) racconta di una divisione nel percorso.
    • Y(se presente) racconta di un ricongiungimento di percorsi. Trattalo come un |.

L'input sarà organizzato in modo tale da creare una sorta di percorso:

   |
   |
   \
    |
    ^
   / \
  /   |
 D    |

Ci sarà sempre uno spazio tra due percorsi e tutti i percorsi si ricongiungeranno o raggiungeranno l'ultima riga dell'input. Ci sarà solo una divisione per mappa. Non c'è limite alla lunghezza della mappa di input. Non ci saranno mai più di due percorsi.

Produzione

L'output dovrebbe essere una stringa di direzioni.

  • " L " dovrebbe dire al vostro amico a muoversi L EFT e prendere 1 passo in avanti.
  • " R " dovrebbe dire al vostro amico a muoversi R volo e prendere 1 passo in avanti.
  • " F " dovrebbe dire al tuo amico di fare un passo avanti.

Per la mappa di esempio di input, l'output sarebbe il seguente:

F F L F R R R

Nota che il tuo amico sta iniziando nella parte superiore della mappa e rivolto verso il basso. Dai le indicazioni dalla sua prospettiva. Per un'istanza di "^", il programma deve essere in grado di scegliere il percorso che conduce alla destinazione (D). Se i due percorsi si ricombinano, il programma deve scegliere il percorso più diritto (quello con il maggior numero di |s) da seguire. Indicazioni devono essere separati da spazi, e devono terminare su D .

Esempi

Ingresso

      |
      |
      \
       \
        ^
       / |
      |  |
      \  |
       \ \
        \ \
         \ /
          Y
          D

Produzione

F F L L L F F F L L R F

Poiché il percorso più a sinistra contiene solo 1 |, utilizziamo il percorso più a destra che ha 3.


Ingresso

\
 |
 /
|
\
 |
 /
D

Produzione

L F R F L F R

Ingresso

    /
   \
    /
   \
    ^
   \ \
    D \

Produzione

R L R L R L

Altri dettagli

  • Questo è il golf del codice, quindi vince la persona con il codice più corto entro mercoledì 19 agosto prossimo.
  • Feedback costruttivo benvenuto e molto apprezzato.
  • Parzialmente ispirato a A Map to Hidden Treasure
  • Sentiti libero di cambiare il titolo in qualcosa di più creativo.
  • Se trovi errori che ho commesso, correggili.
  • E ovviamente divertiti.

Grazie!

Un po 'in ritardo, forse, ma UndefinedFunction è il codice vincente in JavaScript! Grazie a tutti quelli che sono entrati. Non saranno accettate altre iscrizioni.


Sembra ancora spento. Il primo esempio termina L L, che penso dovrebbe essere L L L. L'esempio con Yha ancora un 1alla fine e sembra avere anche altri errori. Ho letto la mappa come F F R R R F F F R R L Fse avessi capito correttamente le regole.
Martin Ender,

@ MartinBüttner dovresti finire con D, ti serviranno solo 2 Ls. 3 L andrebbero oltre D.
The_Basset_Hound

2
Un sentiero può mai raggiungere un vicolo cieco prima di raggiungere l'ultima linea? O tutti i percorsi raggiungeranno l'ultima riga dell'input?
jrich

@BassetHound non dovrebbe essercene uno Lper i ^due e due Lper i due /? E perché ne hai aggiunti altri due Falla fine Ydell'esempio?
Martin Ender,

@ETHproductions Sì.
The_Basset_Hound

Risposte:


5

Javascript (ES6), 261 248 252 248 212 byte

Poiché è necessario supportare solo una divisione:

s=>(s=s.replace(/ /g,o="",d=0).split(`
`)).map((v,j)=>{if(v=="^")for(v="/\\";(w=s[++j])&&(x=w[1]);d=x=="D"?1:w[0]=="D"?0:x>"{"?d+1:w[0]>"{"?d-1:d);o+=(p=v[d>0?1:0]||v[0])<"0"?"R ":p<"E"?"":p=="\\"?"L ":"F "})?o:o


Tuttavia, 240 byte e possiamo gestire più suddivisioni:

s=>(s=s.replace(/ /g,o="").split(`
`)).map((v,j)=>{if(!v[1])t=d=0
else if(!t){for(t=1;(w=s[++j])&&(x=w[1]);d=x=="D"?1:w[0]=="D"?0:x>"{"?d+1:w[0]>"{"?d-1:d);o+=d>0?"L ":"R "}o+=(p=v[d>0?1:0])<"0"?"R ":p<"E"||p=="^"?"":p=="\\"?"L ":"F "})?o:o


Entrambi i programmi definiscono funzioni anonime.

Per usare, dai un nome alle funzioni aggiungendo f=prima del codice.

Successivamente, possono essere chiamati con

alert(f(
`   |
   |
   \\
    |
    ^
   / \\
  /   |
 D    |`
))


Spiegazione

(obsoleto, ma sempre lo stesso concetto. Per la soluzione a divisione multipla)

s=>
    //Remove all spaces from the input
    (s=s.replace(/ /g,o="",
                 //Define function c, to convert symbols to directions
                 c=p=>p<"0"?"R ":p<"E"||p=="^"?"":p=="\\"?"L ":"F "
    //Split input into an array by newlines
    ).split(`
`))
    //for each string v in the input array, at index j:
    .map((v,j)=>{
        //if v is only one character long:
        if(!v[1]){
            t=1     //assign t to 1 (true) - we need to test if multiple paths
            d=0     //assign d to 0 - reset the counter for determining shortest path
        }
        //if v is two characters long, and we have not tested which path is shorter yet:
        else if(t){
            for(    t=0;    //assign t to 0 - we will have tested which path is longer

                    //for each string left in the input, while the input still has two characters:
                    (w=s[++j]) && w[1];
                    //assign d to determine which direction to go. This will be conveyed by if d>0
                    d=
                        w[1]=="D"?1:    //if the dest. is only on one side, choose that side.
                        w[0]=="D"?0:
                        w[1]=="|"?d+1:  //otherwise add/subtract from d (like a tug of war) to determine which side has more "|"
                        w[0]=="|"?d-1:
                        d
               );
            o+=d>0?"L ":"R "    //append to the output which direction was taken
        }

        o+=c(v[d>0?1:0])    //append to the output the characters from the correct path in any case, determined by d calculated above 
                            //(or defaulting to 0, if path is not split, in which case the only character is appended)

    }) ? o : o  //coerce the result, which will evaluate to an array of the input, to the output (o) and implicitly return


Appunti

  • Tutte le barre rovesciate ( \) nell'input sono sfuggite a \\, in modo che javascript possa riconoscerle.

  • Entrambi gli output contengono uno spazio finale.


Maledizione, pensavo di aver risolto tutto.
The_Basset_Hound,

9

PHP, 634 631 607 396 382 381 347 338 330 337 324 byte

Il mio primo golf in assoluto, quindi sii gentile. Tutti i suggerimenti sono molto apprezzati.

<?php
foreach(str_split(strtr(fgets(STDIN),[' '=>'']))as $i){if($i!=D){$z=$i=='^';$x=$i==Y;$s=!$z&&!$x?($i=='/'?R:($i=='|'?F:($i=='\\'?L:$s))):$s;$a.=$z?R:($x?F:(($c==1||!$c)?$s:''));$b.=$z?L:($x?F:(($c==2||!$c)?$s:''));$c=$z?1:($x?0:($c==1?2:($c==2?1:$c)));}else{echo(substr_count($a,F)<substr_count($b,F)&&$c==0||$c==2)?$b:$a;}}

Breve spiegazione:
ho un conteggio che è 0 se l'ingresso ha un solo percorso. Quando il percorso si divide, il conteggio è 1 per il percorso a sinistra e 2 per il percorso a destra. Dopo aver definito entrambi i percorsi (o solo uno), controllo quale percorso ha più "F".

Versione Ungolfed:

<?php
$input = fgets(STDIN);
$inputArray = str_split($input);
foreach ($inputArray as $currentChar) {
    if ($currentChar != 'D') {
        if ($i == '^') {
            $firstPath .= 'R';
            $secondPath .= 'L';
            $count = 1;
        } elseif ($i == 'Y') {
            $secondPath .= 'F';
            $firstPath .= 'F';
            $count = 0;
        } else {
            if ($i == ' ') {
                continue;
            }
            if ($i == '/') {
                $direction = 'R';
            } else {
                if ($i == '|') {
                    $direction = 'F';
                } else {
                    if ($i == '\\') {
                        $direction = 'L';
                    } else {
                        $direction = '';
                    }
                }
            }
            if ($count == 1) {
                $firstPath .= $direction;
                $count = 2;
            } elseif ($count == 2) {
                $secondPath .= $direction;
                $count = 1;
            }
            if (!$count) {
                $firstPath .= $direction;
                $secondPath .= $direction;
            }
        }
    } else {
        echo (substr_count($firstPath, 'F') < substr_count($secondPath, 'F')) || $count == 2 ? $secondPath : $firstPath;
    }
};


log:
salvato 36 byte grazie a Kamehameha.
Ho salvato molti byte modificando un po 'la logica.
Risparmiato 42 byte grazie a axiac.
Sostituito ogni if ​​statment con operatori ternari.


3
Benvenuti nel sito!
isaacg,

2
Puoi provare $a=$b='';invece di - $a='';$b='';Salva circa 3 byte.
Kamehameha,

1
Inoltre, la concatenazione come $a=$a.'L ';può essere ridotta a $a.='L '. Sembra che tu l'abbia fatto in un paio di posti. Ciò consentirà di risparmiare circa 6 byte :)
Kamehameha,

1
Non conosco molto bene PHP, ma credo che puoi lasciare spazio dopo "as" in foreach ( foreach($e as$i)); L'ho provato e sembra funzionare bene.
Programma FOX il

1
Un altro paio di suggerimenti per salvare alcuni byte, come ha detto @ProgramFox riguardo al asin foreach, gli spazi tra echoe il nome della variabile possono essere rimossi in modo da avere echo$b. Inoltre, un paio di test di uguaglianza può essere più breve troppo, $c==0potrebbe essere !$ce se questo è il caso, è possibile inizializzare $ca ''con $ae $b!
Dom Hastings,

3

PHP, 281 byte

$b=0;$p=['|'=>'$a[$b].="F ";$f[$b]++;','/'=>'$a[$b].="R ";','\\'=>'$a[$b].="L ";','^'=>'$d.=$a[0];$n=2;$a=["R ","L "];$f=[];$b=1;','Y'=>'$d.=$a[$f[0]<$f[$n=1]]."F ";$a=[];','D'=>'$d.=$a[$b];exit(rtrim($d));'];foreach(str_split($argv[$n=1])as$c){if($x=$p[$c]){eval($x);$b=++$b%$n;}}

È il risultato di due iterazioni del golf. La versione non golfata è:

$a=$f=[];       // these assignments are not required (they were suppresed in v2)
$n=1;           // this assignment can be squeezed into $argv[$n=1]
$b=0;           // if this assignment is suppressed $b becomes '' and breaks the logic
$code = [
    '|' => '$a[$b].="F ";$f[$b]++;',
    '/' => '$a[$b].="R ";',
    '\\'=> '$a[$b].="L ";',
    '^' => '$d.=$a[0];$n=2;$a=["R ","L "];$f=[];$b=1;',
    'Y' => '$d.=$a[$f[0]<$f[$n=1]]."F ";$a=[];',
    'D' => '$d.=$a[$b];echo(rtrim($d));',
];
foreach (str_split($argv[1]) as $char) {
    // ignore input characters not in the keys of $code
    if ($x = $code[$char]) {
        eval($x);
        $b = ++ $b % $n;   // cycles between 0 and 1 ($n == 2) or stays 0 ($n == 1)
    }
}

È piuttosto golfato da solo ed è emerso come un miglioramento del seguente programma golfizzato (312 byte):

$b=0;foreach(str_split($argv[$n=1])as$c){if($c=='|'){$a[$b].='F ';$f[$b]++;}elseif($c=='/'){$a[$b].='R ';}elseif($c=='\\'){$a[$b].='L ';}elseif($c=='^'){$d.=$a[0];$n=2;$a=['R ','L '];$f=[];$b=1;}elseif($c==Y){$d.=$a[$f[0]<$f[$n=1]].'F ';$a=[];}elseif($c==D){$d.=$a[$b];exit(rtrim($d));}else continue;$b=++$b%$n;}

È la versione da golf dell'originale:

$map = $argv[1];

$dir = '';              // the already computed directions
$nb = 1;                // the number of branches
$branches = [ '' ];     // the branches (2 while between '^' and 'Y', 1 otherwise)
$nbF = [ 0, 0 ];        // the number of 'F's on the branches (used to select the branch)
$curr = 0;              // the current branch
foreach (str_split($map) as $char) {
    if ($char == '|') {             // go 'F'orward
        $branches[$curr] .= 'F ';       // put it to the current branch
        $nbF[$curr] ++;                 // count it for the current branch
    } elseif ($char == '/') {       // go 'R'ight
        $branches[$curr] .= 'R ';
    } elseif ($char == '\\') {      // go 'L'eft
        $branches[$curr] .= 'L ';
    } elseif ($char == '^') {       // fork; choose the path ('L' or 'R') that contains the most 'F'orward segments
        $dir .= $branches[0];           // flush the current path (it was stored as the first branch)
        $nb = 2;                        // start two branches
        $branches = [ 'R ', 'L ' ];     // put the correct directions on each branch
        $nbF = [ 0, 0 ];                // no 'F's on any branch yet
        $curr = 1;                      // need this to let it be 0 on the next loop
    } elseif ($char == 'Y') {       // join
        $dir .= $branches[$nbF[0] < $nbF[1]];   // flush; choose the branch having the most 'F's
        $dir .= 'F ';                           // treat it like a "|"
        $branches = [ '' ];                     // back to a single, empty branch
        $nb = 1;
    } elseif ($char == 'D') {       // finish
        $dir .= $branches[$curr];       // flush
        break;                          // and exit; could use 'return' but it's one byte longer; use exit() in the final program and save 5 bytes
    } else {
        continue;
    }
    $curr = ++ $curr % $nb;
}
echo rtrim($dir);

Esempio di esecuzione:

$ php -d error_reporting=0 directions.php '
      |
      |
      \
       \
        ^
       / |
      |  |
      \  |
       \ \
        \ \
         \ /
          Y
          D
'; echo
F F L L L F F F L L R F
$

Gestisce anche più forcelle correttamente (è necessario unire prima del fork successivo per avere al massimo due rami in qualsiasi momento). Ho chiesto informazioni su più forchette in un commento, ma il codice era già stato fatto quando è arrivata la risposta ("non necessaria").

Il codice completo con la suite di test e altri commenti sono disponibili su github .


Wow, ottimo lavoro! Devo ancora imparare alcune cose!
jrenk,
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.