Passwords Strong Against Bishops Not to be confused with Password Bishop Goodness!

Given a string, answer (truthy/falsy or two consistent values) if it constitutes a password which is strong against bishops.

A password is strong against bishops if it is a string consisting of alternating letters (in a-h) and digits (in 1-8) such that each pair of characters can be interpreted as a square on a chessboard, and if you place a white pawn on each square named in the password, then there is no way for a white bishop to travel, in any number of consecutive moves, from any square in the first (1) row to any square in the last (8) row.

Examples

Passwords strong against bishops


a1b1c1d1e1f1g1h1
a8b8c8d8e8f8g8h8
a1b2c3d4d5f5f4g3g4h2b5
h4g4f4e4c4b4a4c3e3
a1b1c1d1e1f1g1a8b8c8d8e8f8g8
b4b5d4d5f4f5g3h5



   For example, a1b1c1d1e1f1g1a8b8c8d8e8f8g8 corresponds to the position  and b4b5d4d5f4f5g3h5 corresponds to the position 


Passwords weak against bishops


a4c4e4g4g5d6f6e3d2b2 (well-formed but not strong — thanks Jo King for this example!)
b1c1d1e1f1g1h1a8b8c8d8e8f8g8 (well-formed but not strong)
h4g4f4e4c4b4a4c3 (well-formed but not strong)
d4 (well-formed but not strong)
b4b5d4d5f4f5g2h5 (well-formed but not strong)
correct horse battery staple (ill-formed)
1a1b1c1d1e1f1g8a8b8c8d8e8f8g (ill-formed)
a (ill-formed)
aa (ill-formed)
Ruby, 115 182 163 bytes



-&gt;s{z=('00'..'99').map{|x|x=~/[09]/||s[(x[1].ord+48).chr+x[0]]};(11..18).map &amp;g=-&gt;x{z[x]||[x-11,x-9,x+z[x]=9,x+11].map(&amp;g)};s=~/^([a-h][1-8])*$/&amp;&amp;(z[81,9]-[9])[8]}


Try it online!

Returns 1 for strong and nil for weak. (The +67 bytes was for taking into account "backtracking.")

-&gt;s{
 z=                             # this is the board
 ('00'..'99').map{|x|           # coordinates are described as y*10 + x
  x=~/[09]/||                   # truthy if out of bounds...
  s[(x[1].ord+48).chr+x[0]]     # ...or impassable
 }                              # now only the passable squares are falsey
 (11..18).map                   # for each x position at y=1,
  &amp;g=-&gt;x{                       # call helper function on that square
   z[x]||                       # if the square is passable (i.e. falsey),
    [x-11,x-9,x+z[x]=9,x+11]    # mark it impassable by setting to 9 (truthy)
     .map(&amp;g)                   # call helper recursively for each neighbor
  }
 s=~/^([a-h][1-8])*$/           # make sure the input was valid,
 &amp;&amp;(z[81,9]-[9])[8]             # and check that the last row was never reached
}


A few tricks that were used:


Instead of the numerical range 0..99, we use the string range '00'..'99' so that the number is automatically left-padded to 2 digits and stringified. This makes out of bounds checking very short -- match with regex /[09]/.
Inside the helper function, while building the list of new coordinates [x-11, x-9, x+9, x+11], we simultaneously assign z[x] to 9 in the process, which happens to be a truthy value (marking the square visited).
In the last line, we want to check that the array z[81,9] does not contain 9. We do this by removing all instances of 9 (z[81,9]-[9]), then asking for the 9th element of the resulting array ([8]). Since we know the array originally had 9 elements, if any were removed, we'll get nil, whereas if they all remained, we'll get the last element of the array (which happens to always be 1).