道順を与える


15

チャレンジ

次のような友人に地図を渡しました:

      |
      /
     |
     /
    |
    \
     |
     \
      D

上部で始まり下部で終わる単純なマップ。悲しいことに、あなたの友人はそれを取得しません。彼がそれを読むことができるようにマップをデコードできますか?

入力

入力は、以下からなる文字列であり|/\D^Y (空間)、および改行。

  • | 同じ列にとどまるように指示します。
  • \ 右下の列に移動するよう指示します1。
  • / 左および下の列に移動するように指示します1。
  • D 宛先をマークします。
    • ^ (存在する場合)パスの分割を示します。
    • Y(存在する場合)パスの再結合を通知します。のように扱い|ます。

入力は、一種のパ​​スを作成するように配置されます。

   |
   |
   \
    |
    ^
   / \
  /   |
 D    |

2つのパスの間には常にスペースがあり、すべてのパスは再結合するか、入力の最後の行に到達します。マップごとに1つの分割のみがあります。入力マップの長さに制限はありません。2つ以上のパスが存在することはありません。

出力

出力は方向の文字列である必要があります。

  • L」は、友人にLを左に動かし、一歩前進するように指示する必要があります。
  • Rは、」移動にあなたの友人を教えてくださいR IGHTと前進1歩を踏み出します。
  • F」は友人に1歩先に進むように指示する必要があります。

入力マップ例の場合、出力は次のようになります。

F F L F R R R

あなたの友人は地図の一番上から始まり、地図を下に向けていることに注意してください。彼の観点から指示を与えます。「^」のインスタンスの場合、プログラムは宛先(D)に至るパスを選択できる必要があります。2つのパスが再結合する場合、プログラムは、最も直線的なパス(|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

その他の詳細

  • これはコードゴルフであるため、8月19日の次の水曜日までに最も短いコードを持つ人が勝ちます。
  • 建設的なフィードバックを歓迎し、大いに感謝します。
  • A Map to Hidden Treasureに部分的に触発され
  • タイトルをよりクリエイティブなものに変更してください。
  • 私が犯した間違いを見つけた場合は、修正してください。
  • そしてもちろん、楽しんでください。

ありがとうございました!

少し遅いかもしれませんが、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 Lだけを必要とするでしょう。3 LsはDを過ぎます。
The_Basset_Hound15年

2
パスは最後の行に到達する前に行き止まりに到達することはありますか?または、すべてのパスが入力の最後の行に到達しますか?
-jrich

@BassetHoundが1であってはならないLため^と2 L2のために/?そして、なぜ例のF最後にさらに2つ追加したのYですか?
マーティンエンダー

@ETHproductionsはい。
The_Basset_Hound

回答:


5

ジャバスクリプト(ES6)、261の 248 252 248 212バイト

1つの分割のみをサポートする必要があるため:

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

簡単な説明:
入力にパスが1つしかない場合、カウントが0になります。パスが分割されると、カウントは左のパスで1、右のパスで2になります。両方のパス(または1つだけ)を定義した後、どのパスに「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バイト節約できました。
ロジックを少し変更することで多くのバイトを節約しました。
axiacのおかげで42バイト節約されました。
すべてのif文を三項演算子に置き換えました。


3
サイトへようこそ!
isaacg

2
$a=$b='';代わりに試すことができます- $a='';$b='';約3バイト節約します。
カメハメハ

1
また、のような連結$a=$a.'L ';はに減らすことができます$a.='L '。あなたはそれをいくつかの場所でやったようです。約6バイト節約できます:)
カメハメハ

1
PHPについてはよく知りませんが、foreach(foreach($e as$i))の"as"の後にスペースをドロップできると思います。私はそれをテストしましたが、うまくいくようです。
ProgramFOX

1
@ProgramFoxは約述べたようにカップルより多くのヒントは、数バイトを保存することasforeach、間のスペース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;}}

これは、ゴルフを2回繰り返した結果です。改変されていないバージョンは次のとおりです。

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

また、複数のフォークを正しく処理します(常に最大2つのブランチを持つために、次のフォークの前に結合する必要があります)。コメントで複数のフォークについて質問しましたが、答え(「不要」)が来た時点でコードはすでに完了しています。

テストスイートとその他のコメントを含む完全なコードはgithubにあります。


すごい良い仕事だ!まだ多くのことを学ぶ必要があります!
-jrenk
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.