Is my prison secure?

Snails, 13 bytes

!(t\P(o\ ),o~

Try it online!

Prints 0 for insecure prisons and the size of the input's bounding box for secure prisons.

The idea is to ensure that we can't find a path from a P to an out of bounds cell (~) moving only orthogonally (o) through spaces. The t is a teleport so that regardless where we attempt the match it tries all possible starting positions to find a P.


C# (.NET Core), 485 480 474 470 421 408 bytes

The absolutely wrong tool and approach, but nonetheless...

  • 7 bytes (and more) saved with the useful tips from TheLethalCoder.
  • 4 bytes saved by returning an integer.
  • 4 more bytes saved thanks (once again) to TheLethalCoder by replacing ' ' with 32 in the comparisons.
  • LOTS of bytes saved by refactoring the code.
  • 13 more bytes thanks to (guess who?) TheLethalCoder. :) I keep forgetting his tips and he keeps reminding me them.
m=>{var p='P';int a=m.Length,b=m[0].Length,i=0,j,x,y;var c=new System.Collections.Stack();for(;i<a;i++)for(j=0;j<b;j++)if(m[i][j]==p)c.Push(new[]{i,j});while(c.Count>0){var t=(int[])c.Pop();x=t[0];y=t[1];if(x<1|x>a-2|y<1|y>b-2)return 0;foreach(var v in new[]{-1,1}){var z=x>0&x<a-1&y>0&y<b-1;if(z&m[x+v][y]==32){m[x][y]=p;c.Push(new[]{x+v,y});}if(z&m[x][y+v]==32){m[x][y]=p;c.Push(new[]{x,y+v});}}}return 1;}

Try it online!

Basically I expand the positions of the P's whenever a white space is around until it reaches (or not) the border of the layout.

Some licenses:

  • I use a char[][] as the input for the layout.
  • Returns 0 as insecure and 1 as secure.

Perl 5, 69 bytes

-10 bytes thanks to @Grimy.

-2 bytes thanks to @Neil.

77 byte of code + -p0 flags.

/
/;$_=s/(P| )(.{@{-}})?(?!\1)(?1)/P$2P/s?redo:!/\A.*P|P.*\Z|^P|P$/m

Try it online!

Some short explanations:
The idea is to put a P everywhere the prisoners can go. If any P is on the first/last line, or the first/last column, then the prisoners can go there and therefor escape, which means the prison isn't secure.
s/(P| )(.{@{-}})?(?!\1)(?1)/P$2P/s replaces a space on the right of or bellow a P with a P, or a space on the left or on top of a P.
Finally, /\A.*P|P.*\Z|^P|P$/m checks if a line starts or ends with a P, or if there is a P on the first or the last line.