# Will the beam hit?

A laser shoots a straight beam in one of the four orthogonal directions, indicated by <>^v. Determine whether it will hit the target O on a rectangular grid.

Each of these will hit (True):

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

>O.
...

v....
O....

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


These will miss (False):

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

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

.O.
...
.v.

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


Input: A rectangular grid of ., sized at least 2x2, with exactly one target O and one laser that's one of <>^v. The lines can be a list of strings, a 2D array or nested list of characters, or a single newline-separated string with an optional trailing newline.

Output: A consistent truthy value if the laser beam hits the target, and a consistent falsy value if it misses.

I'll consider submissions that don't use regular expressions (or built-in pattern-based string matching) as a separate category. If you put (no regex) after the language name, your answer will appear separately in the leaderboard.

var QUESTION_ID=80196,OVERRIDE_USER=20260;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/80196/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

• Related – VisualMelon May 19 '16 at 17:36
• I was hoping you would include mirrors with / and \ . Maybe for another question... – vsz May 19 '16 at 20:24
• @Mego ... which makes this challenge a lot simpler and allows for very different approaches. – Martin Ender May 20 '16 at 7:05
• @Mego I disagree; by that logic, the plain hello world challenge is a duplicate of dozens of other challenges at the same time. Anyway, thanks for notifying me about the power I now have to close/reopen code golf challenges, I wasn't aware of that. – aditsu quit because SE is EVIL May 21 '16 at 10:17
• @Mego Although this question is a special case of the other one, I don't believe it to be a dupe because the answers use totally different approaches. On that question, they all compute the path the beam takes. Portals can move the path from anywhere to anywhere which doesn't seem to a allow a shortcut, and reflectors are tricky to handle. Answers here instead mostly check or match some property of the input string. Sure, you can copy a path-tracing answer from the other challenge and remove the extra bits, but this method is overkill and gives a needlessly long solution. – xnor May 21 '16 at 18:56

# Snails, 19 bytes

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


The spec for this one can be implemented as literally as possible, no thinking required.

• Can you add an explanation of how this works? – Fund Monica's Lawsuit May 19 '16 at 18:16
• @QPaysTaxes Until feersum gets around to it, hopefully this will help: Snails is a 2D pattern matching language. udlr set the direction of the snail to up/down/left/right. | works like it does in regular regex, and ) doesn't need a matching open parenthesis. So the code pretty directly translates to "Find one of v<>^ and set the direction appropriately, then try to find an O in that direction." – FryAmTheEggman May 19 '16 at 19:13
• Yeah, what Eggman said. The only other thing is that , is like the * of regex. – feersum May 19 '16 at 21:42

# Retina, 5652423831 30 bytes

Saved 1 byte thanks to @MartinBüttner

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


Abuses properties of rectangles. Requires input to have a trailing newline.

Try it online

## Explanation

This works in three parts:

• Matching >
• Matching <
• Matching ^ and v this is because the logic for ^ and v are really the same, just the characters.

Validating <

This is simple:

O.*<


This matches an O, optionally followed by non-newline chars, then a <

Validating >

This is much the same as the previous way except the other way around. First a > is matched, then the O

Validating ^ and v

This was difficult to golf and took adverting of the input always being valid. First, we match whether it's v or an O:

[vO]


If it's an ^, the first character that's encountered should be a O. So, this matches the first character to match. Next we count the amount of .s following it up to the newline:

(.*\n)


Next, this can go into two parts, I'll cover the first:

So first, we match until the following O, using:

[^O]*O


This optionally matches all non-O characters until an O is encountered, if this is successful, then it continues... if not, then the following happens...

Now, it attempts to find the ^ using:

[^^]*\^


^ is a special character in regex so it needs to be escaped. [^^] matches all characters except ^, this works the same as the above, if this succeeds, then the following happens...

So now, one of the above has matched succesfully, the \1 checks and sees if the capture group from before (.*\n), this capture group stored the amount of .s there were after either the v or O from before, so now \1 just checks if the amount of dots in the same.

• You can save a byte by using ¶ instead of \n (Retina can handle source code in ISO 8859-1.) – Martin Ender May 20 '16 at 7:10
• @MartinBüttner thought ¶ was only \n in replacements, thanks for the tip! – Downgoat May 20 '16 at 23:57
• no it works anywhere in the source code. After splitting the file into lines, the first thing Retina does is replace the ¶ everywhere, before doing any further parsing. – Martin Ender May 21 '16 at 6:19

# Java (no regex), 413412246242212211209 198 bytes

Competing in golf challenges using java has less sense than take a part in Formula 1 race on bicycle, but I'm not always doing thinks which makes any sense.

Here is my extremely long java solution Golfed version

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


and ungolfed

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


Seems like my entire concept was wrong, here is my shorter solution

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


and ungolfed version

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


EDIT I rewrote code for looking for 'O', now it contains single loop is much shorter, and I also used @Frozn suggestion to replace some of characters with their ascii values.

In result,another 30 bytes bites the dust.

Another suggestion from @Frozn, and we are couple bytes closer to Python solution

Another rewrite drop one loop, and combine two if statements

• +1 You can remove the space between return and ( to save a byte, though. The space isn't necessary when your return value is inside parenthesis (or quotes for Strings). Source from the Java code-golfing tips. – Kevin Cruijssen May 20 '16 at 11:43
• @KevinCruijssen not saving much, but thanks:) – user902383 May 20 '16 at 12:27
• Every little bit (or should I say byte) helps I guess. ;) Besides, I don't think Java will ever win a code-golf challenge anyway. I still like doing code-golf challenges in Java though, especially since I'm currently working with Java at work. – Kevin Cruijssen May 20 '16 at 13:10
• You can replace the chars by their ASCII value: 'O' = 79, '>' = 62, '<' = 60, '^' = 94. For 'v' it's 118 but that doesn't shorten the code. – Frozn May 26 '16 at 11:13
• @Frozn as Kevin said, in every byte counts. – user902383 May 26 '16 at 11:30

# MATL (no regex), 262524 22 bytes

'>v<^'XJymfX!tZpYswJm)


Try it Online!

Modified version for all test cases

Explanation

        % 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 Now to figure out how to get rid of J – Suever May 19 '16 at 21:13
• I don't know MATL, so this may be a silly question, but why is 0 prime? – Neil May 20 '16 at 9:29
• @Neil It's letter 'O', not number 0. ASCII code for letter 'O' is 79 – Luis Mendo May 20 '16 at 10:05
• Ugh, I guess I would have still been fooled if you'd been looking for odd numbers instead. – Neil May 20 '16 at 11:35

# CJam (no regex), 25

Earlier versions were wrong, this will have to do for now:

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


Try it online

Explanation:

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


I tried a few mathematical formulas for distinguishing between "good" and "bad" strings, and for each type of formula I tried plugging in various numbers. I ended up with the HbI% above.

"good" strings for the original grid are ">O" and "O<" and they give the result 17
"good" strings for the transposed grid are "vO" and "O^" and they give the result 15
"bad" strings for both grids are: ">", "<", "^", "v", "O", "", "O>", "Ov", "<O", "^O" and they give the results 8, 6, 4, 10, 7, 0, 1, 3, 1, 3

# Python 3 (no regex), 184 bytes.

Hooray for eval hacking!

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'><'])


# TSQL (sqlserver 2012) (no regex), 358 bytes

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)


Had to use funky linechange in the declaration to force the online version to execute it(assigning values to input variables doesn't affect the length calculation anyway)

Try it online!

# Pyth, 43 bytes

KxJ"^<v>"h@Js.z}\Ohc_W>K1hf}@JKTCW!%K2.z@JK


Live demo.

## JavaScript (ES6), 78 bytes

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


Regexp of course. Turned out to be similar in principle to the Ruby answer.

# Ruby, 7155 54 bytes

Regex solution, which means that it's probably going to be easily beaten by Retina or Perl.

Returns an index number (truthy) if there is a match.

Now with a similar trick to @Downgoat Retina answer, matching for down and up beams at the same time.

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


## JavaScript (ES6) (no regex), 126 bytes

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)


Where \n represents the literal newline character.

## Clojure (no regex), 293 bytes

(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))))


Doesn't feel great. Straightforward solution, finding the index of corresponding characters and calculating if they're on the same line.

You can try it here https://ideone.com/m4f2ra

# Python (no regex), 105 bytes

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]


returns True or False

First, strips '.' and '\n' from the ends so that the characters of interest, '0<>v^', are the first and last characters.

'>O<vO^'.find(t[0]+t[-1])//3 - checks if the characters are a potentially valid arrangement. Evaluates to 0 for '>O' or 'O<', to 1 for 'vO' or 'O^', and to -1 for anything else.

'\n'in t - checks if the characters are in different rows,
len(t)%(s.find('\n')+1)!=1 - checks if they are in different columns, and
1 - is the default

The not inverts the result selected from the list, so the return expression is equivalent to:

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


# Julia (no regex), 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)


Function operating on an array of chars, normalizing by rotation, removing rows and columns containing only dots by range indexing and finally checking for location of 'O' taking into account if the remainder b is a column or row vector using matrix multiplication.

Try it online

## Python 2 (no regex), 268 bytes

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 and Falsy values returned by the function are 1 and 0, respectively.

I haven't had a chance to golf yet. Honestly, I'm not too hopeful for this one...

Any suggestions would be greatly appreciated!

# C# (No Regex), 282 bytes

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


Works like the java version but transpiled and reduced

### Expanded (Explanation included):

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


# C (ANSI) (No regex), 237 bytes

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


Expanded:

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


I think I took a decently different approach here compared to the Java or C# implementations. I got coordinates of the 'O' and arrow ((c,d) and (x,y)) and then compared them to see if the arrow was pointing in the correct direction.

Returns 0 if false and 1 if true

## Grime v0.1, 31 bytes

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


Not a very interesting solution. Prints 1 for truthy instances, and 0 for falsy ones. Try it online!

## Explanation

We simply search the input rectangle for a minimal-size (n×1 or 1×n) pattern that contains the laser and target in the correct order. The n flag makes the interpreter print the number of matches, of which there will always be at most one. The rest of the line consists of four patterns separated by |-characters, which means a logical OR: a rectangle is matched if it matches one of the patterns. The patterns work as follows:

\>.*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 "^"