Is this string valid FEN? The challenge

Write a program or function which takes a string input as a function parameter or from stdin and determines if it is a valid FEN string.

Input

You can assume the input will only ever include the following characters (case sensitive)
pkqrbnPKQRBN12345678/
The length of the input will always be a minimum of 1 character and a maximum of 100 characters

Output

Output should be a truthy/falsey value. These can be any values you wish as long as they are consistent (all truthy results have the same output, all falsey results have the same output). You should have exactly two distinct possible outputs.

What counts as valid

Lowercase letters represent black pieces, uppercase letters represent white pieces.
You should ensure it is possible in a game of chess for the pieces in the current position to exist.
Each player will always have exactly 1 king (k/K)
Each player may have no more than 8 pawns (p/P)
Each player will usually have no more than 1* queen (q/Q)
Each player will usually have no more than 2* rooks (r/R)
Each player will usually have no more than 2* knights (n/N)
Each player will usually have no more than 2* bishops (b/B)
* It is legal for a player to 'promote' a pawn to any of these four pieces.
The total of pawns, queens, rooks, knights and bishops for each player will never be more than 15  

The total number of pieces plus empty squares (denoted by numbers) should always add up to exactly 8 for each rank. And there should always be exactly 8 ranks, separated by a forward slash.

Things you can ignore

You do not need to concern yourself with whether or not it is possible to play into the position denoted, or if the position is legal, only that the pieces can exist in the quantities given.
You can ignore further complexities of FEN strings such as player turn, castling rights and en passant.

This is code golf. Shortest program in bytes wins. Usual loopholes and rules apply.

Test Cases

Input rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
Output True

Input 2br2k1/1p2n1q1/p2p2p1/P1bP1pNp/1BP2PnP/1Q1B2P1/8/3NR2K
Output True

Input r2r2k1/p3q2p/ppR3pr/rP4bp/3p4/5B1P/P4PP1/3Q1RK1
Output False
(black has 7 pawns and 4 rooks - impossible)

Input 6k1/pp3ppp/4p3/2P3b1/bPP3P1/3K4/P3Q1q1
Output False
(only 7 ranks)

Input 3r1rk1/1pp1bpp1/6p1/pP1npqPn/8/4N2P/P2PP3/1B2BP2/R2QK2R
Output False
(9 ranks)

Input 5n1k/1p3r1qp/p3p3/2p1N2Q/2P1R3/2P5/P2r1PP1/4R1K1
Output False
(2nd rank has 9 squares/pieces)

Input rnbqkbnr/pppppppp/8/35/8/8/PPPPPPPP/RNBQKBNR
Output True
Thanks to Feersum and Arnauld for clarifying this case (3+5=8)

What is FEN?

FEN is a standard notation for recording the position of the pieces on a chess board.

Image credit http://www.chessgames.com
JavaScript (ES6), 168 174 ... 155

This answer has been edited an embarrassing number of times. Hopefully, the current version is both reliable and decently golfed.



Returns a boolean.

s=&gt;[...s].map(c=&gt;++n%9?+c?n+=--c:a[i='pP/KkQqRrBbNn'.search(c),i&amp;=i&gt;4&amp;a[i]&gt;(i&gt;6)||i]=-~a[i]:x+=c=='/',a=[x=n=0])&amp;&amp;!([p,P,s,k,K]=a,n-71|x-7|s|k*K-1|p&gt;8|P&gt;8)


Formatted and commented

s =&gt; [...s].map(c =&gt;                  // for each character 'c' in the FEN string 's':
  ++n % 9 ?                           //   if we haven't reached the end of a rank:
    +c ?                              //     if the character is a digit:
      n += --c                        //       advance the board pointer by c - 1 squares
    :                                 //     else:
      a[                              //       update the piece counter array:
        i =                           //         i = piece identifier (0 to 12)
          'pP/KkQqRrBbNn'.search(c),  //             with special case: '/' --&gt; 2
        i &amp;=                          //         we count it as a promoted pawn instead if:
          i &gt; 4 &amp;                     //           it's a Q, R, B or N and we already have
          a[i] &gt; (i &gt; 6) ||           //           2 of them for R, B, N or just 1 for Q
          i                           //           else, we keep the identifier unchanged
      ] = -~a[i]                      //         '-~' allows to increment 'undefined'
  :                                   //   else:
    x += c == '/',                    //     check that the expected '/' is there
  a = [                               //   initialize the piece counter array 'a'
    x =                               //   initialize the '/' counter 'x',
    n = 0 ]                           //   initialize the board pointer 'n'
) &amp;&amp;                                  // end of map()
!(                                    // now it's time to perform all sanity checks:
  [p, P, s, K, k] = a,                //   copy the 5 first entries of 'a' to new variables
  n - 71 |                            //   have we reached exactly the end of the board?
  x - 7 |                             //   have we identified exactly 7 ends of rank?
  s |                                 //   have we encountered any unexpected '/' character?
  k * K - 1 |                         //   do we have exactly one king on each side?
  p &gt; 8 |                             //   no more than 8 black pawns, including promotions?
  P &gt; 8)                              //   no more than 8 white pawns, including promotions?


Test cases



let f =

s=&gt;[...s].map(c=&gt;++n%9?+c?n+=--c:a[i='pP/KkQqRrBbNn'.search(c),i&amp;=i&gt;4&amp;a[i]&gt;(i&gt;6)||i]=-~a[i]:x+=c=='/',a=[x=n=0])&amp;&amp;!([p,P,s,k,K]=a,n-71|x-7|s|k*K-1|p&gt;8|P&gt;8)

console.log(f("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR")) // True
console.log(f("2br2k1/1p2n1q1/p2p2p1/P1bP1pNp/1BP2PnP/1Q1B2P1/8/3NR2K")) // True
console.log(f("r2r2k1/p3q2p/ppR3pr/rP4bp/3p4/5B1P/P4PP1/3Q1RK1")) // False (black has 7 pawns and 4 rooks - impossible)
console.log(f("6k1/pp3ppp/4p3/2P3b1/bPP3P1/3K4/P3Q1q1")) // False (only 7 ranks)
console.log(f("3r1rk1/1pp1bpp1/6p1/pP1npqPn/8/4N2P/P2PP3/1B2BP2/R2QK2R")) // False (9 ranks)
console.log(f("5n1k/1p3r1qp/p3p3/2p1N2Q/2P1R3/2P5/P2r1PP1/4R1K1")) // False (2nd rank has 9 squares/pieces)
console.log(f("rnbqkbnr/pppppppp/8/35/8/8/PPPPPPPP/RNBQKBNR")) // True
console.log(f("rnbqkbnr/pppppppp/8/9/7/8/PPPPPPPP/RNBQKBNR")) // False (additional test case suggested by Rick Hitchcock)
console.log(f("rnbqkbnr/pppp/ppp/8/8/8/8/PPPPPPPP/RNBQKBNR")) // False (additional test case)