我现在在哪里?


21

我现在在哪里?

给定一个d仅包含字母的字符串,NSWE确定我经过的坐标(从左到右,贪婪地消耗)以及我所居住的最终坐标。

从左到右读取坐标的规则:

  • 如果下一个字符是NS
    • 如果N或之后的字符S是另一个NS
      • 仅消耗第一个N或第二个S
      • 输出[0,1]N
      • 输出[0,-1]S
    • 如果N或之后的字符SWE
      • 同时使用Nor SWor E
      • 输出[1,1]或分别[-1,1]用于NENW
      • 输出[1,-1]或分别[-1,-1]用于SESW
  • 如果字符前面是EW之前不是SN
    • 消费EW
    • 输出[1,0]E
    • 输出[-1,0]W

工作实例

西非国家统计局

[0,1]   (North      N)
[-1,-1] (South-west SW)
[1,0]   (East       E)
[0,0]   (N+SW+E = Didn't actually move)

请注意,这可以是任何格式,以下是有效输出的其他示例:

[[0,1],[-1,-1],[1,0],[0,0]]


[[[0,1],[-1,-1],[1,0]],[0,0]]


"0,1\n0,-1\n-1,0\n1,0\n0,0"

等等...


更多例子

斯威士尼

[-1,-1]
[1,-1]
[0,1]
[1,1]
[-1,-1]
[1,1]
[1,0]

NNEESESSWWNW

[0,1]
[1,1]
[1,0]
[1,-1]
[0,-1]
[-1,-1]
[-1,0]
[-1,1]
[0,0]

尼尼

[1,1]
[1,1]
[1,1]
[1,0]
[4,3]

EN

[1,1]
[0,1]
[1,2]

电子电气设备

[1,0]
[1,0]
[1,0]
[3,0]

规则

  • 您可以以任何不违反漏洞的方便格式输出。
  • 您必须贪婪地消费,NWE永远不要N,W,E,永远都是NW,E
    • 适用于:SW*SE*NW*NE*
    • 您正在从左到右贪婪地消费。
  • ,最低字节数获胜。

“确定我所经过的坐标”:我不确定它是否确实与随后描述的相符。这更像是“确定我所有动作的向量”。只有最终输出是实际坐标。
Arnauld

1
走到某个左右的测试用例[4, 3]将使它更容易看到测试输出中发生了什么。
林恩

3
是复数格式为1-1j(-1+1j)等一个有效的输出格式?
林恩

2
基于在给定的规则和示例中都没有这种情况,我假设input-String永远不会以'N'或'S'结尾?
凯文·克鲁伊森

1
贪婪的消费实际上有什么不同吗?既然NE不是N+E应该没关系吗?
小麦巫师

Answers:


7

Python 2,116字节

import re
a=[(int(s,35)%5-3,('N'in s)-('S'in s))for s in re.findall('[NS][EW]?|.',input())]
print a,map(sum,zip(*a))

在线尝试!

输出为[(3+4j), 1, -1j, …],91字节

lambda x:[sum(1j**(ord(c)%8%5)for c in s)for s in[x]+re.findall('[NS][EW]?|.',x)]
import re

在线尝试!

这个lambda返回一个高斯整数列表:第一个是最终坐标,所有其他都是到达那里的步骤。


5

附件,80字节

V#Sum##{Chop[1-ToBase[22260446188,3],2][Sum@Ords=>MatchAll[_,/"[NS][WE]|."]%11]}

在线尝试!

这是一个带有一个字符串参数的匿名函数。

说明

第一个任务是实现此问题的解析阶段。我发现使用简单的Regex解析输入(_)最短:

MatchAll[_,/"[NS][WE]|."]

[NS][WE]|.如许多其他答案所示,这匹配所有出现的正则表达式。贪婪地产生所需的方向。

现在,我们将对每个维度应用哈希函数。我们获取每个方向的代码点并对其求和。这给出了以下映射:

Direction       Ord-sum
E               69
N               78
S               83
W               87
NE              147
SE              152
NW              165
SW              170

我们将尝试将这些值映射到较小的域;模数对此很有用,我们可以证明导致所有给定输入的唯一值的最小模数为11。按余数排序,可以得出下表:

Direction       Ord-sum         % 11
NW              165             0
N               78              1
E               69              3
NE              147             4
SW              170             5
S               83              6
SE              152             9
W               87              10

现在,我们有一个输入对应关系,由编码Sum@Ords=>[...]%11。接下来,我们必须将这些余数转换为点。我们将尝试导出另一个映射,这意味着将“稀疏填充值”插入与方向不对应的哈希值将很有用:

Direction       Hash        Coordinates
NW              0           [-1, 1]
N               1           [0, 1]
--             (2)          [0, 0]
E               3           [1, 0]
NE              4           [1, 1]
SW              5           [-1, -1]
S               6           [0, -1]
--             (7)          [0, 0]
--             (8)          [0, 0]
SE              9           [1, -1]
W               10          [-1, 0]

当前,我们有一系列要点,这些要点可以提供一个可通过哈希索引的列表:

[-1, 1] [0, 1] [0, 0] [1, 0] [1, 1] [-1, -1] [0, -1] [0, 0] [0, 0] [1, -1] [-1, 0]

现在,我们将压缩它,看它是如何仅由-1s,0s和1s 组成的。由于列表表示成对的,因此我们可以拉平列表而不会丢失数据。然后,如果我们取每个数字x并计算,则会1-x得到以下列表:

2 0 1 0 1 1 0 1 0 0 2 2 1 2 1 1 1 1 0 2 2 1

我们可以将其转换为基数3:

20101101002212111102213

转换为基数10:

20101101002212111102213 ≡ 2226044618810

总而言之,我们采用了我们的观点,将它们取消配对,采用1从base中减去的每个元素,并从base进行转换,得出322260446188。我们可以这样解压缩:

  1. 转换为基数3: ToBase[22260446188,3]
  2. 取一个减去的每个数字(自反): 1-ToBase[22260446188,3]
  3. 重新配对清单: Chop[1-ToBase[22260446188,3],2]

这给了我们原始的一对对。然后,我们可以像这样执行上述索引:

(chopped value)[hashes]

因为在Attache中,通过数组建立索引会返回与那些索引相对应的所有元素。(因此,[1,2,3,4][ [0,0,-1,1] ] = [1,1,4,2]。)现在,我们有了OP所走路径的方向。剩下的就是计算总和。

因此,我们将此结果捕获为lambda {...}并将其作为函数composition(a##b)中的第一个函数,第二个为V#Sum。这是一个fork,在输入的情况下x,将扩展为:

V[x, Sum[x]]

Sum给定2D数组时,碰巧会对数组中的每一列求和(作为矢量化求和的结果)。因此,这将方向与最终目的地配对,我们得到了最终结果。


4

JavaScript(ES6),102个字节

返回一个字符串。

s=>s.replace(/[NS][EW]|./g,s=>(D=d=>!!s.match(d),x+=h=D`E`-D`W`,y+=v=D`N`-D`S`,[h,v]+`
`),x=y=0)+[x,y]

在线尝试!


我喜欢使用模板功能!:D
Conor O'Brien

@ ConorO'Brien是的,他们在这里很方便。到目前为止,我召集的所有哈希法术都至少更长一些。
Arnauld

4

MATL,45字节

'NS' 'WE'Z*Z{2MhX{h'eklihfmj'X{YX9\3_2&YAqts

在线尝试!验证所有测试用例

说明(带有示例)

以输入'NSWE'为例。

'NS' 'WE'  % Push these two strings
           % STACK: 'NS', 'WE'
Z*         % Cartesian product. Gives a 4×2 char matrix
           % STACK: ['NW'; 'NE'; 'SW'; 'SE']
Z{         % Cell array of rows (strings)
           % STACK: {'NW', 'NE', 'SW', 'SE'}
2M         % Push again the inputs of the second-last function call
           % STACK: {'NW', 'NE', 'SW', 'SE'}, 'NS', 'WE'
h          % Concatenate horizontally
           % STACK: {'NW', 'NE', 'SW', 'SE'}, 'NSWE'
X{         % Cell array of individual elements (chars)
           % STACK: {'NW', 'NE', 'SW', 'SE'}, {'N', 'S', 'W', 'E'}
h          % Concatenate horizontally
           % STACK: {'NW', 'NE', 'SW', 'SE', 'N', 'S', 'W', 'E'}
'eklihfmj' % Push this string
           % STACK: {'NW', 'NE', 'SW', 'SE', 'N', 'S', 'W', 'E'}, 'eklihfmj'
X{         % Cell array of individual elements (chars)
           % STACK: {'NW','NE','SW','SE','N','S','W','E'},{'e','k','l','i','h','f','m','j'}
YX         % Implicit input. Regexp replace: replaces 'NW' by 'e', then 'NE' by 'k', etc.
           % Note that the two-letter combinations are replaced first, which implements
           % the greediness; and the target letters do not appear in the source, which
           % avoids unwanted interactions between replacements
           % STACK: 'hlj'
9\         % Modulo 9 (of codepoints), element-wise
           % STACK: [5, 0, 7]
3_2&YA     % Convert to base 3 with 2 digits. Gives a 2-column matrix
           % STACK: [1, 2; 0, 0; 2, 1]
q          % Subtract 1, element-wise
           % STACK: [0, -1; -1, -1; 1, 0]
tXs        % Duplicate. Sum of each column
           % STACK: [0, -1; -1, -1; 1, 0], [0, 0]
           % Implicit display

4

Java(JDK 10),171字节

s->{var r="";int i=0,l=s.length,c,x=0,y=0,Y,X;for(;i<l;X=c>1||i<l&&(c=~-s[i]/6%4)>1&&++i>0?c*2-5:0,r+=X+","+Y+" ",x+=X,y+=Y)Y=(c=~-s[i++]/6%4)<2?1-c*2:0;return r+x+","+y;}

在线尝试!

说明

感谢c=~-s[i]/6%4,完成了以下映射:

'N' -> ascii: 78 -> -1 = 77 -> /6 = 12 -> %4 = 0
'S' -> ascii: 83 -> -1 = 83 -> /6 = 13 -> %4 = 1
'W' -> ascii: 87 -> -1 = 86 -> /6 = 14 -> %4 = 2
'E' -> ascii: 69 -> -1 = 68 -> /6 = 11 -> %4 = 3
  • NS被检查c<2并映射到+1/ -1使用1-c*2;
  • EW与检查c>1并映射到+1/ -1使用c*2-5

学分


啊,当我输入我的解释时,您发布了Java答案。:)因为我们俩都使用完全不同的方法,所以我现在暂时离开。在lambda中使用的变量太坏需要有效地最终确定,否则您可以返回String而不是List来保存字节。
凯文·克鲁伊森

谢谢,它只保存了几个字节(4),但总比没有好;)
OlivierGrégoire18年

@KevinCruijssen谢谢,起初看起来很明显,但是我正在研究另一种方法,该方法将字节数减少了30多个。“解析”一个,而不是“匹配”一个。
奥利维尔·格雷戈尔


1
@KevinCruijssen对不起,将您的更改整合在一起是一团糟...我上班了,我忘了刷新此页面...无论如何,谢谢^^'信用额很可能低于您的实际信用。太抱歉了:s
OlivierGrégoire'18

3

视网膜0.8.2,93字节

.+
$&¶$&
\G[NS]?[EW]?
$&¶
G`.
W
J
%O`.
+`EJ|NS

m`^((J)?[EJ]*)((S)?[NS]*)
$#2$*-$.1,$#4$*-$.3

在线尝试!说明:

.+
$&¶$&

复制输入。

\G[NS]?[EW]?
$&¶

将第一个副本分成多个方向。

G`.

删除上述过程创建的多余空白行。

W
J

更改WJ,使其在E和之间进行排序N。(ES和之间移动W也可以。)

%O`.

将每一行排序。

+`EJ|NS

删除成对的相反方向(这只会影响课程的最后一行)。

m`^((J)?[EJ]*)((S)?[NS]*)
$#2$*-$.1,$#4$*-$.3

计算水平和垂直移动的次数,并在必要时添加符号。

那些知道Retina 0.8.2和Retina 1之间的区别的人将要指出,我可以在Retina 1中保存2个字节,因为它使用*代替$*。当我在那里的时候,我试图简化分割过程,但是我无法进一步减少字节数,因此只能做到这一点:

L$`$(?<=(.*))|[NS]?[EW]?
$&$1

3

Java的10,269个 265 243字节

s->{var r="";int x=0,y=0,t,X,Y,a;for(;!s.isEmpty();r+=X+"|"+Y+" ",s=s.substring(++t),x+=X,y+=Y){a=s.charAt(t=0);if(s.matches("[SN][WE].*")){X=s.charAt(1)<70?1:-1;Y=1-a%2*2;t++;}else{X=a<70?1:a>86?-1:0;Y=a>69&a<87?1-a%2*2:0;}}return r+x+"|"+y;}

绝对不是解决此挑战的正确语言。

在线尝试。

说明:

s->{                  // Method with String as both parameter and return-type
  var r="";           //  Result-String, starting empty
  int x=0,            //  Ending `x`-coordinate, starting at 0
      y=0,            //  Ending `y`-coordinate, starting at 0
      t,X,Y,a;        //  Temp-integers
  for(;!s.isEmpty()   //  Loop as long as the input-String is not empty yet
      ;               //    After every iteration:
       r+=X+"|"+Y+" ",//     Append the current steps to the result-String
       s=s.substring(t),
                      //     Remove the first `t` characters from the input-String
       x+=X,y+=Y){   //      Append the ending `x`,`y` coordinates with the steps
    a=s.charAt(0);   //    Set `a` to the first character of the input-String to save bytes
    t=1;             //    Set `t` to 1
    if(s.matches("[SN][WE].*")){
                     //   Else-if the input-String starts with N/S followed by E/W:
      X=s.charAt(1)<70?1:-1;
                     //    Set `X` to 1 if 'E', -1 if 'W'
      Y=1-a%2*2;     //    Set `Y` to 1 if 'N', -1 if 'S'
      t++;}          //    Increase `t` by 1
    else{            //   Else:
      X=a<70?1:a>86?-1:0;
                     //    Set `X` to 1 if 'E', -1 if 'W', 0 if 'N' or 'S'
      Y=a>69&a<87?1-a%2*2:0;}}
                     //    Set `Y` 1 if 'N', -1 if 'S', 0 if 'E' or 'W'
  return r+x+"|"+y;} //  Append the ending coordinates, and return the result-String

1
Java答案会获得分数,尽管因为每个人都会获得分数:)。
魔术章鱼缸

@MagicOctopusUrn正确。:)而且,即使您永远不会是最矮的,我仍然喜欢用Java打高尔夫球。除非您是唯一可以回答的人(得到两个公认的Java答案。但是,对于这个挑战,OlivierGrégoire的Java答案大约短了70个字节,因此大多数投票应该交给他。
凯文·克鲁伊森


2

JavaScript(ES6),102个字节

f=
s=>s.replace(/((N)|(S))?((E)|(W))?/g,(m,v,n,s,h,e,w)=>(x+=h=!w-!e,y+=v=!s-!n,m?[h,v]+`
`:[x,y]),x=y=0)
<input oninput=o.textContent=/[^NSEW]/.test(this.value)?``:f(this.value)><pre id=o>0,0

返回一个字符串。


1

红宝石75 71字节

->x{[*x.scan(/[NS][EW]?|./),x].map{|s|s.chars.sum{|c|1i**(c.ord%8%5)}}}

在线尝试!

-4个字节,感谢benj2240。

由于返回复数看起来是可以接受的输出格式,因此我认为它不仅会带来很好的Lynn答案,而且不会带来更多的收益。


非常好。您可以通过跳过inner来节省一些字节,map直接将其块传递给sum在线尝试!
benj2240 '18

1

F#(单声道),269字节

let f s=
 let l,h=(string s).Replace("NW","A").Replace("NE","B").Replace("SW","C").Replace("SE","D")|>Seq.map(function 'N'->0,1|'S'->0,-1|'W'-> -1,0|'E'->1,0|'A'-> -1,1|'B'->1,1|'C'-> -1,-1|'D'->1,-1)|>Seq.mapFold(fun(x,y) (s,t)->(s,t),(x+s,y+t))(0,0)
 Seq.append l [h]

在线尝试!


嗨,欢迎来到PPCG。不幸的是,您缺少输出的最后一项,应该是您结束的位置。因此,对于NSWE当前正在输出(0,1)(-1,-1)(1,0),但第四输出应该是那些坐标的总和,所以(0,0)(因为0+-1+1 = 01+-1+0 = 0)。
凯文·克鲁伊森

@KevinCruijssen好吧,我没听懂。进行了更新。
Henrik Hansen

1
现在看来工作不错,所以我+1了。入住愉快!:)而且,如果您还没有看过,那么通读F#高尔夫技巧<all language>高尔夫技巧可能会很有趣。
凯文·克鲁伊森

1

sed,125

服用调戏输出格式的版本:

得分包括-rsed参数的+1 。

s/(N|S)(E|W)/\L\2,\1 /g
s/N|S/,& /g
s/E|W/&, /g
s/N|E/A/gi
s/S|W/a/gi
p
:
s/(\S*),(\S*) (\S*),(\S*)/\1\3,\2\4/
t
s/Aa|aA//
t

在线尝试

输出如下:

  • 坐标元素以逗号分隔
  • 每组坐标都用TAB分隔
  • 最终坐标在新行上
  • 所有数字均以ℤ-一元表示:
    • 字符串A表示+ ve整数len(string)
    • 字符串a表示-ve整数-len(string)
    • 空字符串代表 0

例如:

  • , 是[0,0]
  • ,AA 是[0,2]
  • aaa, 是[-3,0]

sed 4.2.2包括GNU exec扩展 147

合理的输出格式的版本:

得分包括-rsed参数的+1 。

s/(N|S)(E|W)/\L\2 \1\n/g
s/N|S/0 &\n/g
s/E|W/& 0\n/g
s/N|E/1/gi
s/S|W/-1/gi
p
:
s/(\S+) (\S+)\n(\S+) (\S+)/\1+\3 \2+\4/
t
s/\S+/$[&]/g
s/^/echo /e

输出以空格分隔的坐标给出,每行一个。在倒数第二和最后一组坐标之间还有一条换行符-不确定是否有问题。

在线尝试!


0

PHP,153个字节

让正则表达式进行拆分;循环进行比赛,打印并汇总中间结果:

preg_match_all("/[NS][EW]?|E|W/",$argn,$m);foreach($m[0]as$s){$x+=$p=strtr($s[-1],NEWS,1201)-1;$y+=$q=strtr($s[0],NEWS,2110)-1;echo"$p,$q
";}echo"$x,$y";

与管道一起运行-nR在线尝试


0

C(gcc),173字节

使用不支持正则表达式的语言来完成此操作很有趣!

f(char*s){char*t="[%d,%d]\n";int x[4]={0},i;for(;*s;*x=x[1]=!printf(t,x[1],*x))for(i=-1;i<5;)if(*s=="S NW E"[++i]){x[i/3+2]+=x[i/3]=i%3-1;i+=2-i%3;s++;}printf(t,x[3],x[2]);}

在线尝试!


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.