길 안내


15

도전

다음과 같이 보이는 친구에게지도를 제공했습니다.

      |
      /
     |
     /
    |
    \
     |
     \
      D

상단에서 시작하여 하단에서 끝나는 간단한지도. 슬프게도, 친구는 그것을 얻지 못합니다. 그가 읽을 수 있도록지도를 해독 할 수 있습니까?

입력

입력이 이루어지는 문자열이며 |, /, \, D, ^, Y, (공간) , 개행.

  • | 같은 열에 머 무르라고 지시합니다.
  • \ 열의 오른쪽과 아래쪽으로 이동하도록 지시합니다.
  • / 왼쪽과 아래로 열로 이동하도록 지시합니다.
  • D 목적지를 표시합니다.
    • ^ (있는 경우) 경로의 분할을 알려줍니다.
    • Y(있는 경우) 경로 재결합을 알려줍니다. 처럼 취급하십시오 |.

입력은 일종의 경로를 만들도록 배열됩니다.

   |
   |
   \
    |
    ^
   / \
  /   |
 D    |

두 경로 사이에는 항상 공백이 있으며 모든 경로는 다시 입력되거나 입력의 마지막 줄에 도달합니다. 지도 당 하나의 스플릿 만 있습니다. 입력 맵의 길이에는 제한이 없습니다. 경로는 두 개를 넘을 수 없습니다.

산출

출력은 일련의 지시 사항이어야합니다.

  • " L "은 친구에게 L eft 를 움직이고 1 단계 앞으로 나아갈 것을 지시해야합니다.
  • " R "은 친구에게 오른쪽 으로 이동 하고 1 단계 앞으로 이동하도록 지시해야 합니다.
  • " F "는 친구에게 1 단계 앞으로 이동하도록 지시해야합니다.

입력 예제 맵의 경우 출력은 다음과 같습니다.

F F L F R R R

친구가지도 상단에서 시작하여지도를 아래로 향하게합니다. 그의 관점에서 지시를주십시오. "^"인스턴스의 경우 프로그램에서 대상 (D)으로 연결되는 경로를 선택할 수 있어야합니다. 두 경로가 다시 결합되면 프로그램은 |따라야 할 가장 직선 경로 (가장 높은 경로)를 선택해야합니다 . 방향 공간에 의해 분리되어야하며 끝나야 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

기타 세부 사항

  • 이것은 코드 골프이므로 8 월 19 일 수요일까지 코드가 가장 짧은 사람이 승리합니다.
  • 건설적인 피드백은 매우 환영합니다.
  • 부분적으로 영감 숨겨진 보물에지도
  • 제목을 더 창의적인 것으로 변경하십시오.
  • 내가 실수 한 것을 발견하면 바로 잡으십시오.
  • 물론 재미있게 보내십시오.

감사합니다!

조금 늦었지만 UndefinedFunction은 JavaScript의 승자 코딩입니다! 들어온 모든 분들께 감사드립니다. 다른 항목은 접수되지 않습니다.


여전히 꺼져있는 것 같습니다. 첫 번째 예는로 L L끝나야한다고 생각합니다 L L L. 의 예는 Y여전히 1끝에 있으며 다른 오류가있는 것 같습니다. F F R R R F F F R R L F규칙을 올바르게 이해하는 것처럼지도를 읽습니다 .
Martin Ender

@ MartinBüttner 당신은 D로 끝나기로되어 있습니다 .2 L 만 필요합니다. 3 L은 D를 지나갔습니다.
The_Basset_Hound

2
마지막 줄에 도달하기 전에 경로가 막 다른 길에 도달 할 수 있습니까? 아니면 모든 경로가 입력의 마지막 줄에 도달합니까?
jrich

@BassetHound에 L대한 하나 ^와 둘 L에 대한 두 가지 가 없어야 /합니까? 그리고 예제 F의 끝에 왜 두 개 를 더 추가 했 Y습니까?
Martin Ender

@ETHproductions 예.
The_Basset_Hound

답변:


5

자바 (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 1

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


로그 :
Kamehameha 덕분에 36 바이트를 절약했습니다.
논리를 약간 변경하여 많은 바이트를 절약했습니다.
액 시악 덕분에 42 바이트를 절약했습니다.
모든 if 문이 삼항 연산자로 대체되었습니다.


3
사이트에 오신 것을 환영합니다!
isaacg

2
$a=$b='';대신 시도해보십시오 - $a='';$b='';약 3 바이트를 절약합니다.
Kamehameha

1
또한 연결 $a=$a.'L ';을로 줄일 수 있습니다 $a.='L '. 당신은 두 곳에서 그렇게 한 것 같습니다. 그것은 약 6 바이트를 절약 할 것이다 :)
Kamehameha

1
PHP는 잘 모르지만 foreach ( foreach($e as$i)) 에서 "as"뒤에 공백을 놓을 수 있다고 생각합니다 . 나는 그것을 테스트했고 잘 작동하는 것 같습니다.
ProgramFOX

1
@ProgramFox as에서 에 대해 언급했듯이 변수와 변수 이름 foreach사이의 공백을 echo제거 하면 몇 바이트를 절약 할 수있는 몇 가지 팁 이 있습니다 echo$b. 또한, 평등 테스트의 몇 너무 짧아 질 수 $c==0!$c와 그런 경우, 당신은 초기화 수 $c''$a$b!
Dom Hastings

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

두 번의 골프 반복의 결과입니다. ungolfed 버전은 다음과 같습니다.

$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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.