# Validating a Battleship board

## JavaScript (ES6),  162  158 bytes

Returns 0 if the grid is invalid, or a positive integer otherwise.

m=>(o=0,g=u=>m.some((r,y)=>r.some((v,x)=>v&&[0,1].map(d=>(r=(w,X=x+!d*w,R=m[y+d*w]||0)=>R[X]&&R[R[X]--,u&(k=1<<w*3)*7&&g(u-k),r(-~w),X]++))))|u||++o)(668)*o


Try it online!

### Commented

m => (                       // m[] = input matrix
o = 0,                     // o = result
g = u =>                   // g is a recursive function taking a bit mask u
// holding the ship counters on 4 x 3 bits
m.some((r, y) =>           //   for each row r[] at position y in m[]:
r.some((v, x) =>         //     for each value v at position x in r[]:
v &&                   //       abort if v is not set
[0, 1].map(d =>        //       otherwise, look for a horizontal ship (d = 0)
(                    //       or a vertical ship (d = 1):
r = (              //         r is a recursive function taking:
w,               //           w = ship width - 1
X = x + !d * w,  //           X = position of the cell in ...
R = m[y + d * w] //           ... R[] = row of the cell
|| 0         //           (force it to 0 if undefined)
) =>               //
R[X] &&            //           abort if R[X] is not set
R[                 //
R[X]--,          //           otherwise, set the cell to 0
u & 7 *          //           if there's still at least one ship of
(k = 1 << w * 3) //           width w to be found in the grid:
&& g(u - k),     //             do a recursive call to g with u updated
r(-~w),          //           do a recursive call to r with w + 1
X                //
]++                //           restore the cell afterwards
)                  //         initial call to r with u zero'ish
)                      //       end of map()
)                        //     end of some()
)                          //   end of some()
| u || ++o                 //   increment o if the grid has been cleared and all
//   boats have been found
)(668)                       // initial call to g with u = 668 (001 010 011 100)
* o                          // multiply by o


## R, 211 bytes

v=function(b,f=c(3:1,2,1,1))if(any(f),{any(sapply(list(b,t(b)),function(m)any(apply(h<-which(m[1:(dim(m)[1]-f[1]),]>0,T),1,function(x)if(all(m[y<-t(x+rbind(0:f[1],0))]),{m[y]=0;v(m,f[-1])},F)))))},sum(b)==4)


Try it online!

How?
Pseudo-code version:

# recursive function:
validate_battleships=
v=function(board,fleet_without_submarines)
if there's nothing left in the fleet,
and the board contains the right number of submarines:
return(TRUE)
else if any of these:
try all positions:
if we can place the first ship in the fleet:
return result of recursive call
after removing this ship from the board and the fleet
return(TRUE)
else return(FALSE)


And the actual, ungolfed R code:

validate_battleships=
v=function(b,f=c(3:1,2,1,1))        # f=fleet=ship sizes minus 1, without submarines
if(any(f),{                     # if there are any ships in the fleet:
any(                            # return TRUE if any of these are true:
sapply(list(b,t(b)),          # test the board and the transpose of the board (to try horizontal & vertical ship-placements)
function(m)any(             # check if any of these are true:
apply(h<-                 # test each nonzero position on the board (excluding the last rows that would make the ship go off the edge)
which(m[1:(dim(m)[1]-f[1]),]>0,T),1,
function(x)           # consider the first ship: f[1] (first item in fleet argument)
if(all(m[y<-t(x+rbind(0:f[1],0))]),
# if all the adjacent positions up to the ship size are nonzero (so we can place this ship),
{m[y]=0;          # set all these positions to zero
v(m,f[-1])}      # and return the result of a recursive call without this ship;
,F)                 # otherwise return FALSE
))))}
,sum(b)==4)                       # if there were no ships in the fleet, check that the nonzero positions on the board
# add-up to 4 (number of submarines): if they do, return TRUE.


Here is my answer in Java, I am definitely not skilled enough to get it down to a minimal amount of bytes and I prefer not to say(shortest byte solution for this code is down at the bottom of this post, credit to @ceilingcat for getting my code down to 482 bytes:P) try it, it works!

thanks to ceilingcat with the 482bytes solution:

int k,R[][],a[]=new int[]{4,3,3,2,2,2},d,e,s,x,y;boolean H(int[][]b,int I){var q=I==6;if(!q)for(int L=a[I++],r=d=b.length,c,M,N,i;r-->0;)for(c=e;c-->0;)for(M=N=i=1;b[x=r][y=c]>0&i<L;i++)q|=(M+=r+(s=L)>d?0:b[r+i][c])==L&&H(R(b,1),I)||(N+=c+L>e?0:b[r][c+i])==L&&H(R(b,0),I);return q;}int[][]R(int[][]n,int o){for(R=new int[k=d][e];k-->0;)R[k]=n[k].clone();for(;s-->0;)R[x+s*o][y-s*~-o]=0;return R;}boolean v(int[][]f){e=f[k=0].length;for(var y:f)for(var x:y)k+=x;return k==20&H(f,0);}


so here is my solution. (I went with a recursive solution for finding the ships)

public class BF {
private static int[][] fields;
public BF(int[][] field) {
fields=field;
}
public boolean validate() {
int cnt=counter(fields);
if(cnt!=20)return false;
return checkBoard(fields, new int[]{4,3,3,2,2,2},0);
}

public static boolean checkBoard(int[][] board,int[] allBoats,int index){
if (index == allBoats.length) {
return true;
}
int boatLen = allBoats[index];
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[0].length; col++) {
if(board[row][col]==1 && row+ boatLen <=board.length) {//vertically
int cnt=1;
for(int i=1;i<boatLen;i++) {//check vertically
if(board[row+i][col]==1) {cnt++;}
}
if(cnt>=boatLen) {
int[][] newBoard = deepcopy(board);
newBoard= remove(newBoard , row, col, boatLen, "ver");
if(checkBoard(newBoard,allBoats,index+1)) { return true;}
}
}
if(board[row][col]==1 && col+boatLen<=board[0].length) {//horizontally
int cnt=1;
for(int i=1;i<boatLen;i++) {//check horizontally
if(board[row][col+i]==1) {cnt++;}
}
if(cnt>=boatLen) {
int[][] newBoard = deepcopy(board);
newBoard= remove(newBoard , row, col, boatLen, "hor");
if(checkBoard(newBoard,allBoats,index+1)) { return true;}
}
}
}
}
return false;
}

public static int[][] remove(int[][] newBoard,int row,int col,int size,String orien){
int[][] removedBoard= deepcopy(newBoard);
if(orien=="ver") {
for(int i=0;i<size;i++) {
removedBoard[row+i][col]=0;
}
return removedBoard;
}
else if(orien=="hor") {
for(int i=0;i<size;i++) {
removedBoard[row][col+i]=0;
}
return removedBoard;
}
return removedBoard;
}
public static int[][] deepcopy(int[][] fields){
int[][] copy= new int[fields.length][fields[0].length];
for (int row = 0; row < fields.length; row++) {
for (int col = 0; col < fields[0].length; col++) {
copy[row][col]= fields[row][col];
}
}
return copy;
}
public static int counter(int[][] f) {// counts amount of tiles on the board with 1's
int cnt=0;
for (int col = 0; col < f[0].length; col++) {
for (int row = 0; row < f.length; row++) {
if (f[row][col] == 1) {
cnt++;
}
}
}
return cnt;
}
}


here is my Pseudo code on the Check board function

/*
*
* function gets length of boat(field, size, ships){{3,2,1};
* loop go through each position in field
* checks vertically {
*  finds option for where the boat can be
*  copies the board
*  removes the boat from the copy
*  call remove boat(function gets length of boat) for size-1, deepcopy
*  if true then return true
* }
* check horizontal{
*  finds option for where the boat can be
*  copies the board
*  removes the boat from the copy
*  call remove boat(function gets length of boat) for size-1, deepcopy
*  if true then return true
* }
* else find next size 4 option
* }
*/


let me know what u think:P

if you want to test it, here is some code for testing in my Java Solution:

import org.junit.Test;
import static org.junit.Assert.*;
public class SolutionTest {
@Test
public void testContact() {
int[][] field = {};
assertTrue("Must return true", new BF(field).validate());
}
}