Anweisungen geben

15

Herausforderung

Sie haben einem Freund eine Karte gegeben, die ungefähr so ​​aussieht:

      |
      /
     |
     /
    |
    \
     |
     \
      D

Eine einfache Karte, die oben beginnt und unten endet. Leider versteht es dein Freund nicht. Kannst du die Karte entschlüsseln, damit er sie lesen kann?

Eingang

Die Eingabe ist eine Kette von Zeichen , bestehend aus |, /, \, D, ^, Y, (Raum) , und neue Zeilen.

  • | sagt, in der gleichen Spalte zu bleiben.
  • \ fordert Sie auf, zur rechten und unteren Spalte zu wechseln 1.
  • / fordert Sie auf, zur linken und unteren Spalte zu wechseln 1.
  • D markiert das Ziel.
    • ^ (falls vorhanden) weist auf eine Teilung des Pfades hin.
    • Y(falls vorhanden) erzählt von einer Wiedervereinigung von Pfaden. Behandle es wie ein |.

Die Eingabe wird so angeordnet, dass sie eine Art Pfad ergibt:

   |
   |
   \
    |
    ^
   / \
  /   |
 D    |

Zwischen zwei Pfaden wird immer ein Leerzeichen eingefügt, und alle Pfade werden entweder wieder verbunden oder erreichen die letzte Zeile der Eingabe. Es wird nur einen Split pro Karte geben. Die Länge der Eingabekarte ist unbegrenzt. Es wird nie mehr als zwei Wege geben.

Ausgabe

Die Ausgabe sollte eine Folge von Anweisungen sein.

  • L “ sollte Ihr Freund zu bewegen sagen L inks und vorwärts 1 Schritt.
  • R “ sollte Ihr Freund zu bewegen sagen R echts und vorwärts 1 Schritt.
  • " F " sollte deinem Freund sagen, dass er einen Schritt nach vorne gehen soll.

Für die Eingabebeispielzuordnung lautet die Ausgabe wie folgt:

F F L F R R R

Beachten Sie, dass Ihr Freund oben auf der Karte beginnt und nach unten zeigt. Geben Sie die Anweisungen aus seiner Perspektive. Für eine Instanz von "^" muss Ihr Programm in der Lage sein, den Pfad zu wählen, der zum Ziel führt (D). Wenn die beiden Pfade erneut kombiniert werden, muss Ihr Programm den geradesten Pfad (den mit den meisten |s) auswählen, dem Sie folgen möchten. Anweisungen müssen durch Leerzeichen getrennt sein und mit D enden .

Beispiele

Eingang

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

Ausgabe

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

Da der Pfad ganz links nur 1 enthält |, verwenden wir den Pfad ganz rechts mit 3.


Eingang

\
 |
 /
|
\
 |
 /
D

Ausgabe

L F R F L F R

Eingang

    /
   \
    /
   \
    ^
   \ \
    D \

Ausgabe

R L R L R L

Andere Details

  • Dies ist Codegolf, also gewinnt die Person mit dem kürzesten Code am kommenden Mittwoch, dem 19. August.
  • Konstruktives Feedback willkommen und sehr geschätzt.
  • Teilweise inspiriert von A Map to Hidden Treasure
  • Fühlen Sie sich frei, den Titel in etwas Kreativeres zu ändern.
  • Wenn Sie Fehler finden, die ich gemacht habe, korrigieren Sie sie.
  • Und natürlich viel Spaß.

Vielen Dank!

Ein bisschen spät vielleicht, aber UndefinedFunction ist die Gewinner-Codierung in JavaScript! Vielen Dank an alle, die eingetreten sind. Andere Einträge werden nicht akzeptiert.

The_Basset_Hound
quelle
Es scheint immer noch aus. Das erste Beispiel endet damit L L, was ich denke sollte L L L. Das Beispiel mit hat Ynoch einen 1am Ende und scheint auch andere Fehler zu haben. Ich habe die Karte gelesen, als F F R R R F F F R R L Fob ich die Regeln richtig verstehe.
Martin Ender
@ Martinbüttner du sollst auf d enden, du würdest nur 2 ls brauchen. 3 Ls würden an D vorbeigehen.
The_Basset_Hound vorbeigehen
2
Kann ein Pfad jemals eine Sackgasse erreichen, bevor er die letzte Linie erreicht? Oder erreichen alle Pfade die letzte Zeile der Eingabe?
Jrich
@ BassetHound sollte es nicht eine Lfür die ^und zwei Lfür die beiden geben /? Und warum haben Sie Fam Ende des YBeispiels noch zwei hinzugefügt ?
Martin Ender
@ETHproductions Ja.
The_Basset_Hound

Antworten:

5

Javascript (ES6), 261 248 252 248 212 Bytes

Da nur ein Split unterstützt werden muss:

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


Jedoch, 240 Bytes , und wir können mit mehreren Splits umgehen:

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


Beide Programme definieren anonyme Funktionen.

Geben Sie zur Verwendung der Funktion (en) einen Namen, indem Sie ihn f=vor dem Code einfügen.

Danach können sie mit angerufen werden

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


Erläuterung

(veraltet, aber immer noch dasselbe Konzept. Für die Multiple-Split-Lösung)

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


Anmerkungen

  • Alle Backslashes ( \) in der Eingabe werden als maskiert\\ maskiert, damit Javascript sie erkennen kann.

  • Beide Ausgaben enthalten ein Leerzeichen.

jrich
quelle
Verdammt, dachte ich hätte alles repariert.
The_Basset_Hound
9

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

Mein allererstes Golf so sanft sein. Alle Tipps sind sehr dankbar.

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

Kurze Erklärung:
Ich habe eine Zählung, die 0 ist, wenn der Eingang nur einen Pfad hat. Wenn der Pfad geteilt wird, ist die Anzahl 1 für den linken Pfad und 2 für den rechten Pfad. Nachdem ich beide Pfade (oder nur einen) definiert habe, überprüfe ich, welcher Pfad mehr "F" hat.

Ungolfed Version:

<?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:
36 Bytes dank Kamehameha gespeichert.
Sparte viele, viele Bytes, indem die Logik ein wenig geändert wurde.
42 Bytes gespart dank Axiac.
Ersetzt jede if-Anweisung durch ternäre Operatoren.

jrenk
quelle
3
Willkommen auf der Seite!
isaacg
2
Sie können versuchen, $a=$b='';statt - $a='';$b='';Speichert etwa 3 Bytes.
Kamehameha
1
Auch Verkettung wie $a=$a.'L ';kann reduziert werden $a.='L '. Sie scheinen das an einigen Stellen getan zu haben. Das spart ungefähr 6 Bytes :)
Kamehameha
1
Ich kenne PHP nicht sehr gut, aber ich glaube, Sie können das Leerzeichen nach "as" in foreach ( foreach($e as$i)) einfügen . Ich habe das getestet und es scheint gut zu funktionieren.
ProgramFOX
1
Ein paar weitere Tipps, um ein paar Bytes zu sparen, wie bei @ProgramFox erwähnt, asin dem foreachdie Leerzeichen zwischen echound der Variablenname entfernt werden können, damit Sie haben echo$b. Auch kann ein paar Gleichheitstests kürzer sein, $c==0könnte sein , !$cund wenn das der Fall ist, können Sie initialisieren , $cum ''mit $aund $b!
Dom Hastings
3

PHP, 281 Bytes

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

Es ist das Ergebnis von zwei Golf-Iterationen. Die ungolfed Version ist:

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

Es ist selbst ziemlich Golf und es ist als eine Verbesserung des folgenden Golfprogramms (312 Bytes) herausgekommen:

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

Es ist die Golfversion des Originals:

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

Beispielausführung:

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

Es werden auch mehrere Gabeln korrekt gehandhabt (müssen vor der nächsten Gabelung verbunden werden, um jederzeit höchstens zwei Zweige zu haben). Ich habe in einem Kommentar nach mehreren Gabeln gefragt, aber der Code war bereits fertig, als die Antwort ("nicht benötigt") kam.

Den kompletten Code mit Testsuite und weiteren Kommentaren finden Sie auf github .

Axiac
quelle
Wow, gute Arbeit! Ich muss noch einiges lernen!
Juni