Давать инструкции

15

Вызов

Вы дали карту другу, который выглядит примерно так:

      |
      /
     |
     /
    |
    \
     |
     \
      D

Простая карта, которая начинается сверху и заканчивается снизу. К сожалению, твой друг не понимает этого. Можете ли вы расшифровать карту, чтобы он мог ее прочитать?

вход

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

  • | говорит остаться в той же колонке.
  • \ приказывает перейти в колонку вправо и вниз 1.
  • / приказывает перейти к колонке влево и вниз 1.
  • D отмечает место назначения.
    • ^ (если присутствует) говорит о расщеплении в пути.
    • Y(если присутствует) говорит о воссоединении путей. Относись к этому как к |.

Ввод будет организован таким образом, чтобы он составлял своего рода путь:

   |
   |
   \
    |
    ^
   / \
  /   |
 D    |

Между двумя путями всегда будет пробел, и все пути либо воссоединятся, либо достигнут последней строки ввода. На карте будет только один сплит. Нет ограничений на длину входной карты. Там никогда не будет более двух путей.

Выход

Вывод должен быть строкой направлений.

  • « L » должны сообщить своему другу , чтобы двигаться L EFT и принять 1 шаг вперед.
  • « R » должен сказать своему другу , чтобы переместить R IGHT и принять 1 шаг вперед.
  • « F » должен сказать вашему другу, чтобы он сделал шаг вперед.

Для входного примера карты результат будет следующим:

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! Спасибо всем кто зашел. Другие записи не принимаются.

The_Basset_Hound
источник
Это все еще кажется выключенным. Первый пример заканчивается 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
Может ли путь когда-нибудь зайти в тупик до последней линии? Или все пути достигнут последней строки ввода?
11
@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 мог их распознать.

  • Оба выхода содержат завершающий пробел.

jrich
источник
Черт, подумал, что я все исправил.
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 байта благодаря Axiac.
Заменен каждый if if с троичными операторами.

jrenk
источник
3
Добро пожаловать на сайт!
Исаак
2
Вы можете попробовать $a=$b='';вместо - $a='';$b='';Сохраняет около 3 байтов.
Камехамеха
1
Кроме того, объединение $a=$a.'L ';может быть уменьшено до $a.='L '. Вы, кажется, сделали это в нескольких местах. Это сэкономит около 6 байтов :)
Kamehameha
1
Я не очень хорошо знаю PHP, но я верю, что вы можете оставить пробел после "as" в вашем foreach ( 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 .

axiac
источник
Вау, хорошая работа! Мне все еще нужно выучить немало вещей!
jrenk