相対対絶対


17

このグリッドのポイントAで北を向いている人が、方向を緑のパス(グリッド線のみに従うことができるため)に沿ってポイントBにしたい場合、次のように伝えます。

ゴーNorth, North, West, East, East, South, East, East

または同等に

ゴーForward, Forward, Left, Back, Forward, Right, Left, Forward
RightLeft、またはBackのコマンドが暗黙的にその方向に回転することを意味する場合、次に進みます。)

AからBへのパス

同じポイントにだけではなく、同じパス沿ったこれらの絶対方向と相対方向の間で変換する1つの引数を持つ関数を作成します。指示された人が常に北を向いていると仮定します。

引数が文字の文字列の場合、NSEW同等の相対方向を返します。
たとえばf("NNWEESEE")、文字列を返しますFFLBFRLF

引数が文字の文字列の場合、FBLR同等の絶対方向を返します。
たとえばf("FFLBFRLF")、文字列を返しますNNWEESEE

空の文字列はそれ自身をもたらします。他の入力ケースは想定しません。

言語に関数や文字列がない場合は、最も適切と思われるものを使用してください。

バイト単位の最短コードが優先されます


人は常に頭を北に向けて始めると思いますか?そうすれば、相対的な観点から東に向かうには、単に前方に言うのではなく、右に曲がる必要があります
オプティマイザー14

@Optimizerはい、北。そして、あなたの他のポイントにイエス。開始時にR等しいE
カルビンの趣味14

1
わーい!あなたは私がいつも考えていたことを確認するために写真を変えました!
ジャスティン14

4
あなたは再びPPCGに夢中ですか?;)
マーティン・エンダー14

4
@MartinBüttnerそれとも私は宿題の問題を隠すのが得意です。;)
カルビンの趣味14

回答:


6

CJam、57 53 49

{"NESW""FRBL"_3$&!!:Q$:R^^f#0\{{+0\}Q*_@-R=\}%);}

前のバージョン

{"NESW""FRBL"_3$0=#W>:Q{\}*:R;f#0\{{+0\}Q*_@-R=\}%);}

例:

{"NESW""FRBL"_3$0=#W>:Q{\}*:R;f#0\{{+0\}Q*_@-R=\}%);}:T;
"NNWEESEE"T
N
"FFLBFRLF"T

出力:

FFLBFRLF
NNWEESEE

使い方

{
  "NESW""FRBL"             " Push the two strings. ";
  _3$0=#W>                 " Check if the first character is in FRBL. ";
  :Q                       " Assign the result to Q. ";
  {\}*                     " Swap the two strings if true. ";
  :R;                      " Assign the top string to R and discard it. ";
  f#                       " Find each character of the input in the string. ";
  0\                       " Push a 0 under the top of the stack. ";
  {                        " For each item (index of character): ";
    {                      " If Q: ";
      +0\                  " A B -> 0 (A+B) ";
    }Q*
    _@-                    " C D -> D (D-C) ";
    R=                     " E -> E-th character in R ";
    \                      " Swap the top two items. ";
  }%
  );                       " Discard the last item in the list. ";
}

6

C ++、99 97

以下は、ラムダ式としてフォーマットされています。1つのchar*引数を取り、上書きします。

[](char*s){for(int d=0,n=0,c=*s*9%37&4;*s;d+=n)c?n=*s%11/3-d:n+=*s%73%10,*s++="NESWFRBL"[c|n&3];}

この機能に慣れていない人(1時間前の私など)には、次のように使用してください。

#include <iostream>

int main()
{
    char s[] = "NNWEESEE";
    auto x = [](char*s){for(int d=0,n=0,c=*s*9%37&4;*s;d+=n)c?n=*s%11/3-d:n+=*s%73%10,*s++="NESWFRBL"[c|n&3];};

    x(s); // transform from absolute to relative
    std::cout << s << '\n';

    x(s); // transform from relative to absolute
    std::cout << s << '\n';
}

いくつかの説明:

  • のようなコードflag ? (x = y) : (x += z)を使用する場合、Cでは2番目の括弧のペアが必要です。したがって、代わりにC ++を使用しました。
  • C ++では、関数の戻り値の型を指定する必要があります。ラムダ式を使用しない限り、それは!追加のボーナスは、関数の名前に1文字を無駄にする必要がないことです。
  • コード*s*9%37&4は最初のバイトをテストします。結果が4の場合NESW、そうでなければ0
  • コード*s%11/3はバイトNESWを0、1、2、3に変換します
  • コード*s%73%10は、バイトFRBLを0、9、6、3(0、1、2、3モジュロ4)に変換します
  • 相対方向を絶対方向に変換する場合、d変数は必要ありません。完全に削除するためにコードを再配置しようとしましたが、不可能なようです...

1
文字を数字に変換する方法がとても気に入っています。:)
エミル14

6

JavaScript(E6)84 86 88 92 104

編集:%の代わりに&を使用し、異なる演算子の優先順位(括弧なし)を使用し、負の数でより適切に動作します
Edit2:| +の代わりに、再びop優先順位、-2。DocMax
Edit3に感謝します。配列内包表記は、文字列の場合、map()より2文字短くなります。

F=p=>[o+=c[d=n,n=c.search(i),n<4?4|n-d&3:n=n+d&3]for(i of n=o='',c='NESWFRBL',p)]&&o

FireFox / FireBugコンソールでテストする

console.log(F('NNWEESEE'),F('FFLBFRLF'))

出力

FFLBFRLF NNWEESEE

@Optimizerはもう必要ありません。そして、さらに縮小したいと考えています。
edc65 14

何が&& o最終平均で?
ベベ14

2
@bebe map関数は、副作用として配列を返します。返される必要のあるo文字列を入力します。array && valueevalute value任意の配列は、と評価さとしてtruthy
edc65

1
最後に!88に達して以来、私はこの1つを見つめていた。何かを逃していない限り、2文字に置き換え4+(n-d&3)4|n-d&3保存できます。
DocMax 14

4

APL、72

{^/⍵∊A←'NESW':'FRBL'[1+4|-2-/4,3+A⍳⍵]⋄A[1+4|+\'RBLF'⍳⍵]}

インタープリターの構成をペナルティーなしで変更できる場合、スコアは66⎕IOなり0ます。

{^/⍵∊A←'NESW':'FRBL'[4|-2-/0,A⍳⍵]⋄A[4|+\'FRBL'⍳⍵]}

3

Python、171 139

他のソリューションほど短い方法ではありませんが、Pythonでできることにとっては比較的良いはずだと思います。

def f(i):a,b='NWSE','FLBR';I=map(a.find,'N'+i);return''.join((b[I[k+1]-I[k]],a[sum(map(b.find,i)[:k+1])%4])[-1in I]for k in range(len(i)))

読みやすくするための拡張バージョン:

def f(i):
    a, b = 'NWSE', 'FLBR'
    I = map(a.find,'N'+i)     # translate to numbers assuming abs. directions
    J = map(b.index,i)        # translate to numbers assuming rel. directions
    if not -1 in I:
        o = [b[I[k+1]-I[k]] for k in range(len(i))]    # rel. dir. is differences of abs. dir.
    else:
        o = [a[sum(J[:k+1])%4] for k in range(len(i))] # abs. dir. is sum of all rel. dir. so far
    return ''.join(o)

1

行く、201

type q string;func F(s q)q{d,z:=byte(0),make([]byte,len(s));for i,c:=range[]byte(s){if(c^4)*167%3<2{c=c*156%5;z[i],d="LBRF"[(d-c)%4],c-1;}else{c=(c^43)*3%7-1;d=(d+c)%4;z[i]="NESW"[d];};};return q(z);}

読み取り可能なバージョン:

func F(s string) string {
    d, z, R, A := 0, make([]byte, len(s)), "LBRFLBR", "NESW"
    for i, c := range []byte(s) {
        switch c {
        case 'N': c = R[d+3]; d = 0
        case 'E': c = R[d+2]; d = 1
        case 'S': c = R[d+1]; d = 2
        case 'W': c = R[d]; d = 3
        case 'F': c = A[d]
        case 'R': d = (d + 1) % 4; c = A[d]
        case 'B': d = (d + 2) % 4; c = A[d]
        case 'L': d = (d + 3) % 4; c = A[d]
        }
        z[i] = c
    }
    return string(z)
}


1

GNU sed、356バイト

課題は、文字のストリームの単純な変換を必要とします。 sed、ストリームエディタは言語の明らかな選択です;-)

/[FRBL]/bx                                     # Jump to label x if relative
:y                                             # label y (start of abs->rel loop)
/[FRBL]$/q                                     # quit if string ends in rel char
s/(^|[FRBL])N/\1F/;ty                          # Substitute next abs char with
s/(^|[FRBL])E/\1R/;tr                          #     rel char, then jump to
s/(^|[FRBL])S/\1B/;tb                          #     relevant rotation label if
s/(^|[FRBL])W/\1L/;tl                          #     a match was found
by                                             # loop back to y
:r;y/NESW/WNES/;by                             # Rotation labels: transform then
:b;y/NESW/SWNE/;by                             #     loop back to y
:l;y/NESW/ESWN/;by
:x                                             # label x (start of rel->abs loop)
/^[NESW]/q                                     # quit if string starts w/ abs char
/F([NESW]|$)/s/F([NESW]|$)/N\1/                # Matches for each direction:
/R([NESW]|$)/y/NESW/ESWN/;s/R([NESW]|$)/E\1/   #     rotate, then substitute
/B([NESW]|$)/y/NESW/SWNE/;s/B([NESW]|$)/S\1/
/L([NESW]|$)/y/NESW/WNES/;s/L([NESW]|$)/W\1/
bx                                             # loop back to x

(ゴルフスコアの計算のために削除されたコメントとスペース)

出力:

$ sed -rf absrel.sed <<< NNWEESEE
FFLBFRLF
$ sed -rf absrel.sed <<< FFLBFRLF
NNWEESEE
$ 

説明:

ここでの考え方は、参照フレームを変更する{N, E, S, W}と、との間の直接マッピングが常に存在するということです{F, R, B, L}

絶対から相対の場合、文字列を順方向に処理します。マッピング{N, E, S, W}する各文字について{F, R, B, L}、残りを回転させます[NESW]ばかりの文字に従って文字をせ、次の文字に移動します。

絶対に相対する場合は、逆を行います。文字列を逆方向に処理し、後続のすべて[NESW]の文字を直前の文字に従って回転させます。その後、我々はその文字をマップ{N, E, S, W}{F, R, B, L}我々は文字列の先頭に到達するまで、。


0

ハスケル、224

import Data.Function
i=flip(\x->length.takeWhile(/=x))
r=['F','R','B','L']
a=['N','E','S','W']
f s@(x:_)|elem x a=map((r!!).(`mod`4).(4-))$zipWith((-)`on`(i a))('N':s)(s)|True=tail$map((a!!).(`mod`4)).scanl(+)(0)$map(i r) s

これにより、回転方向が相対方向に、方向番号が絶対方向に割り当てられ、連続する方向間の回転または連続した回転後の方向が検出されます。このi関数は、2つの凡例内でインデックスを見つけます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.