# Capture on the Pawn Chessboard

You should write a program or function which receives a string representing a chessboard with only pawns as input and outputs or returns whether any capture is possible on the board.

Input is in a FEN-like notation describing positions of white and black pawns with no other pieces present. You should decide if there is a pawn which can capture an enemy one.

Each rank is described, starting with rank 8 and ending with rank 1; within each rank, the contents of each square are described from file "a" through file "h". Each pawn is identified by a single letter (white pawn = "P", black pawn = "p", ). Empty squares are noted using digits 1 through 8 (the number of empty squares), and "/" separates ranks. (partially taken from Wikipedia)

For example

8/pppppppp/8/8/4P3/8/PPPP1PPP/8


describes the board

--------

pppppppp

P

PPPP PPP

--------


A white pawn can capture a black one if the black one is positioned diagonally up from it (black is up-left or up-right) and a black pawn can capture a white one if the white one is diagonally below from it (white is down-left or down-right). No other capture move (en passant) should be considered.

## Input

• A FEN-like string consisting of the characters 12345678pP/.
• The input describes the pawns of a valid chess game position. This means (among other more complex constraints) there will be at most 8 pawns for each side and no pawns on ranks 1 and 8.

## Output

• If there is a possible capture for either side you should output a truthy value and a falsy value otherwise.

## Examples

Inputs with truthy output (one per line)

8/7p/6P1/8/8/8/8/8
8/8/p7/1P6/3P3p/8/8/8
8/2P5/8/4P1p1/2p2P2/3p4/3p1P2/8
8/P7/8/5P2/2pp4/3P2p1/3pP3/8
8/P7/p7/p1P1P3/1P3p2/8/1p6/8
8/4p1P1/2P2P1P/2p1pPpp/8/6P1/pP1p4/8


Inputs with falsy output (one per line)

8/8/8/8/8/8/8/8
8/7P/6p1/8/8/8/8/8
8/7p/7P/8/8/8/8/8
8/pppppppp/8/8/8/8/PPPPPPPP/8
8/p7/8/1p6/5P2/8/8/8
8/p7/P7/2P1p1p1/2p5/8/PP6/8


This is code golf so the shortest entry wins.

• Shouldn't the example board be described by 8/pppppppp/8/8/8/7P/PPPP1PPP/8 ? – TheNumberOne Sep 30 '15 at 14:24
• @TheNumberOne No, 7P would mean the pawn is on the last, 8th file. (The diagram was incorrect though, I corrected that.) – randomra Sep 30 '15 at 14:47
• I feel removing en passant makes this a less interesting puzzle. – corsiKa Sep 30 '15 at 21:03
• @corsiKa en passant requires more than one board to verify. For that, a very different approach is required. – Razetime Sep 5 at 4:13
• @Razetime The same argument could be made for removing it, so meh... 5 years later is still feel the same way. – corsiKa Sep 5 at 4:16

# Pyth, 25 bytes

/smC,>JsXzM9*LN9dJ,8T"Pp


Test suite

Steps:

Transform the input by replacing the digits with the equivalent number of quote marks (N). This is saved in J. We then slice off the first 8 or 10 characters, and zip the result with the original. Any capturing pair will be transformed into "Pp", so we then find the count of that string in the resultant list. This is the output.

As a bonus, this actually counts the number of captures possible in the input.

• Another 25 solution: :sXzM9*LN9"p.{7}(..)?P"1 Sadly the last parameter of : is not optional (I think it should be). – Jakube Sep 30 '15 at 18:16
• @Jakube Will do. – isaacg Sep 30 '15 at 18:49

# Retina, 33 29 bytes

Tdw
)\d
$0. _ p.{7}(..)?P  To run the code from a single file, use the -s flag. Should be easily beatable by something like Perl where the expansion of digits into strings of spaces (or other characters) doesn't take up 17 bytes. The output is positive (truthy) if there is a possible capture and zero (falsy) if there isn't. ## Explanation Tdw )\d$0.


This is a loop of two stages. The first one is a transliteration stage which decrements each digit, and turns zeroes to underscores. Why? Because d and w expand to the following two lines:

0123456789
_0123456789AB...YZab...yz


If the target set of a transliteration stage is longer than the source set, the extraneous characters are ignored, hence the decrementing behaviour (honestly, it was just luck that I decided to put the underscore in front of the digits when expanding the w character class).

Then the second stage is a replacement, which appends a . to each digit. That means that for each digit n, n periods are added before that digit is turned into an underscore.

_
<empty>


This just gets rid of the underscores.

p.{7}(..)?P


Finally, we find the matches. Since we're ignoring en passant, captures are only possible if there is a p and then a P diagonally below it. In the linear string, this simply means that there must be 7 or 9 characters between the two pawns. This matched with .{7}(..)? (i.e. match 7 characters and then, optionally, match another two).

Such a match stage returns the number of matches it found.

• Re "Should be easily beatable by something like Perl where the expansion of digits into strings of spaces (or other characters) doesn't take up 17 bytes.": I can't get Perl to even tie your score, let alone beat it. (My Perl answer.) But maybe someone else can.... – msh210 Jun 22 '16 at 23:06

# Javascript, 272 characters

function h(t){b=[[]];for(i=-1;i++<7;){c=0;b.push(l=[]);for(j=-1;j++<7;){o=t.split('/')[i][j];switch(o){case'P':l[c++]=-1;break;case'p':l[c++]=1;break;default:c+=parseInt(o);}}}b.push([]);for(i=1;i<9;i++)for(j=0;j<8;j++)if((p=b[i][j])&&(b[i+p][j-1]||b[i+p][j+1]))return 1;}


There's probably a lot of room for improvement.

# Ruby, 145 123 46 bytes

->b{b.gsub(/\d/){|x|?.*x.to_i}=~/p.{7}(..)?P/}


Here's the test: http://ideone.com/Gzav8N

The old approach:

->b{l={}
r=p
b.split(?/).map{|s|c={}
i=0
s.chars.map{|x|n=x.to_i;c[i]=x;i+=n<1?1:n;x==?P&&r||=l[i-2]==?p||l[i]==?p}
l=c}
r}


Online test: http://ideone.com/9L01lf, version before golfing: http://ideone.com/CSmqlW

A history of modifications is available here.

## ES6, 64 bytes

An appropriate byte count, if it lasts!

f=s=>/p.{7}(..)?P/.test(s.replace(/\d/g,n=>"        ".slice(-n)))


I actually thought of this solution without reading the other answers first, but I won't mind if you don't believe me.

# Pip, 21 bytes

p.{7}(..)?PNaRXDsX_


Verify all test cases!

### Explanation

Same regex-based solution as most of the other answers.

p.{7}(..)?PNaRXDsX_
a        1st command-line argument
R       Replace
XD      regex matching a digit
sX_   with space repeated that many times
N         Count occurrences of
                      this regex:
p                       A black pawn
.{7}                   followed by any 7 characters
(..)?              optionally followed by 2 more characters
P             followed by a white pawn


# Perl 5, 30 bytes

29, plus 1 for -pe instead of -e

s/\d/1x$&/ge;$_=/p.{7}(..)?P/


A Perl copy of w0lf's Ruby answer.

# PHP, 9487 80 bytes

for(;$i++<8;)$t[$i]=$s.=" ";echo preg_match("#p.{7}(..)?P#",strtr($argv[1],$t));


That loop+strtr is a lot shorter than preg_replace_callback with str_pad.

## Jelly, 8884797269656463 60 bytes

Definitely room for improvement. Noncompeting because Jelly was created before the question. Thanks to @lirtosiast for telling me that!

ØDṖḊ
”_x
e1£¬
1£iÐ€2Ŀ€
x"3Ŀ€;"ÇFṣ”/
w€⁾pPn0
5ĿUŒDÇ
5ĿŒD6ĿoÇS


# APL (Dyalog Unicode), 47 bytes

'p.{7}(..)?P'{≢⍺ ⎕S⍬⊢⍵}('\d'⎕R{' '⍴⍨⍎⍵.Match})⍞


I wanted to make a matrix based matching solution for this, but Martin Ender's Regex ended up being simpler.

Try it online!

## Explanation

'p.{7}(..)?P'{≢⍺ ⎕S⍬⊢⍵}('\d'⎕R{' '⍴⍨⍎⍵.Match})⍞
⍞ String input
⎕R                  Perform Regex replacement
'\d'                    match all digits
{' '⍴⍨⍎⍵.Match}   Execute match(convert to number), replace with that many spaces
{≢⍺ ⎕S⍬⊢⍵}                         Tally number of matches of left argument in right
'p.{7}(..)?P'                                   Match two opposite colored pawns 7-9 spaces apart