Надання напрямків


15

Виклик

Ви подарували другу другу карту, яка виглядає приблизно так:

      |
      /
     |
     /
    |
    \
     |
     \
      D

Проста карта, яка починається вгорі і закінчується внизу. На жаль, твій друг цього не розуміє. Чи можете ви розшифрувати карту, щоб він міг її прочитати?

Вхідні дані

Введення являє собою рядок символів , що складаються з |, /, \, D, ^, Y, (пропуск) і нового рядка.

  • | повідомляє залишитися в тій же колонці.
  • \ говорить про перехід до стовпця праворуч і вниз 1.
  • / говорить про перехід до стовпчика зліва та вниз 1.
  • D позначає місце призначення.
    • ^ (якщо є) повідомляє про розкол шляху.
    • Y(якщо є) розповідає про повторне з'єднання шляхів. Ставтесь до цього як до |.

Вхід буде розташований таким чином, що він робить своєрідний шлях:

   |
   |
   \
    |
    ^
   / \
  /   |
 D    |

Завжди буде пробіл між двома стежками, і всі шляхи або з’єднаються, або дістаються до останнього рядка вводу. Буде лише один розкол на карті. Немає обмежень щодо довжини вхідної карти. Ніколи не буде більше двох шляхів.

Вихідні дані

Вихід повинен бути рядком напрямків.

  • " L " повинен сказати вашому другові перемістити L eft і зробити 1 крок вперед.
  • « R » повинен сказати своєму другові , щоб перемістити R IGHT і прийняти 1 крок вперед.
  • " F " повинен сказати вашому другові рухатися на 1 крок вперед.

Для карти вхідного прикладу вихід буде таким:

F F L F R R R

Зауважте, що ваш друг починає вгорі карти і зверненим вниз по карті. Дайте вказівки з його точки зору. Для прикладу "^", ваша програма повинна мати можливість вибору шляху, який веде до місця призначення (D). Якщо два шляхи рекомбінуються, ваша програма повинна вибрати найпростіший шлях (той, у якого найбільше |s), який слід пройти. Напрями повинні бути розділені пробілами, і повинні закінчуватися на D .

Приклади

Вхідні дані

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

Вихідні дані

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

Оскільки крайній лівий шлях містить лише 1 |, ми використовуємо крайній правий шлях, у якого є 3.


Вхідні дані

\
 |
 /
|
\
 |
 /
D

Вихідні дані

L F R F L F R

Вхідні дані

    /
   \
    /
   \
    ^
   \ \
    D \

Вихідні дані

R L R L R L

Інші деталі

  • Це кодовий гольф, тому людина, яка має найкоротший код до наступної середи, 19 серпня, виграє.
  • Конструктивний зворотний зв'язок вітається і дуже цінується.
  • Частково натхненний Картою на прихований скарб
  • Не соромтеся змінити назву на щось більш креативне.
  • Якщо ви виявили помилки, які я допустив, виправте їх.
  • І звичайно, весело провести час.

Дякую!

Можливо, трохи пізно, але UndefinedFunction - це переможець, що кодує JavaScript! Дякуємо всім, хто увійшов. Інші записи не приймаються.


Це все ще здається. Перший приклад закінчується на тому L L, що, я думаю, має бути L L L. Приклад із "Все Yще" має 1кінець, а також, схоже, має й інші помилки. Я читаю карту так, F F R R R F F F R R L Fніби правильно розумію правила.
Мартін Ендер

@ MartinBüttner ви повинні закінчити на D, вам знадобиться лише 2 Ls. 3 Ls пройде повз D.
The_Basset_Hound

2
Чи може колись шлях досягти тупика, перш ніж дійти до останньої лінії? Або всі шляхи досягнуть останнього рядка вводу?
jrich

@BassetHound не повинно бути одного Lдля ^двох і двох Lдля двох /? І чому ви додали ще два Fнаприкінці Yприкладу?
Мартін Ендер

@ETHproductions Так.
The_Basset_Hound

Відповіді:


5

Javascript (ES6), 261 248 252 248 212 байт

Оскільки потрібно підтримувати лише один розкол:

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


Однак 240 байт, і ми можемо мати справу з кількома розбиттями:

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


Обидві програми визначають анонімні функції.

Для використання дайте ім'я функції (ів), додавши f=перед кодом.

Після цього їх можна викликати

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


Пояснення

(застаріле, але все одно те саме поняття. Для рішення для множинних спліт)

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


Примітки

  • Усі косої коси риси ( \) на вході видаляються як \\, так що javascript може розпізнати їх.

  • Обидва виходи містять пробіл.


Заплакав, подумав, що все це виправлено.
The_Basset_Hound

9

PHP, 634 631 607 396 382 381 347 338 330 337 324 байт

Мій перший в історії гольф, будь ласкавим. Будь-які поради високо цінуються.

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

Коротке пояснення: у
мене число 0, якщо вхід має лише один шлях. Коли шлях розщеплюється, кількість становить 1 для лівого шляху та 2 для правого шляху. Після визначення обох контурів (або лише одного) я перевіряю, який шлях має більше "F".

Версія без заготівлі:

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


Журнал:
Збережено 36 байт завдяки Kamehameha.
Зберегли багато багато байтів, трохи змінивши логіку.
Збережено 42 байти завдяки аксіаку.
Замінюється кожен, якщо статмент з потрійними операторами.


3
Ласкаво просимо на сайт!
isaacg

2
Можна спробувати $a=$b='';замість - $a='';$b='';Економить близько 3 байт.
Камехамега

1
Також конкатенація на зразок $a=$a.'L ';може бути зведена до $a.='L '. Ви, здається, це зробили в декількох місцях. Це дозволить заощадити близько 6 байт :)
Камехамега

1
Я не знаю PHP дуже добре, але я вважаю, що ви можете залишити пробіл після "як" у вашому передплічі ( foreach($e as$i)); Я перевірив це, і, здається, він працює добре.
ProgramFOX

1
Ще пара рад , щоб заощадити кілька байт, так як @ProgramFox згадувалося про asв foreach, проміжки між echoі ім'я змінним можуть бути видалені так у вас є echo$b. Крім того , пара тестів рівності може бути коротше , теж, $c==0може бути , !$cі якщо це так, то ви можете ініціалізіруетесь $cдо ''з $aі $b!
Дом Гастінгс

3

PHP, 281 байт

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

Це результат двох ітерацій з гольфу. Негольована версія:

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

Це досить гольф сам по собі, і він з'явився вдосконаленням наступної програми для гольфу (312 байт):

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

Це оригінальна версія для гольфу:

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

Приклад виконання:

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

Він також обробляє декілька виделок правильно (потрібно з'єднатись до наступної вилки, щоб мати максимум дві гілки в будь-який час). Я запитав про кілька вилок у коментарі, але код вже був зроблений, коли відповідь ("не потрібна") прийшла.

Повний код із тестовим набором та більше коментарів можна знайти на github .


Нічого хорошої роботи! Мені ще потрібно навчитися досить багато речей!
jrenk
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.