Donner des indications

15

Défi

Vous avez donné une carte à un ami qui ressemble un peu à ceci:

      |
      /
     |
     /
    |
    \
     |
     \
      D

Une carte simple qui commence en haut et se termine en bas. Malheureusement, votre ami ne comprend pas. Pouvez-vous décoder la carte pour qu'il puisse la lire?

Contribution

L'entrée est une chaîne de caractères consistant en |, /, \, D, ^, Y, (espace) , et les nouvelles lignes.

  • | dit de rester dans la même colonne.
  • \ indique de se déplacer vers la colonne vers la droite et vers le bas 1.
  • / indique de se déplacer vers la colonne vers la gauche et vers le bas 1.
  • D marque la destination.
    • ^ (le cas échéant) indique une division du chemin.
    • Y(le cas échéant) raconte une jonction de chemins. Traitez-le comme un |.

L'entrée sera arrangée de façon à faire une sorte de chemin:

   |
   |
   \
    |
    ^
   / \
  /   |
 D    |

Il y aura toujours un espace entre deux chemins, et tous les chemins rejoindront ou atteindront la dernière ligne de l'entrée. Il n'y aura qu'un seul partage par carte. Il n'y a pas de limite à la longueur de la carte d'entrée. Il n'y aura jamais plus de deux chemins.

Production

La sortie doit être une chaîne de directions.

  • « L » devrait dire à votre ami de déplacer L TEF et prendre 1 pas en avant.
  • " R " devrait dire à votre ami de se déplacer vers la droite et de faire un pas en avant.
  • " F " devrait dire à votre ami d'avancer d'un pas.

Pour l'exemple de carte d'entrée, la sortie serait la suivante:

F F L F R R R

Notez que votre ami commence en haut de la carte et fait face vers le bas. Donnez les directions de son point de vue. Pour une instance de "^", votre programme doit pouvoir choisir le chemin qui mène à la destination (D). Si les deux chemins se recombinent, votre programme doit choisir le chemin le plus droit (celui avec le plus de |s) à suivre. Des directives doivent être séparés par des espaces, et doivent se terminer sur D .

Exemples

Contribution

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

Production

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

Puisque le chemin le plus à gauche ne contient que 1 |, nous utilisons le chemin le plus à droite qui en a 3.


Contribution

\
 |
 /
|
\
 |
 /
D

Production

L F R F L F R

Contribution

    /
   \
    /
   \
    ^
   \ \
    D \

Production

R L R L R L

Autres détails

  • C'est le golf de code, donc la personne avec le code le plus court d'ici mercredi 19 août prochain, gagne.
  • Commentaires constructifs bienvenus et grandement appréciés.
  • Partiellement inspiré par A Map to Hidden Treasure
  • N'hésitez pas à changer le titre en quelque chose de plus créatif.
  • Si vous trouvez des erreurs que j'ai faites, corrigez-les.
  • Et bien sûr, amusez-vous.

Je vous remercie!

Un peu tard, peut-être, mais UndefinedFunction est le gagnant du codage en JavaScript! Merci à tous ceux qui sont entrés. Aucune autre inscription ne sera acceptée.

The_Basset_Hound
la source
Il semble toujours éteint. Le premier exemple se termine L L, ce qui, je pense, devrait l'être L L L. L'exemple avec a Ytoujours un 1à la fin et semble également avoir d'autres erreurs. J'ai lu la carte comme F F R R R F F F R R L Fsi je comprenais bien les règles.
Martin Ender
@ MartinBüttner vous êtes censé terminer sur D, vous n'auriez besoin que de 2 L. 3 L passeraient devant D.
The_Basset_Hound
2
Un chemin peut-il atteindre une impasse avant d'atteindre la dernière ligne? Ou tous les chemins atteindront-ils la dernière ligne de l'entrée?
jrich
@BassetHound ne devrait-il pas y en avoir un Lpour les ^deux et deux Lpour les deux /? Et pourquoi en avez-vous ajouté deux de plus Fà la fin de l' Yexemple?
Martin Ender
@ETHproductions Oui.
The_Basset_Hound

Réponses:

5

Javascript (ES6), 261 248 252 248 212 octets

Puisqu'un seul fractionnement doit être pris en charge:

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


Cependant, 240 octets et nous pouvons traiter plusieurs divisions:

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


Les deux programmes définissent des fonctions anonymes.

Pour l'utiliser, donnez un nom aux fonctions en ajoutant f=avant le code.

Ensuite, ils peuvent être appelés avec

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


Explication

(obsolète, mais toujours le même concept. Pour la solution à plusieurs divisions)

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


Remarques

  • Toutes les barres obliques inverses ( \) dans l'entrée sont échappées en tant que \\, afin que javascript puisse les reconnaître.

  • Les deux sorties contiennent un espace de fin.

jrich
la source
Dang it, pensais que j'avais tout réparé.
The_Basset_Hound
9

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

Mon tout premier golf alors soyez doux. Tous les conseils sont très appréciés.

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

Explication courte:
J'ai un nombre qui est 0 si l'entrée n'a qu'un seul chemin. Lorsque le chemin se divise, le nombre est de 1 pour le chemin de gauche et de 2 pour le chemin de droite. Après avoir défini les deux chemins (ou un seul), je vérifie quel chemin a le plus de "F".

Version non golfée:

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


Journal:
économisé 36 octets grâce à Kamehameha.
Enregistré de nombreux octets en modifiant un peu la logique.
Économisé 42 octets grâce à axiac.
Remplacé chaque if par des opérateurs ternaires.

jrenk
la source
3
Bienvenue sur le site!
isaacg
2
Vous pouvez essayer $a=$b='';au lieu de - $a='';$b='';Enregistre environ 3 octets.
Kamehameha
1
De plus, la concaténation comme $a=$a.'L ';peut être réduite à $a.='L '. Vous semblez l'avoir fait à quelques endroits. Cela économisera environ 6 octets :)
Kamehameha
1
Je ne connais pas très bien PHP, mais je pense que vous pouvez supprimer l'espace après "as" dans votre foreach ( foreach($e as$i)); J'ai testé cela et cela semble bien fonctionner.
ProgramFOX
1
Quelques conseils supplémentaires pour économiser quelques octets, comme @ProgramFox l'a mentionné à propos asde la foreach, les espaces entre echoet le nom de la variable peuvent être supprimés pour que vous l'ayez echo$b. En outre, deux tests d'égalité peut être trop courte, $c==0pourrait être !$cet si tel est le cas, vous pouvez initialiser $cà ''avec $aet $b!
Dom Hastings
3

PHP, 281 octets

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

C'est le résultat de deux itérations de golf. La version non golfée est:

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

Il est assez golfé et est apparu comme une amélioration du programme de golf suivant (312 octets):

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

C'est la version golfée de l'original:

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

Exemple d'exécution:

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

Il gère également plusieurs fourches correctement (besoin de se joindre avant la prochaine fourche afin d'avoir au maximum deux branches à tout moment). J'ai demandé plusieurs fourchettes dans un commentaire mais le code était déjà fait lorsque la réponse ("non nécessaire") est arrivée.

Le code complet avec la suite de tests et plus de commentaires peuvent être trouvés sur github .

axiaque
la source
Wow bon travail! J'ai encore besoin d'apprendre pas mal de choses!
jrenk