Memberi arahan

15

Tantangan

Anda telah memberikan peta kepada teman yang terlihat sedikit seperti ini:

      |
      /
     |
     /
    |
    \
     |
     \
      D

Peta sederhana yang dimulai di bagian atas dan berakhir di bagian bawah. Sayangnya, temanmu tidak mengerti. Bisakah Anda memecahkan kode peta sehingga dia bisa membacanya?

Memasukkan

Input adalah string karakter yang terdiri dari |, /, \, D, ^, Y, (space) , dan baris baru.

  • | menyuruh tinggal di kolom yang sama.
  • \ memberitahu untuk pindah ke kolom ke kanan dan ke bawah 1.
  • / memberitahu untuk pindah ke kolom ke kiri dan ke bawah 1.
  • D menandai tujuan.
    • ^ (Jika ada) menceritakan perpecahan di jalan.
    • Y(Jika ada) menceritakan tentang bergabung kembali dengan jalan. Perlakukan itu seperti |.

Input akan diatur sedemikian rupa sehingga membuat semacam jalur:

   |
   |
   \
    |
    ^
   / \
  /   |
 D    |

Akan selalu ada spasi di antara dua jalur, dan semua jalur akan bergabung kembali atau mencapai baris terakhir dari input. Hanya akan ada satu pembagian per peta. Tidak ada batasan panjang peta input. Tidak akan pernah ada lebih dari dua jalur.

Keluaran

Outputnya harus berupa serangkaian arah.

  • " L " harus memberi tahu temanmu untuk memindahkan L. eft dan mengambil 1 langkah ke depan.
  • " R " harus memberi tahu teman Anda untuk memindahkan R ight dan mengambil 1 langkah maju.
  • " F " harus memberi tahu teman Anda untuk maju 1 langkah.

Untuk peta contoh input, outputnya adalah sebagai berikut:

F F L F R R R

Perhatikan bahwa teman Anda mulai di bagian atas peta dan menghadap ke bawah peta. Berikan arahan dari sudut pandangnya. Misalnya "^", program Anda harus dapat memilih jalur yang mengarah ke tujuan (D). Jika kedua jalur bergabung kembali, program Anda harus memilih jalur paling lurus (jalur paling banyak |) untuk diikuti. Petunjuk arah harus dipisahkan oleh spasi, dan harus diakhiri dengan D .

Contohnya

Memasukkan

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

Keluaran

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

Karena jalur paling kiri hanya berisi 1 |, kami menggunakan jalur paling kanan yang memiliki 3.


Memasukkan

\
 |
 /
|
\
 |
 /
D

Keluaran

L F R F L F R

Memasukkan

    /
   \
    /
   \
    ^
   \ \
    D \

Keluaran

R L R L R L

Detail lainnya

  • Ini golf kode, jadi orang dengan kode terpendek pada hari Rabu berikutnya, 19 Agustus, menang.
  • Umpan balik yang konstruktif disambut dan sangat dihargai.
  • Terinspirasi sebagian oleh A Map to Hidden Treasure
  • Jangan ragu untuk mengubah judul menjadi sesuatu yang lebih kreatif.
  • Jika Anda menemukan kesalahan yang saya buat, perbaiki.
  • Dan tentu saja, bersenang-senanglah.

Terima kasih!

Agak terlambat, mungkin, tapi UndefinedFunction adalah pengkodean pemenang dalam JavaScript! Terima kasih untuk semua yang masuk. Tidak ada entri lain yang akan diterima.

The_Basset_Hound
sumber
Sepertinya masih off. Contoh pertama berakhir L L, yang saya pikir seharusnya L L L. Contoh dengan Ymasih memiliki 1di akhir dan juga tampaknya memiliki kesalahan lain. Saya membaca peta seolah- F F R R R F F F R R L Folah saya memahami aturan dengan benar.
Martin Ender
@ MartinBüttner Anda seharusnya berakhir pada D, Anda hanya perlu 2 Ls. 3 Ls akan melewati D.
The_Basset_Hound
2
Bisakah jalan pernah mencapai jalan buntu sebelum mencapai garis terakhir? Atau semua jalur akan mencapai baris input terakhir?
jrich
@ BassetHound tidakkah seharusnya ada satu Luntuk ^keduanya dan dua Luntuk keduanya /? Dan mengapa Anda menambahkan dua lagi Fdi akhir Ycontoh?
Martin Ender
@ EHProduk Ya.
The_Basset_Hound

Jawaban:

5

Javascript (ES6), 261 248 252 248 212 byte

Karena hanya satu pemisahan yang harus didukung:

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


Namun, 240 byte dan kami dapat menangani beberapa pemisahan:

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


Kedua program mendefinisikan fungsi anonim.

Untuk menggunakan, beri fungsi nama dengan menambahkan f=sebelum kode.

Setelah itu, mereka dapat dipanggil dengan

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


Penjelasan

(usang, tetapi masih konsep yang sama. Untuk solusi split ganda)

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


Catatan

  • Semua garis miring terbalik ( \) pada input diloloskan sebagai \\, sehingga javascript dapat mengenalinya.

  • Kedua output berisi spasi tambahan.

Jrich
sumber
Sial, pikir aku sudah memperbaiki semuanya.
The_Basset_Hound
9

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

Golf pertamaku jadi lembut. Setiap tips sangat dihargai.

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

Penjelasan Singkat:
Saya memiliki hitungan yaitu 0 jika Input hanya memiliki satu jalur. Ketika jalur membagi jumlah adalah 1 untuk jalur kiri dan 2 untuk jalur kanan. Setelah mendefinisikan kedua jalur (atau hanya satu) saya memeriksa jalur mana yang memiliki lebih banyak "F's".

Versi Tidak Serigala:

<?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:
Disimpan 36 Bytes berkat Kamehameha.
Menyimpan banyak byte dengan mengubah sedikit logika.
Disimpan 42 Bytes berkat aksioma.
Diganti setiap statment dengan operator ternary.

jrenk
sumber
3
Selamat datang di situs ini!
isaacg
2
Anda dapat mencoba $a=$b='';bukannya - $a='';$b='';Menghemat sekitar 3 byte.
Kamehameha
1
Juga, gabungan seperti $a=$a.'L ';dapat dikurangi menjadi $a.='L '. Anda tampaknya telah melakukan itu di beberapa tempat. Itu akan menghemat sekitar 6 byte :)
Kamehameha
1
Saya tidak tahu PHP dengan baik, tapi saya yakin Anda bisa menghapus spasi setelah "as" di foreach Anda ( foreach($e as$i)); Saya telah menguji itu dan tampaknya berfungsi dengan baik.
ProgramFOX
1
Beberapa tips lagi untuk menyimpan beberapa byte, seperti yang disebutkan @ProgramFox asdi dalam foreach, spasi di antara echodan nama variabel dapat dihapus sehingga Anda memiliki echo$b. Juga, beberapa tes kesetaraan dapat lebih pendek juga, $c==0bisa !$cdan jika itu yang terjadi, Anda dapat menginisialisasinya $cuntuk ''dengan $adan $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;}}

Ini adalah hasil dari dua iterasi golf. Versi ungolfed adalah:

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

Ini cukup golf sendiri dan muncul sebagai peningkatan dari program golf berikut (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;}

Ini adalah versi golf dari aslinya:

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

Contoh eksekusi:

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

Ini juga menangani beberapa garpu dengan benar (perlu bergabung sebelum garpu berikutnya untuk memiliki paling banyak dua cabang kapan saja). Saya bertanya tentang beberapa garpu dalam komentar tetapi kode sudah dilakukan ketika jawabannya ("tidak diperlukan") datang.

Kode lengkap dengan test suite dan lebih banyak komentar dapat ditemukan di github .

aksioma
sumber
Wow kerja bagus! Saya masih perlu belajar beberapa hal!
jrenk