相对vs绝对


17

如果某人在此网格中的A点处朝北,希望指示遵循绿色路线(因为他们只能遵循网格线)到达B点,您可能会告诉他们:

围棋North, North, West, East, East, South, East, East

或同等

围棋Forward, Forward, Left, Back, Forward, Right, Left, Forward
(其中,向右向左向后的命令隐含地意味着朝该方向转向然后前进。)

A到B路径

用一个参数编写一个函数,该函数沿相同的路径(不仅指向同一点)在这些绝对方向和相对方向之间转换。假设定向人员总是开始朝北。

如果参数是字母字符串,则NSEW返回等效的相对方向。
例如f("NNWEESEE")返回字符串FFLBFRLF

如果参数是字母字符串,则FBLR返回等效的绝对方向。
例如f("FFLBFRLF")返回字符串NNWEESEE

空字符串产生自己。假设没有其他输入情况。

如果您的语言没有函数或字符串,请使用最合适的方法。

以字节为单位的最短代码获胜。


我们是否假设一个人总是从头朝北开始?这样的话,相对来说去实现东,这需要他向右转弯,而不是简单地说,前进
优化

@Optimizer是的,北方。是的,到您的其他观点。一开始就R等于 E
卡尔文的爱好2014年

1
好极了!您更改了图片以确认我一直在想的!
贾斯汀2014年

4
您又迷上了PPCG吗?;)
Martin Ender 2014年

4
@MartinBüttner还是我很擅长掩饰我的作业问题。;)
卡尔文的爱好2014年

Answers:


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

以下格式设置为lambda表达式。它接受一个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中需要第二对括号。所以我改用C ++!
  • C ++要求为函数指定返回类型。除非我使用lambda表达式,否则!另外一个好处是,我不需要在函数名称上浪费1个字符。
  • 代码*s*9%37&4测试第一个字节;如果是以下之一,则结果为4 NESW;否则为0
  • 该代码*s%11/3将字节转换NESW为0、1、2、3
  • 该代码*s%73%10将字节转换为0、9、6、3 FRBL(即0、1、2、3模4)。
  • 将相对方向转换为绝对方向时,我不需要d变量。我尝试重新排列代码以完全消除它,但是似乎不可能...

1
我非常喜欢您将字母转换为数字的方式。:)
Emil 2014年

6

JavaScript(E6)84 86 88 92 104

编辑:使用&代替%,使用不同的运算符优先级(括号较少),并且在使用负数时效果更好
。而不是+,再次是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 2014年

是什么&& o在到底意味着什么?
贝贝

2
@bebe map函数在内部返回一个数组,作为副作用,我填充了我需要返回的o字符串。array && valueevalute到value任何阵列评估为truthy
edc65

1
最后!自从它达到88以来,我一直在盯着它。除非我缺少任何东西,否则可以替换4+(n-d&3)4|n-d&3并保存2个字符。
DocMax 2014年

4

APL,72

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

如果解释器配置可以不受处罚被改变,则得分是66,通过改变⎕IO0

{^/⍵∊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函数在两个图例中查找索引。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.