Is this Tic-Tac-Toe board valid?

JavaScript (ES6), 88 87 bytes

s=>(a=[...s]).sort()[5]-a[3]&[7,56,73,84,146,273,292,448].every(j=>j&i,i=`0b`+s^~-a[4])

Takes input as a string of 9 0 and 1 characters and returns 1 for valid, 0 for invalid. We sort the characters into order. If the middle three characters are now the same then the board is invalid as there are too many of one piece. Otherwise, we convert the original board into binary, flipping the bits if there are more 0s than 1s. At this point the board is valid if 0 does not have a line of three, so we simply test all eight lines via an array of bitmasks. Edit: Saved 1 byte thanks to @ETHproductions.


Python 3, 131 127 125 100 96 bytes

For a different algorithmic approach (and one that will be really suited to these multi-byte golfing languages with built-in compression), instead of calculating if the board is valid, let's have a 512-bit number where each bit represents whether or not a particular board is valid or not, and pass in a binary value representing the board. Furthermore, due to symmetry, the second half of the table can be eliminated, along with a bunch of zeros:

def z(b):return int('agqozfx67wwye6rxr508ch2i8qicekpreqkap0725pk',36)<<24&1<<b+(b>255)*(511-b-b)

The test value:

X X X
O X O
X X X

Is represented as the binary value 0b111010111, and the function returns a non-zero value if the board is valid.


Jelly, 26 bytes

ṢŒrṪ4=$$Ðfx3ðœ-µẆm€6R¤;/µL

Try it online!

The input format is a little unusual; it's a string representing the board, but with Windows newlines (carriage return followed by newline). For example, XXO\r\nOXO\r\nOOX. (Actually, any two-character padding string between the lines works, but Windows newlines are much more defensible than the other options.)

The basic idea is that we look for characters that appear 4 times in the input, but don't have three evenly spaced occurrences in the original string. With two or more characters of padding between the lines of a 3×3 grid, all horizontal, vertical, and diagonal lines are evenly spaced, but no other evenly spaced line can have three elements.

Explanation:

The ð and µs are chain separators, which split the program into multiple parts that are each independent. I've replaced them with spaces below, to make things a bit clearer.

ṢŒrṪ4=$$Ðfx3 œ- Ẇm€6R¤;/ L
Ṣ                           sorted version of the input
 Œr                         run-length-encode it
        Ðf                  keep only elements where
   Ṫ                        delete the last element, and it was
    4=                      equal to 4
      $$                    parse Ṫ4= as a group
          x3                repeat each element three times

                Ẇ           all sublists of the input
                 m€         take every nth element of each (€) sublist
                   6R       for each n in 1..6
                     ¤      parse 6R as a group
                      ;/    flatten one level (m€ creates a nested structure)

             œ-             multiset difference
                         L  length of that difference

In other words, we find the list of characters that appear exactly four times in the input, and make a list consisting of three copies of each of those; we find the list of all subsequences that are evenly spaced in the original string; and if we subtract the second from the first, we want the result to have length 1 (i.e. a player played four times but didn't win). Note that as we're on a 3×3 grid and every square is full, it's impossible for both players to have played four times. In Jelly, 1 is truthy, 0 is falsey, so we don't need to do anything special to convert the resulting list to a boolean. (The µL is required, though, because otherwise both “XXX” and “OOO” would be possible truthy output values, and the question requires that all valid boards give the same output.)