23
\$\begingroup\$

You are the roughest, toughest, coolest cowboy west of the Mississippi. However, some weird guy on a wacky nerd website decided that it would be cool to plop you into random unfinished landscapes and fight. No matter, you'll still win. However, to help you win those grueling gunfights you'll write home about, it's helpful to know how many bullets the coward lurking in the landscape has.

How about you help this poor guy out. Given an ASCII landscape, find the gun inside it and tell him how many bullets are loaded into it. This is the gun:

  (X)
(X\ /X)
 (XVX)
  \X/

Each X in the above picture is a potential slot for a bullet. The slot will either contain a space or one of 0,O,o (may not be consistent - the cowboy may have loaded different types of bullets in his gun).

There will always be exactly one gun, matching the above description, in the landscape. However, please note that the spaces around and inside the gun can contain anything.

Input

You will be given a string containing printable ASCII (so not tabs) and newlines to separate lines. You may also take a list of strings, if you wish. Strings will all be padded with spaces, so they will all be the same length. The input will be at least 4 rows high and 7 columns wide.

There will always be exactly one gun in the landscape.

Output

You will output how many bullets (0, O, o) there are in the gun, so your output will always between 0 and 6.

Test Cases

  (0)   ( )
(o\ /o( \ / )
 (oVo) ( V )
  \o/   \ /

0

----------------------------
////////////////////////////
////////////////////////////
/////////////(o)////////////
///////////(0\// )//////////
////////////( Vo)///////////
/////////////\ /////////////
////////////////////////////
----------------------------

3

()()()()()()()()()()()()()()()()\)/)()()()()()()()()()()()()
()()()()()()()()()()()()()()()()(V)()()()()()()()()()()()()(
()()()()()()()(\0/)()()()()()()()()()()()()()()()()()()()()(
()()()()()()()()()()()()()()()()()()()()()()()( )()()()()()(
()()()()()()(o)()()()()()()()(00)()()()()()(( \(/0)()()()()(
()()()()()()()()()()()()()()()()()()()()()()(( V )()()()()()
()()()()()()()()()()()()()()()()()()()()()()()\O/()()()()()(

2

------(0)---
||||(0\|/0)
-----(0V0)--
||||||\0/
-------_------
|||||||-|
------|-|
|||||||-|
------|-|

6

00ooOO(0)/\\/V

  ( )
( \\/ )
 ( V )
 \\ /

00OOoo()()()())))

0

  (\)     (0)
(0\\/0) ( \0/ )
 (0V0)   ( V )
 \\0/     \ /

1 (left gun is invalid because of the `\` in the bullet slot)

-00(0)00\0
-(O\0/o)\ 
- (OVo)o\0
-o \ /oo/ 

5

This is , so shortest answer in bytes wins.

\$\endgroup\$
  • \$\begingroup\$ Sandbox \$\endgroup\$ – Stephen Jul 1 '17 at 17:45
  • 10
    \$\begingroup\$ +1 If someone FGITWs this challenge ;) \$\endgroup\$ – Beta Decay Jul 1 '17 at 18:02
  • 2
    \$\begingroup\$ You should add a test case where there's a 0 inside the gun's bounding box but outside the gun. \$\endgroup\$ – Martin Ender Jul 1 '17 at 18:20
  • \$\begingroup\$ @StepHen Oh right, there's the one zero inside the gun that doesn't belong to it. It would be good to have zeros outside the gun but within its bounding box as well though. \$\endgroup\$ – Martin Ender Jul 1 '17 at 18:21
  • \$\begingroup\$ "The input will be at least 4 rows high and 5 columns wide." - if there is always a gun then the input must be at least 7 columns wide. \$\endgroup\$ – manassehkatz Jul 2 '17 at 14:30
19
\$\begingroup\$

Snails, 71 bytes

Try it online.

A
\/a=\)2w\V={\\u\(}c=\/b={\\c\(2}u!{(nb|.|.n.)=^o=^O=^0^ }{nb|.|.n.}^ 
\$\endgroup\$
  • 4
    \$\begingroup\$ Programming language for 2-dimensional pattern matching. you must be glad I made this challenge then :P \$\endgroup\$ – Stephen Jul 1 '17 at 18:35
  • 25
    \$\begingroup\$ Do you have a link to this language? It's pretty funny that the fastest gun in the west is a snail. \$\endgroup\$ – PyRulez Jul 1 '17 at 20:24
  • 1
    \$\begingroup\$ @PyRulez Here is a link for you \$\endgroup\$ – ovs Jul 1 '17 at 20:32
  • 6
    \$\begingroup\$ @PyRulez you can click the language name on the TIO page \$\endgroup\$ – Stephen Jul 1 '17 at 20:59
  • \$\begingroup\$ I am interested in how this works. \$\endgroup\$ – Cows quack Jul 2 '17 at 6:09
6
\$\begingroup\$

Mathematica, 170 bytes

Catch@BlockMap[b="O"|"o"|"0";MatchQ[#,p=Characters@{"  (X)  ","(X\\ /X)"," (XVX) ","  \\X/  "}/." "->_/."X"->$;p/.$->b|"X"|" "]&&Throw@Count[Pick[#,p,$],b,2]&,#,{4,7},1]&

Takes an array of strings/chars. Returns the number of bullets.

\$\endgroup\$
4
\$\begingroup\$

JavaScript, 215 211 209 bytes

Thanks to Shaggy for -4 bytes!

f=

i=>[...i].map((_,x)=>eval(String.raw`a=i.match(/(\n|^).{${x}}..\(${Z='([oO0 ])'}\).*\n.{${x}}\(${Z}\\.\/${Z}\).*\n.{${x}}.\(${Z}V${Z}\).*\n.{${x}}..\\${Z}\//);a&&alert(a.filter(i=>/^[oO0]$/.test(i)).length)`))

tests = [["  (0)   ( )\n(o\\ /o( \\ / )\n (oVo) ( V )\n  \\o/   \\ /",0],["----------------------------\n////////////////////////////\n////////////////////////////\n/////////////(o)////////////\n///////////(0\\// )//////////\n////////////( Vo)///////////\n/////////////\\ /////////////\n////////////////////////////\n----------------------------",3],["()()()()()()()()()()()()()()()()\\)/)()()()()()()()()()()()()\n()()()()()()()()()()()()()()()()(V)()()()()()()()()()()()()(\n()()()()()()()(\\0/)()()()()()()()()()()()()()()()()()()()()(\n()()()()()()()()()()()()()()()()()()()()()()()( )()()()()()(\n()()()()()()(o)()()()()()()()(00)()()()()()(( \\(/0)()()()()(\n()()()()()()()()()()()()()()()()()()()()()()(( V )()()()()()\n()()()()()()()()()()()()()()()()()()()()()()()\\O/()()()()()(",2],["------(0)---\n||||(0\\|/0)\n-----(0V0)--\n||||||\\0/\n-------_------\n|||||||-|\n------|-|\n|||||||-|\n------|-|",6],["00ooOO(0)/\\\\/V\n\n  ( )\n( \\\\/ )\n ( V )\n \\\\ /\n\n00OOoo()()()())))",0],["  (\\)     (0)\n(0\\\\/0) ( \\0/ )\n (0V0)   ( V )\n \\\\0/     \\ /",1]]

alert = x => i = x;

tests.forEach((t, index) => {
    i = 'Not Found'
    f(t[0]);
    document.getElementById('a').textContent += t[0] + '\n\n' + i + '\n\n';
    if (i != t[1]) {
        document.getElementById('a').textContent += 'Failed test ' + index + '! Expected '  + t[1] + '\n\n';
        document.getElementById('a').style = 'color: red'
    }
})
<pre id="a"></pre>

Basically, tries to match a gun n characters after a line break, for n from 0 to the length of the string.

\$\endgroup\$
  • \$\begingroup\$ Save a few bytes by assigning to Z within the literal, the first time you use it and getting rid of the {}. \$\endgroup\$ – Shaggy Jul 3 '17 at 16:52
  • \$\begingroup\$ @Shaggy Thanks! \$\endgroup\$ – Artyer Jul 3 '17 at 17:53
3
\$\begingroup\$

Python 2, 219 224 227 bytes

import re
f=lambda s:sum(sum(g>' 'for g in m.groups())for m in[re.match(r'.*@..\(X\)..@\(X\\./X\)@.\(XVX\).@..\\X/.*'.replace('X','([0Oo ])').replace('@',r'[^\n]*\n.{%d}'%i),'\n'+s,re.DOTALL)for i in range(0,s.find('\n'))]if m)

EDIT: Fixed a bug which cost me 5 bytes :(... found 3 bytes of extra r''s that weren't needed. And then Grrr!! Was not counting \ chars in my code correctly, so added 6...

Takes a string with newlines; retuns the number of bullets found.

Basically, applies a regex that looks for the gun pattern with 0, 1, ... lineLength characters of pad at the beginning of the lines.

\$\endgroup\$
3
\$\begingroup\$

C (gcc), 357 351 bytes

#define M(F,C)F(i){i=s[i]==C;}
b,i;char*s,c;M(L,'(')M(R,')')M(A,'/')M(D,'\\')M(V,'V')B(i){i=b=(c=s[i])==32?b:c==111?b+1:c==79?b+1:c==48?b+1:0;}(*t[])(int)={L,B,R,L,B,D,A,B,R,L,B,V,B,R,D,B,A};main(j,v,k,l)char**v;{for(s=v[1];s[l++]!=10;);for(;k=i,s[i++];){for(j=17;j--;)if(!(t[j])(k-=j==13?l-3:j==8?l-5:j==5?2:j==2?l-4:1))break;b=j<0?putchar(b+47):1;}}

Try it online! (golfed) (expanded) (357 golfed) (357 expanded)

I wondered how bad a solution would be in a language without built-in pattern matching. It came out a lot smaller than I feared.

Basically, this approach breaks the gun down into a series of individual parts it expects to see in specific locations relative to a specific index. If all parts are found where they are expected, it's a gun! The bullet test increments a global counter to keep track of how many bullets were in it, which we print when we have found the one and only gun in the landscape.

Note 1: I padded the test cases with spaces to ensure consistent row widths.

Note 2: Add 10 bytes if you don't like the assign instead of return trick. For clarity, I used actual return statements in the expanded code.

\$\endgroup\$
  • \$\begingroup\$ Three minor optimizations: - Use putchar with b's value directly instead of printf (3 bytes). - Use ternary operator instead of if statement to print bullet count (1 byte). - Roll bullet count initialization into print ternary (2 bytes). The last one is a bit smelly since it means b is zero when testing the first index, but since no gun could be at index 0 anyway, I think it's a fair change. \$\endgroup\$ – jiv Jul 3 '17 at 16:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.