光束会命中吗?


31

激光沿正交的四个方向之一发射直光束<>^v。确定它是否会击中O矩形网格上的目标。

这些都将击中(True):

.....
...O.
.....
...^.
.....

>O.
...

v....
O....

...........
...........
O.........<
...........

这些会错过(错误):

......
......
.^..O.

......
.....>
O.....
......
......


.O.
...
.v.

.....<.
..O....

输入:.大小至少为2x2的矩形网格,正好有一个目标O,一个激光是之一<>^v。这些行可以是字符串列表,二维数组或嵌套的字符列表,也可以是单个新行分隔的字符串,并带有可选的尾随新行。

输出:如果激光束击中目标,则真值保持一致,如果未击中,则真值保持不变。

我将考虑不使用正则表达式(或内置的基于模式的字符串匹配)的提交作为单独的类别。如果(no regex)在语言名称后面加上空格,您的答案将单独出现在排行榜中。



6
我希望您能在/和中加入镜子\ 。也许还有一个问题……
vsz

2
@Mego ...使得这个挑战变得简单得多,并允许非常不同的方法。
Martin Ender

2
@Mego,我不同意;按照这种逻辑,普通的hello world挑战是同时存在许多其他挑战的重复。无论如何,感谢您通知我现在必须关闭/重新打开代码高尔夫球挑战的功能,但我并没有意识到。
aditsu

5
@Mego尽管这个问题是另一个问题的特例,但我不认为这是一个骗子,因为答案使用的是完全不同的方法。在这个问题上,他们都计算出光束所经过的路径。门户网站可以将路径从任何地方移动到似乎不允许快捷的任何地方,并且反射器很难处理。相反,这里的答案主要是检查或匹配输入字符串的某些属性。当然,您可以从其他挑战中复制路径跟踪答案并删除多余的位,但是此方法过大且不必要地提供了冗长的解决方案。
xnor

Answers:


27

蜗牛,19字节

\>|\<l|\^u|\vd).,\O

此规范可以在不考虑任何思想的情况下尽可能地实现。


6
您能补充一下它的工作原理吗?
基金莫妮卡的诉讼

5
@QPaysTaxes在feersum熟悉它之前,希望这会有所帮助:Snails是2D模式匹配语言。udlr将蜗牛的方向设置为上/下/左/右。|就像在常规正则表达式中一样工作,并且)不需要匹配的开放括号。因此,代码可以直接转换为“找到其中一个v<>^并适当设置方向,然后尝试在该方向上找到一个O”。
FryAmTheEggman's

是的,Eggman说了什么。唯一的另一件事是,,就像是*正则表达式。
feersum '16

13

视网膜,56 52 42 38 31 30字节

@MartinBüttner节省了1个字节

O.*<|>.*O|[vO](.*¶)[^O]*[O^]\1

滥用矩形的属性。需要输入才能包含尾随换行符。

在线尝试

说明

它分为三个部分:

  • 匹配 >
  • 匹配 <
  • 匹配^v,这是因为逻辑^v真的一样的,只是人物。

证实 <

这很简单:

O.*<

这与匹配O,可选地后面跟非换行符,然后是<

证实 >

除另一种方法外,这与以前的方法几乎相同。首先>匹配一个,然后匹配O

验证^v

这很难打高尔夫,并且广告的输入始终是有效的。首先,我们匹配是v还是O

[vO]

如果为^,则遇到的第一个字符应为O。因此,这匹配要匹配的第一个字符。接下来,我们计算.跟随s直到换行符的s 的数量:

(.*\n)

接下来,这可以分为两部分,我将介绍第一部分:

因此,首先,我们O使用以下命令匹配直到以下内容:

[^O]*O

可以选择匹配所有非O字符,直到O遇到为止,如果成功,则继续...如果不成功,则发生以下情况...

现在,它尝试查找^使用方法:

[^^]*\^

^是正则表达式中的特殊字符,因此需要进行转义。[^^]匹配除以外的所有字符^,与上面的相同,如果成功,则发生以下情况...

因此,现在,上述条件之一已成功匹配,\1检查并查看捕获组是否来自before (.*\n),此捕获组存储了.s vOfrom之前的s 数量,因此现在\1仅检查是否存在相同。


您可以使用代替来保存字节\n(Retina可以处理ISO 8859-1中的源代码。)
Martin Ender,

@MartinBüttner认为只能替代\ n,谢谢小费!
Downgoat '16

不,它在源代码中的任何地方都有效。将文件分割成几行后,Retina要做的第一件事是在进行任何进一步解析之前替换所有内容。
马丁·恩德

9

的Java(没有正则表达式),413 412 246 242 212个 211 209 198字节

与使用Java参加高尔夫挑战赛相比,参加自行车一级方程式比赛的意义不大,但是我并不总是认为这有意义。

这是我极长的Java解决方案高尔夫版本

boolean l(char[][]w){int[]t={},l={};for(int y=0;y<w.length;y++)for(int x=0;x<w[0].length;x++){if(w[y][x]=='O')t=new int[]{x,y};if(w[y][x]=='<')l=new int[]{x,y,1};if(w[y][x]=='>')l=new int[]{x,y,2};if(w[y][x]=='v')l=new int[]{x,y,3};if(w[y][x]=='^')l=new int[]{x,y,4};};return(l[2]==1&&l[1]==t[1]&&l[0]>t[0])||(l[2]==2&&l[1]==t[1]&&l[0]<t[0])||(l[2]==3&&l[0]==t[0]&&l[1]<t[1])||(l[2]==4&&l[0]==t[0]&&l[1]>t[1]);}

而且没有高尔夫球

boolean l(char[][] w) {
    int[] t = {}, l = {};
    for (int y = 0; y < w.length; y++)
        for (int x = 0; x < w[0].length; x++) {
            if (w[y][x] == 'O')
                t = new int[] { x, y };
            if (w[y][x] == '<')
                l = new int[] { x, y, 1 };
            if (w[y][x] == '>')
                l = new int[] { x, y, 2 };
            if (w[y][x] == 'v')
                l = new int[] { x, y, 3 };
            if (w[y][x] == '^')
                l = new int[] { x, y, 4 };
        }
    ;
    return (l[2] == 1 && l[1] == t[1] && l[0] > t[0])
            || (l[2] == 2 && l[1] == t[1] && l[0] < t[0])
            || (l[2] == 3 && l[0] == t[0] && l[1] < t[1])
            || (l[2] == 4 && l[0] == t[0] && l[1] > t[1]);
}

似乎我的整个概念是错误的,这是我的较短解决方案

boolean z(char[][]w){int x=0,y=0,i=0,a=w.length,b=w[0].length;for(;w[y][x]!=79;)if(++y==a){y=0;x++;}for(;i<(a<b?b:a);)if(i<b&w[y][i]==(i<x?62:60)|i<a&w[i][x]==(i++<y?'v':94))return 1<2;return 1>2;}

和非高尔夫版本

oolean z(char[][] w) {
        int x = 0, y = 0, i = 0, a = w.length, b = w[0].length;
        for (; w[y][x] != 79;)
            if (++y == a) {
                y = 0;
                x++;
            }
        for (; i < (a < b ? b : a);)
            if (i < b & w[y][i] == (i < x ? 62 : 60) | i < a
                    & w[i][x] == (i++ < y ? 'v' : 94))
                return 1 < 2;
        return 1 > 2;
    }

编辑 我重新编写了代码以查找'O',现在它包含的单循环要短得多,并且我还使用@Frozn建议用其ascii值替换某些字符。

结果,又有30个字节咬住了灰尘。

@Frozn的另一个建议,我们离Python解决方案还差几个字节

另一个重写放置一个循环,并合并两个if语句


1
+1您可以删除空间之间return(保存一个字节,虽然。当您的返回值在括号(或字符串的引号)内时,则不需要空格。来自Java代码查询技巧的源代码。
凯文·克鲁伊森,2016年

@KevinCruijssen没有节省太多,但是谢谢:)
user902383 '16

每一点(或者我应该说字节)都可以帮助我猜测。;)此外,我认为Java也不会赢得代码高尔夫挑战。不过,我仍然喜欢用Java编写代码挑战,特别是因为我目前正在使用Java。
凯文·克鲁伊森

你可以通过自己的ASCII值替换字符:'O' = 79'>' = 62'<' = 60'^' = 94。对于“ v”,它是118,但这不会缩短代码。
Frozn

正如Kevin所说,@ Frozn在每个字节中都很重要。
user902383 '16

7

MATL(无正则表达式),26 25 24 22字节

'>v<^'XJymfX!tZpYswJm)

在线尝试!

所有测试用例的修改版本

说明

        % Implicitly grab input
'>v<^'  % String literal indicating the direction chars
XJ      % Store in the J clipboard
y       % Copy the input from the bottom of the stack
m       % Check to see which of the direction chars is in the input. The
        % result is a 1 x 4 logical array with a 1 for the found direction char
f       % Get the 1-based index into '>v<^' of this character
X!      % Rotate the input board 90 degrees N times where N is the index. This
        % Way we rotate the board so that, regardless of the direction char,
        % the direction char should always be BELOW the target in the same column
t       % Duplicate
Zp      % Determine if any elements are prime ('O' is the only prime)
Ys      % Compute the cumulative sum of each column
w       % Flip the top two stack elements
J       % Grab '>v<^' from clipboard J
m       % Create a logical matrix the size of the input where it is 1 where
        % the direction char is and 0 otherwise
)       % Use this to index into the output of the cumulative sum. If the 
        % direction char is below 'O' in a column, this will yield a 1 and 0 otherwise
        % Implicitly display the result

@LuisMendo现在弄清楚如何摆脱J
Suever

我不知道MATL,所以这可能是一个愚蠢的问题,但是为什么0是素数?
尼尔,

3
@Neil是字母'O',而不是数字0。字母的ASCII码'O'79
Luis Mendo,

gh,如果您一直在寻找奇数,我想我还是会上当。
尼尔,

5

CJam(无正则表达式),25岁

早期版本是错误的,现在必须这样做:

q~_z]{'.-HbI%}f%[HF].&~+,

在线尝试

说明:

q~         read and evaluate the input (given as an array of strings)
_z         copy and transpose
]          put the original grid and transposed grid in an array
{…}f%      map the block to each grid (applying it to each string in each grid)
  '.-      remove all dots (obtaining a string of 0 to 2 chars)
  Hb       convert to base H=17, e.g. ">O" -> 62*17+79=1133
  I%       calculate modulo I=18
[HF]       make an array [17 15]
.&         set-intersect the first array (mapped grid) with 17 and 2nd one with 15
~+         dump and concatenate the results
,          get the array length

我尝试了一些数学公式来区分“好”和“坏”字符串,对于每种类型的公式,我都尝试插入各种数字。我最终得到了HbI%以上。

原始网格的“好”字符串为“> O”和“ O <”,它们给出的结果为17。
换位网格的“好”字符串为“ vO”和“ O ^”,它们给出的结果为15
“坏”。两个网格的字符串是:“>”,“ <”,“ ^”,“ v”,“ O”,“”,“ O>”,“ Ov”,“ <O”,“ ^ O”,它们给出结果8,6,4,10,7,0,1,3,1,3


3

Python 3(无正则表达式),184个字节。

万岁黑客入侵!

def f(a,o=0,d={},q=''):
 for r in a:
  i=0
  for c in r:d[c]=o,i;i+=1;q=(c,q)[c in'O.']
  o+=1
 z,y=d['O'];e,j=d[q];return eval("z%se and y%sj"%(('><'[q<'v'],'=='),('==',q))[q in'><'])

3

TSQL(sqlserver 2012)(无正则表达式),358字节

DECLARE @ varchar(1000)=
'......'+ CHAR(13)+CHAR(10)+
'......'+ CHAR(13)+CHAR(10)+
'...0..'+ CHAR(13)+CHAR(10)+
'...^..'+ CHAR(13)+CHAR(10)
;

WITH C as(SELECT
number n,SUBSTRING(@,number,1)a,1+min(IIF(SUBSTRING(@,number,1)=char(13),number,99))over()m
FROM master..spt_values
WHERE'P'=type and
SUBSTRING(@,number,1)in('>','<','^','v','0',char(13)))SELECT
IIF(c.n%c.m=d.n%c.m and c.a+d.a in('0^','v0')or
c.n/c.m=d.n/c.m and c.a+d.a in('>0','0<'),1,0)FROM c,c d
WHERE c.n<d.n and char(13)not in(c.a,d.a)

必须在声明中使用时髦的linechange来强制在线版本执行它(将值分配给输入变量无论如何都不会影响长度计算)

在线尝试!



2

JavaScript(ES6),78个字节

s=>s.match(`>.*O|O.*<|(?=v)([^]{${l=s.search`\n`+1}})+O|(?=O)([^]{${l}})+\\^`)

正则表达式当然。事实证明,其原理与Ruby答案相似。


2

Ruby,71 55 54字节

正则表达式解决方案,这意味着它可能会被Retina或Perl轻易击败。

如果存在匹配项,则返回一个索引号(真)。

现在具有与@Downgoat Retina答案类似的技巧,可以同时匹配上下光束。

->m{m=~/>\.*O|O\.*<|(?=[vO])(.{#{??+m=~/\n/}})+[O^]/m}

2

JavaScript(ES6)(无正则表达式),126个字节

s=>([n,o,l,r,u,d]=[..."\nO<>^"].map(c=>1+s.indexOf(c)),l>o&l-o<n&l%n>o%n||r&&r<o&o-r<n&r%n<o%n||u>o&u%n==o%n||d&&d<o&d%n==o%n)

其中\n代表文字换行符。


2

Clojure(无正则表达式),293字节

(defn z[f](let[v(sort(keep-indexed(fn[i v](if(some #{v}[\v\>\<\^\O])[(if(= v\O)\& v)i]))f))l(+(.indexOf f"\n")1)d((nth v 1)0)q((nth v 1)1)p((nth v 0)1)r(=(quot p l)(quot q l))i(> q p)](cond(= d\^)(and i(=(mod(- q p)l)0))(= d\v)(and(not i)(=(mod(- p q)l)0))(= d\>)(and(not i)r):else(and i r))))

感觉不太好。简单的解决方案,找到相应字符的索引并计算它们是否在同一行上。

您可以在这里尝试https://ideone.com/m4f2ra


2

Python(无正则表达式),105字节

def f(s):t=s.strip('.\n');return not['\n'in t,len(t)%(s.find('\n')+1)!=1,1]['>O<vO^'.find(t[0]+t[-1])//3]

返回True或False

首先,去除“。”。和'\ n'从头开始,这样感兴趣的字符'0 <> v ^'是第一个和最后一个字符。

'>O<vO^'.find(t[0]+t[-1])//3-检查字符是否可能有效。对于'> O'或'O <',其值为0;对于'vO'或'O ^',其值为1;对于其他任何值,其值为-1。

'\n'in t-检查字符是否在不同的行中,
len(t)%(s.find('\n')+1)!=1-检查字符是否在不同的列中,以及
1 -是默认设置

not反转结果从列表中选择,所以return表达式等价于:

t[0]+t[-1] in '>0<' and '\n' not in t or t[0]+t[-1] in 'vO^' and len(t)%(s.find('\n')+1)==1

2

朱莉娅(未使用正则表达式),98岁

a->(c=rotr90(a,findlast("i1Q/",sum(a-46)));
    f(n)=find(any(c.!='.',n));b=c[f(2),f(1)];
    (b'*b)[1]==97)

函数对char数组进行操作,通过旋转进行归一化,通过范围索引删除仅包含点的行和列,最后考虑矩阵b是否是列或行向量,并考虑矩阵余数来确定'O'的位置。

在线尝试


1

Python 2(无正则表达式),268个字节

import numpy
def q(i):
 s=numpy.asmatrix(i)
 for n in s:
  n=n.tolist()[0]
  try:
   a=n.index("0")
   if n.index(">")<a or n.index("<")>a:return 1
  except:0
 for n in range(len(i)):
  c=[x[0] for x in s[:,n].tolist()]
  try:
   a=c.index("0")
   if c.index("v")<a or c.index("^")>a:return 1
  except:0
 return 0

该函数返回的Truthy和Falsy值分别为1和0。

我还没有机会打高尔夫球。老实说,我对此不太希望...

任何建议将不胜感激!


1

C#(无Regex),282个字节

bool F(char[,]b){int k=0,l=1,m=1,n=0,o=0;for(int x=0;x<b.GetLength(0);x++)for(int y=0;y<b.GetLength(1);y++){char i=b[x,y];if(i=='O'){k=x;l=y;}if(new[]{'<','>','^','v'}.Contains(i)){m=x;n=y;o=i;}}return(o==60&&k==m&&l<n)||(o==62&&k==m&&l>n)||(o==94&&l==n&&k<m)||(o==118&&l==n&&k>m);}

像Java版本一样工作,但经过编译和精简

扩展(包括说明):

bool F(char[,] b)
{
    // declare variables for goal x, goal y, laser x, laser y, and laser direction respectively (laser direction is char code for directions)
    int k = 0, l = 0, m = 0, n = 0, o = 0;
    // go through each cell
    for (int x = 0; x < b.GetLength(0); x++)
    {
        for (int y = 0; y < b.GetLength(1); y++)
        {
            // get cell contents
            char i = b[x, y];
            // set goal position if goal
            if (i == 'O')
            {
                k = x;
                l = y;
            }
            // set laser position and direction if laser
            if (new[]{ '<', '>', '^', 'v' }.Contains(i))
            {
                m = x;
                n = y;
                o = i;
            }
        }
    }
    // check everything is on the same line and in right direction
    return (o == 60 && k == m && l < n) ||
           (o == 62 && k == m && l > n) ||
           (o == 94 && l == n && k < m) ||
           (o == 118 && l == n && k > m);
}

0

C(ANSI)(无正则表达式),237个字节

#define l b[1][i]
main(i,b,c,d,x,y,z,p)char **b;{for(y=z=i=0,x=1;z<2&&(l==10?x=0,++y:1);i++,x++)if(l>46){if(l!=79)p=l;if(!z++)c=x,d=y;}i--;x--;z=(c==x)*((p=='v')*(l==79)+(p==94)*(l==p))+(d==y)*((p==60)*(l==p)+(p==62)*(l==79));return z;}

展开:

#define l b[1][i]
main(i,b,c,d,x,y,z,p)char **b;{
    for(y=z=i=0,x=1;z<2&&(l==10?x=0,++y:1);i++,x++)
        if(l>46){if(l!=79)p=l;if(!z++)c=x,d=y;}
    i--;x--;
    z=(c==x)*((p=='v')*(l==79)+(p==94)*(l==p))+(d==y)*((p==60)*(l==p)+(p==62)*(l==79));
    printf("%i\n",z);
    return z;
}

与Java或C#实现相比,我认为我在这里采取了截然不同的方法。我得到了“ O”和箭头((c,d)和(x,y))的坐标,然后将它们进行比较以查看箭头是否指向正确的方向。

如果为false,则返回0,如果为true,则返回1


0

Grime v0.1,31个字节

n`\>.*a|a.*\<|\v/./*/a|a/./*/\^

这不是一个非常有趣的解决方案。打印1真实的实例和虚假的实例0在线尝试!

说明

我们只需在输入矩形中搜索最小尺寸(n×1或1×n)的图案即可,该图案包含正确顺序的激光和目标。该n`标志使解释器打印匹配的数目,其中始终最多有一个。该行的其余部分由四个由- |字符分隔的模式组成,这意味着逻辑或:如果矩形与其中一种模式匹配,则该矩形匹配。这些模式的工作方式如下:

\>.*a    Literal ">", horizontal row of any chars, one alphabetic char
a.*\<    One alphabetic char, horizontal row of any chars, literal "<"
\v/./*/a Literal "v", on top of vertical column of any chars, on top of one alphabetic char
a/./*/\^ One alphabetic char, on top of vertical column of any chars, on top of literal "^"
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.