Đưa ra chỉ dẫn


15

Thử thách

Bạn đã đưa một bản đồ cho một người bạn trông giống như thế này:

      |
      /
     |
     /
    |
    \
     |
     \
      D

Một bản đồ đơn giản bắt đầu ở phía trên và kết thúc ở phía dưới. Đáng buồn thay, bạn của bạn không nhận được nó. Bạn có thể giải mã bản đồ để anh ta có thể đọc nó?

Đầu vào

Đầu vào là một chuỗi ký tự bao gồm |, /, \, D, ^, Y, (không gian) , và dòng mới.

  • | nói để ở trong cùng một cột.
  • \ nói để di chuyển đến cột bên phải và xuống 1.
  • / nói để di chuyển đến cột bên trái và xuống 1.
  • D đánh dấu đích đến.
    • ^ (nếu có) nói về sự phân chia trong đường dẫn.
    • Y(nếu có) kể về sự nối lại của các đường dẫn. Hãy đối xử với nó như một |.

Đầu vào sẽ được sắp xếp sao cho nó tạo ra một loại đường dẫn:

   |
   |
   \
    |
    ^
   / \
  /   |
 D    |

Sẽ luôn có một khoảng trống giữa hai đường dẫn và tất cả các đường dẫn sẽ nối lại hoặc đến dòng cuối cùng của đầu vào. Sẽ chỉ có một phần chia cho mỗi bản đồ. Không có giới hạn về độ dài của bản đồ đầu vào. Sẽ không bao giờ có nhiều hơn hai con đường.

Đầu ra

Đầu ra phải là một chuỗi các hướng.

  • " L " nên nói với bạn của bạn để di chuyển L eft và tiến lên 1 bước.
  • " R " sẽ nói với bạn của bạn để di chuyển R ight và tiến lên 1 bước.
  • " F " sẽ nói với bạn của bạn để tiến lên 1 bước.

Đối với bản đồ ví dụ đầu vào, đầu ra sẽ như sau:

F F L F R R R

Lưu ý rằng bạn của bạn đang bắt đầu ở trên cùng của bản đồ và hướng xuống bản đồ. Đưa ra các hướng từ quan điểm của mình. Đối với trường hợp "^", chương trình của bạn phải có thể chọn đường dẫn đến đích (D). Nếu hai đường dẫn kết hợp lại, chương trình của bạn phải chọn đường dẫn thẳng nhất (đường dẫn có nhiều nhất| s ) để theo dõi. Chỉ phải được tách bằng dấu cách, và phải kết thúc trên D .

Ví dụ

Đầu vào

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

Đầu ra

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

Vì đường dẫn ngoài cùng bên trái chỉ chứa 1 | , chúng tôi sử dụng đường dẫn ngoài cùng bên phải có 3.


Đầu vào

\
 |
 /
|
\
 |
 /
D

Đầu ra

L F R F L F R

Đầu vào

    /
   \
    /
   \
    ^
   \ \
    D \

Đầu ra

R L R L R L

Những chi tiết khác

  • Đây là môn đánh gôn, vì vậy người có mã ngắn nhất vào thứ Tư tuần sau, ngày 19 tháng 8, sẽ thắng.
  • Phản hồi mang tính xây dựng chào đón và đánh giá rất cao.
  • Lấy cảm hứng một phần bởi A Map to Hidden Treasure
  • Hãy thoải mái thay đổi tiêu đề để một cái gì đó sáng tạo hơn.
  • Nếu bạn tìm thấy sai lầm mà tôi đã làm, hãy sửa chúng.
  • Và tất nhiên, vui chơi.

Cảm ơn bạn!

Một chút muộn, có thể, nhưng Und xác định chức năng là mã chiến thắng trong JavaScript! Cảm ơn tất cả những người đã tham gia. Không có mục khác sẽ được chấp nhận.


Nó vẫn có vẻ tắt. Ví dụ đầu tiên kết thúc L L, mà tôi nghĩ nên có L L L. Ví dụ với Yvẫn có một 1ở cuối và dường như cũng có các lỗi khác. Tôi đọc bản đồ như F F R R R F F F R R L Fthể tôi hiểu chính xác các quy tắc.
Martin Ender

@ MartinBüttner bạn phải kết thúc vào D, bạn sẽ chỉ cần 2 Ls. 3 Ls sẽ đi qua D.
The_Basset_Hound

2
Một con đường có thể đi đến ngõ cụt trước khi đến dòng cuối cùng không? Hoặc tất cả các đường dẫn sẽ đạt đến dòng cuối cùng của đầu vào?
jrich

@BassetHound không nên có một Lcho ^hai và hai Lcho hai /? Và tại sao bạn lại thêm hai cái nữa Fvào cuối Yví dụ?
Martin Ender

@ETHproductions Có.
The_Basset_Hound 14/08/2015

Câu trả lời:


5

Javascript (ES6), 261 248 252 248 212 byte

Vì chỉ có một phần tách phải được hỗ trợ:

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


Tuy nhiên, 240 byte và chúng tôi có thể xử lý nhiều phân tách:

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


Cả hai chương trình xác định chức năng ẩn danh.

Để sử dụng, hãy đặt tên cho (các) hàm bằng cách thêm f=trước mã.

Sau đó, họ có thể được gọi với

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


Giải trình

(lỗi thời, nhưng vẫn là cùng một khái niệm. Đối với giải pháp chia nhỏ)

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


Ghi chú

  • Tất cả dấu gạch chéo ngược ( \) trong đầu vào được thoát dưới dạng \\, để javascript có thể nhận ra chúng.

  • Cả hai đầu ra đều chứa một dấu cách.


Dang nó, nghĩ rằng tôi đã sửa tất cả.
The_Basset_Hound

9

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

Lần đầu tiên chơi golf của tôi thật nhẹ nhàng. Bất kỳ lời khuyên được đánh giá rất cao.

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

Giải thích ngắn:
Tôi có số đếm bằng 0 nếu Đầu vào chỉ có một đường dẫn. Khi đường dẫn chia số đếm là 1 cho đường dẫn bên trái và 2 cho đường dẫn bên phải. Sau khi xác định cả hai đường dẫn (hoặc chỉ một) tôi kiểm tra đường dẫn nào có nhiều chữ "F" hơn.

Phiên bản Ungolfed:

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


Nhật ký:
Đã lưu 36 Byte nhờ Kamehameha.
Đã lưu nhiều byte bằng cách thay đổi logic một chút.
Tiết kiệm được 42 byte nhờ vào axiac.
Thay thế mọi nếu statment với các nhà khai thác ternary.


3
Chào mừng đến với trang web!
isaacg

2
Bạn có thể thử $a=$b='';thay vì - $a='';$b='';Lưu khoảng 3 byte.
Kamehameha

1
Ngoài ra, nối như thế $a=$a.'L ';có thể được giảm xuống $a.='L '. Bạn dường như đã làm điều đó ở một vài nơi. Điều đó sẽ tiết kiệm khoảng 6 byte :)
Kamehameha

1
Tôi không biết PHP rất rõ, nhưng tôi tin rằng bạn có thể bỏ khoảng trống sau "as" trong foreach ( foreach($e as$i)); Tôi đã thử nghiệm điều đó và nó có vẻ hoạt động tốt.
Chương trìnhFOX

1
Một vài mẹo nữa để lưu một vài byte, như @ProgramFox đã đề cập về phần astrong foreach, khoảng trắng giữa echovà tên biến có thể được loại bỏ để bạn có echo$b. Ngoài ra, một vài xét nghiệm bình đẳng có thể ngắn quá, $c==0có thể !$cvà nếu đó là trường hợp, bạn có thể khởi $cđến ''với $a$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;}}

Nó là kết quả của hai lần lặp golf. Phiên bản không có bản quyền là:

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

Nó được chơi golf khá tốt và nó nổi lên như là một cải tiến của chương trình chơi gôn sau (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;}

Đây là phiên bản golf của bản gốc:

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

Ví dụ thực hiện:

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

Nó cũng xử lý nhiều nhánh chính xác (cần tham gia trước ngã ba tiếp theo để có nhiều nhất hai nhánh bất cứ lúc nào). Tôi đã hỏi về nhiều nhánh trong một bình luận nhưng mã đã được thực hiện khi câu trả lời ("không cần thiết") đến.

Mã hoàn chỉnh với bộ kiểm tra và nhiều bình luận có thể được tìm thấy trên github .


Wow công việc tốt! Tôi vẫn cần học khá nhiều thứ!
jrenk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.