# Determine win in Tictactoe

Let's play some code golf!

Given a tic-tac-toe board state (Example:)

|x|x|o|
|x|o|x|
|o|o|x|


Determine whether a game is a win a lose or cat. Your code should output any of these options given a state. The above game should output lose

Just to be clear: a win is defined as any 3 xs in a row (diagonal, horizontal, vertical). a lose is 3 os in a row, while a cat game in none in a row.

To make things interesting, you get to determine your input structure for the state- which you must then explain. For instance xxoxoxoox is a valid state as seen above where each of the characters is read from left to right, top to bottom. [['x','x','o'],['x','o','x'],['o','o','x']] is the game in multidimensional array read in a similar way. While 0x1a9 which is hex for 110101001 might work as a suitable compression where 1 can be manipulated for xs and 0 can be manipulated for o.

But those are just some ideas, I'm sure you might have many of your own.

Ground rules:

1. Your program must be able to accept any viable state.
2. The form of input must be able to represent any state.
3. "The win state must be determined from the board"
4. Assume a complete board
5. Win before lose for instance in the case 'xxxoooxxx'

Lowest character count wins

• I like this input structure: (win|lose|cat) [xo]{9}, where the first word denotes whether the game is a win, lose, or cat (?) for player x. Able to represent any state. – Runer112 Jun 24 '14 at 2:51
• Can I suggest a rule like "The win state must be determined from the board" or "The input must contain no information except the board state"? – undergroundmonorail Jun 24 '14 at 3:16
• Are we assuming only legal games played? If so, certain states would be impossible, i.e. XXX OOO XXX but otherwise some full-board states include this as a fourth impossible outcome, where X wins but O also wins. – Riot Jun 24 '14 at 4:17
• why "cat" out of interest? – Chris Jun 24 '14 at 12:08
• @DylanMadisetti: never heard it before and googlign for "win lose cat" came up with nothing. I'd have gone with tie or draw personally. Or in the case of this game maybe "inevitability". ;-) I don't much mind as far as the competition goes though. A string is a string. ;-) – Chris Jun 24 '14 at 13:22

## Ruby 2.0, 85 characters

Here's a simple bitmask-based solution in Ruby:

d=gets.hex
$><<[292,146,73,448,56,7,273,84].map{|m|d&m<1?:lose:d&m<m ?:cat: :win}.max  The board is represented as a hex number, made up of nine bits corresponding to the nine squares. 1 is an X, 0 is an O. This is just like the 0x1a9 example in the question, though the 0x is optional! There's probably a better way to do the bitmasks then just hardcoding a big list. I'll happily take suggestions. See it running on Ideone here. • Your list contains 273 twice. And I really like the max idea! – Ventero Jun 24 '14 at 7:36 • Oh @Ventero, always with the obscure optimizations (thanks) – Paul Prestidge Jun 24 '14 at 8:19 • There can be empty spaces on a board. Your input format does not account for this and therefore cannot represent any viable game state. – Stephen Ostermiller Jun 24 '14 at 13:57 • @StephenOstermiller rule 4:assume a complete board. You are correct that this rule is perhaps contradicted by rules 1 and 2, however if you read all the comments on the question I think this is within the spirit of the question (incomplete boards are not covered, while complete but illegal boards are.) However I think that octal would be a more user-friendly input format than hex. – Level River St Jun 24 '14 at 14:53 • Got it, I thought complete meant something different. – Stephen Ostermiller Jun 24 '14 at 15:11 # Mathematica, 84 chars a=Input[];Which[Max@#>2,win,Min@#<1,lose,1>0,cat]&@{Tr@a,Tr@Reverse@a,Tr/@a,Total@a}  Input format: {{1, 1, 0}, {1, 0, 1}, {0, 0, 1}} • What's happening here? – seequ Jun 24 '14 at 15:54 • @TheRare Start from the right. Tr@a is the trace of the field (sum over diagonal), Tr@Reverse@a is the trace of the flipped field (some over anti-diagonal), Tr/@a is Tr applied to each row, which gives you the sum over each row, Total@a gives you the sum over each column. So basically, you've got all 8 lines you need to check. Then the Which thing is applied to that (basically an if/elseif/else statement), where # represents that list of 8 values. if there's a 3 you win, else if there's a 0 you lose, else if 1>0 (true) cat. – Martin Ender Jun 24 '14 at 17:14 # Bash: 283262 258 Featuring a relatively friendly interface. t(){ sed 's/X/true/g;s/O/false/g'<<<$@;}
y(){ t $(sed 's/X/Q/g;s/O/X/g;s/Q/O/g'<<<$@);}
f(){($1&&$2&&$3)||($1&&$5&&$9)||($1&&$4&&$7)||($2&&$5&&$8)||($3&&$5&&$7)||($3&&$6&&$9)||($4&&$5&&$6)||($7&&$8&&$9)}
f $(t$@)&&echo win||(f $(y$@)&&echo lose)||echo cat


To execute bash tictactoe.sh O X O X O X X O X

Note: the list of 9 positions is a standard matrix representation. It doesn't matter if the board is represented as column major or row major, read from left to right or top to bottom - games of noughts and crosses (or tic tac toe if you insist) are symmetrical, so input order should be irrelevant to the result in every correct implementation, as long as input is linear.

Edit: Thanks to h.j.k for shorter function syntax suggestion.

• Consider t() { ... } instead of function t? Can save some characters there. :) – h.j.k. Jun 25 '14 at 2:14
• I'd totally forgotten about the alternative function syntax - thanks! – Riot Jun 25 '14 at 6:51
• Spaces are not required around <<< to save another four characters. – Michael Mior Oct 2 '18 at 13:10

# Befunge 93 - 375

Takes a binary string as input.

99>~\1-:!!|>v
>0v>v>v   >^$>v ^+ + + 0<:p: >#+#+#+ ^246 ^+ + + 0<265 >#+#+#+ ^pp6 ^+ + + 0<2++ #+#+#+ 55p 0 0 552 >^>^>0v +46 v+ + + < ppp >0 + + + v 444 v!!-3:<< 246 v_"ni"v ppp 0v" w"< :+: \>,,,,@ 266 ->,,,@ 555 !^"cat"_^ 645 !>:9-! ^ +:+ >| p:p >"eso"v 6p6 @,,,,"l"< 246 p2p >^ v <^ <  Reads the string. Bruteforce writes it (the right most vertical strip) as a matrix in between the ^+ + + >#+#+#+ ^+ + + >#+#+#+ ^+ + + #+#+#+  adding lattice (idk). Determins the sum of the columns, rows, and two diagnals. Compares those values to 3 ("win") or 0 ("lose"), else if all the values equal 1 or 2 then draw ("cat"). ## GolfScript, 27 chars 70&.{~"win""lose"if}"cat"if  The input format is a string consisting of eight octal digits, each (redundantly) encoding three consecutive board squares: • The first three digits each encode a single row of the board, from top down and left to right. • The following three digits each encode a single column of the board, from left to right and top down. • The final two digits each encode one of the diagonals (first from top left to bottom right, then from bottom left to top right). To encode a sequence (row / column / diagonal) of three squares as an octal digit, replace every x in the sequence with a 1 and every o with a 0, and interpret the resulting sequence of ones and zeros as a binary number between 0 and 7 inclusive. This input format is quite redundant (all board positions are encoded at least twice, with the center position encoded four times), but it does unambiguously represent any possible state of a completely filled tic-tac-toe board, and does not directly encode the winner into the input. The input may, optionally, contain spaces or other delimiters between digits. In fact, all the program really cares about is whether or not the input string contains the digits 7 or 0. For example, the example board: |x|x|o| |x|o|x| |o|o|x|  may be represented by the input: 651 643 50  For convenience, here's a GolfScript program to convert an ASCII art board layout, as shown in the challenge above, into an input string suitable for this program: ."XOxo"--[{1&!}/]:a[3/.zip"048642"{15&a=}%3/]{{2base""+}%}%" "*  This converter ignores any characters other than x and o, in either case, in its input. It produces a single digit string (complete with space delimiters as shown above) suitable for feeding into the win-determining program above, so the concatenation of these two programs can be used to determine the winner directly from the ASCII art board. Also, here's a reverse converter, just to demonstrate that the input indeed does unambiguously represent the board: .56,48>-- 3<{2base-3>{"ox"=}%n}%"|".@@*+);  • The input format seems like bit of a cheat as much of the work happens in producing the input. – Arkku Jun 24 '14 at 13:50 • @Arkku: Well, yes, it is, but the question explicitly says that "you get to determine your input structure for the state - which you must then explain." It even shows a bit-packed hex string as an example of a valid input format; the only difference between that and my input format is that I reorder and duplicate some bits. – Ilmari Karonen Jun 24 '14 at 14:00 • It is exactly the duplication that seems like a cheat. (e.g., it does directly encode the winner as the presence of 7 or 0 in the input) – Arkku Jun 24 '14 at 14:03 • Still that's a clever encoding, it's redundant, but makes finding the solution much more efficient than any non-redundant encoding ! – ARRG Jun 24 '14 at 14:29 # Python 2 - 214 bytes b=eval(raw_input()) s=map(sum,b) w,l='win','lose' e="if min(s)<1:print l;a\nif max(s)>2:print w;a" exec e+'\ns=map(sum,zip(*b))\n'+e m=b[1][1] for i in 0,2: if m==b[0][i]==b[2][abs(i-2)]:print[l,w][m];a print'cat'  I'm sure there are improvements to be made. To run: python2 tictactoe.py <<< '[[1,1,1],[1,0,1],[0,1,0]]'  which represents this board: X|X|X ----- X|O|X ----- 0|X|0  Exits with a NameError exception in every case except cat. • Whoa, I never knew about <<<! +1 just for that. – Greg Hewgill Jun 24 '14 at 3:22 • @GregHewgill It's pretty convenient. ./whatever <<< 'blah blah blah' is the same as echo -n 'blah blah blah' | ./whatever but without having a whole separate process for echo. – undergroundmonorail Jun 24 '14 at 3:24 • @undergroundmonorail echo in bash is actually a builtin, so doesn't fork a new process – Bob Jun 24 '14 at 16:43 • @GregHewgill it's called a herestring – user16402 Jun 25 '14 at 14:30 ## Haskell, 146 chars To make things interesting, you get to determine your input structure for the state- which you must then explain. OK :). My representation of a board is one of those 126 characters ĻŃŇŉŊœŗřŚşšŢťŦŨųŷŹźſƁƂƅƆƈƏƑƒƕƖƘƝƞƠƤƳƷƹƺƿǁǂǅǆǈǏǑǒǕǖǘǝǞǠǤǯǱǲǵǶǸǽǾȀȄȍȎȐȔȜȳȷȹȺȿɁɂɅɆɈɏɑɒɕɖɘɝɞɠɤɯɱɲɵɶɸɽɾʀʄʍʎʐʔʜʯʱʲʵʶʸʽʾˀ˄ˍˎː˔˜˭ˮ˰˴˼̌ Here's the solution in 146 chars : main=interact$(\x->case(head x)of h|elem h "ĻŃœťŦŨųŷŹƁƂƅƈƕƠƤƳƿǂǆǞǤǵǾȀȳȿɁɅɑɒɘɝɠɤɵɽʀʐʽʾː˭ˮ˰˴˼̌"->"lose";h|elem h "ƏƝƞƹǁǈǑǝȍȺɆɈɶɾʎʸ"->"cat";h->"win")


And here's how it works, as an haskell script :

import Data.List (subsequences, (\\))
import Data.Char (chr)

-- A set of indexes [0-8] describing where on the board pieces of a single color have been played
-- For example the board "OxO;Oxx;xxO" is indexes [0,2,3,8]
type Play = [Int]

-- There are 126 filled tic tac toe boards when X plays first.
--      (This is a combination of 4 OHs among 9 places : binomial(9 4) = 126)
-- perms returns a list of all such possible boards (represented by the index of their OHs).
perms = filter (\x -> 4 == length x) $subsequences [0..8] -- We now create an encoding for plays that brings them down to a single char. -- The index list can be seen as an 9 bit binary word [0,2,3,8] -> '100001101' -- This, in turn is the integer 269. The possible boards give integers between 15 and 480. -- Let's call those PlayInts type PlayInt = Int permToInt [] = 0 permToInt (x:xs) = (2 ^ x) + permToInt xs -- Since the characters in the range 15-480 are not all printable. We offset the chars by 300, this gives the range -- ĻŃŇŉŊœŗřŚşšŢťŦŨųŷŹźſƁƂƅƆƈƏƑƒƕƖƘƝƞƠƤƳƷƹƺƿǁǂǅǆǈǏǑǒǕǖǘǝǞǠǤǯǱǲǵǶǸǽǾȀȄȍȎȐȔȜȳȷȹȺȿɁɂɅɆɈɏɑɒɕɖɘɝɞɠɤɯɱɲɵɶɸɽɾʀʄʍʎʐʔʜʯʱʲʵʶʸʽʾˀ˄ˍˎː˔˜˭ˮ˰˴˼̌ -- Of all distinct, printable characters uOffset = 300 -- Transform a PlayInt to its Char representation pIntToUnicode i = chr$ i + uOffset

-- Helper function to convert a board in a more user friendly representation to its Char
-- This accepts a representation in the form "xooxxxoxo"
convertBoard s = let play = map snd $filter (\(c, i) -> c == 'o')$ (zip s [0..]) :: Play
in pIntToUnicode $permToInt play -- -- Now let's cook some data for our final result -- -- All boards as chars allUnicode = let allInts = map permToInt perms in map pIntToUnicode allInts -- Now let's determine which boards give which outcome. -- These are all lines, columns, and diags that give a win when filled wins = [ [0,1,2],[3,4,5],[6,7,8], -- lines [0,3,6],[1,4,7],[2,5,8], -- columns [0,4,8],[2,4,6] -- diagonals ] isWin :: Play -> Bool isWin ps = let triplets = filter (\x -> 3 == length x)$ subsequences ps -- extract all triplets in the 4 or 5 moves played
in any (\t -> t elem wins) triplets -- And check if any is a win line

-- These are OH wins
oWins = filter isWin perms
-- EX wins when the complement board wins
xWins = filter (isWin . complement) perms
where complement ps = [0..9] \\ ps
-- And it's stalemate otherwise
cWins = (perms \\ oWins) \\ xWins

-- Write the cooked data to files
cookData = let toString = map (pIntToUnicode . permToInt) in do
writeFile "all.txt" allUnicode
writeFile "cWins.txt" $toString cWins writeFile "oWins.txt"$ toString oWins
writeFile "xWins.txt" $toString xWins -- Now we know that there are 48 OH-wins, 16 stalemates, and 62 EX wins (they have more because they play 5 times instead of 4). -- Finding the solution is just checking to which set an input board belongs to (ungolfed :) main = interact$ \x -> case (head x) of -- Only consider the first input char
h | elem h "ĻŃœťŦŨųŷŹƁƂƅƈƕƠƤƳƿǂǆǞǤǵǾȀȳȿɁɅɑɒɘɝɠɤɵɽʀʐʽʾː˭ˮ˰˴˼̌" -> "lose" -- This string is == oWins
h | elem h "ƏƝƞƹǁǈǑǝȍȺɆɈɶɾʎʸ" -> "cat" -- And this one == cWins
h -> "win"


## JavaScript, 420 chars

if((s&0x3F000)==0x3F000||(s&0x00FC0)==0x00FC0||(s&0x0003F)==0x0003F||(s&0x030C3)==0x030C3||(s&0x0C30C)==0x0C30C||(s&0x30C30)==0x30C30||(s&0x03330)==0x03330||(s&0x30303)==0x30303)return 'win'
if((s&0x3F000)==0x2A000||(s&0x00FC0)==0x00A80||(s&0x0003F)==0x0002A||(s&0x030C3)==0x02082||(s&0x0C30C)==0x08208||(s&0x30C30)==0x20820||(s&0x03330)==0x02220||(s&0x30303)==0x20202)return 'lose'
if((s&0x2AAAA)==0x2AAAA)return 'cat'


In this version, s contains an integer which represents the state of the game board. It is a bit array of value where two bits represents each square on the board:

• 10 - X
• 11 - O
• 00 - Empty square

This solution uses bit manipulation to test each of the eight possible "three in a row" configurations (it tests them each twice, once for X and once for O).

I present this with minor minification from my Tic-Tac-Toe website where this detectWin function is in use as part of a real Tic-Tac-Toe game.

• Well, this could be called brute forcing it. – seequ Jun 24 '14 at 17:12

## Ruby, 84 characters

$><<(gets.tr("01","10")[r=/0..(0|.0.)..0|000(...)*$|^..0.0.0/]?:win:~r ?:lose: :cat)


Simple, RegExp based solution. The input format is a 9-digit binary string, e.g. 110101001 for the example board given in the question.

$><<(gets.tr("ox","xo")[r=/o...(o|.o.)...o|ooo|o_.o._o/]?:win:~r ?:lose: :cat)  Input format: xxo_xox_oox # Haskell, 169 main=interact$(\x->last$"cat":[b|(a,b)<-[("ooo","lose"),("xxx","win")],any(==a)x]).(\x->x++(foldr(zipWith(:))(repeat[])x)++map(zipWith(!!)x)[[0..],[2,1,0]]).take 3.lines  Input format: "X" is represented only by x, "O" only by o. Within each row, characters are simultaneous without spaces, etc. Rows are separated by new lines. Generates all possible rows/columns/diagonals, then filters [("ooo","lose"),("xxx","win")] by their existence on the board, then selects the second word in the tuple, so we know which players won. We prepend "cat" so that we can take the last element of the list as our winner. If both players won, "win" will be last (list comprehensions maintain order). Since "cat" is always first, if a winner exists, it will be chosen, but otherwise a last element still exists as prepending "cat" guarantees nonemptyness. EDIT: Shaved 3 characters by changing last list comprehension to map. # C,150 approx It's midnight here and I haven't done any testing, but I'll post the concept anyway. I'll get back to it tomorrow. User inputs two octal numbers (I wanted to use binary but as far as I know C only supports octal): a represents the centre square, 1 for an X, 0 for an O b is a nine-digit number representing the perimeter squares, circling round the board starting in one corner and finishing in the same corner (with repeat of that corner only), 1 for an X, 0 for an O. There are two possible ways to win: 1. centre square is X (a=1) and two opposite squares are also X (b&b*4096 is nonzero) 2. three adjacent perimeter squares are X (b/8 & b & b*8 is nonzero.) This is only a valid win if the middle square is an edge square, not a corner square, therefore it is necessary to apply the mask m also, to avoid the corner square cases. Losing is detected using the variable c, which is the inverse of b. int a,b,c,m=010101010; main(){ scanf("%o%o",a,b);c=b^0111111111; printf("%s",(a&&b&b*4096)|(b/8&b&b*8&m)?"win":((!a&&c&c*4096)|(c/8&c&c*8)?"lose":"cat")); }  • You forgot to apply the mask m in the "lose" detection - c/8&c&c*8. I have re-golfed your code (without testing its operation) as follows: int a,b;t(v){return a&&v&v<<12||v/8&v&v*8&0x208208;}main(){scanf("%o%o",a,b);printf("%s",t(b)?"win":t(b^0x1249249)?"lose":"cat");} (130 chars). The repeated test was long enough to extract into a test function t(); this removes the need for c and m; the constants converted to hex to save one char each. – Toby Speight Jun 5 '15 at 10:59 • Just spotted that the printf doesn't need a format string - just supply the result string as the format - or puts it, since the question doesn't ask for a newline after the output! (saves a further 7 chars). – Toby Speight Jun 5 '15 at 11:02 # Bash, 107 103 Generates and runs a sed script. I/O format: oxo-oox-xoo outputs lose (use a - to separate rows). Input on stdin. Requires GNU sed for the c command. I've interpreted rule 5 as "if both win and lose are possible, choose win". ## Main Code This is the actual answer. Nothing interesting really. It defines $b as /cwin to save characters, then defines the win condition part of the script, then uses sed y/x/o/\;s$b/close/ to convert x to o and cwin to close (thereby generating the lose conditions). It then sends the two things and ccat (which will output cat if no win/lose condition is matched) to sed. b=/cwin v="/xxx$b
/x...x...x$b /x..-.x.-..x$b
/x-.x.-x$b" sed "$v
sed y/x/o/\;s$b/close/<<<"$v"
ccat"


## Generated Code

This is the sed script generated and run by the Bash script.

In the regexes, . matches any character and after them cTEXT prints TEXT and exits if the regex is matched.

This can run as a standalone sed script. It's 125 characters long, you can count it as another solution.

/xxx/cwin
/x...x...x/cwin
/x..-.x.-..x/cwin
/x-.x.-x/cwin
/ooo/close
/o...o...o/close
/o..-.o.-..o/close
/o-.o.-o/close
ccat


# Python 3, 45

Input is in i, which is a list of numbers representing each row, column, and diagonal of the game board, e.g:

X X O
O X O
O O X


is represented by [6, 2, 1, 4, 6, 1, 7, 4].

Code: ('cat','lose','win')[2 if 7 in i else 0 in i]

## Dart - 119

(See dartlang.org).

Original version using RegExp: 151 chars.

main(b,{w:"cat",i,p,z}){
for(p in["olose","xwin"])
for(i in[0,2,3,4])
f(){ x=$[($1&$2&$3)|($1&$5&$9)|($1&$4&$7)|($2&$5&$8)|($3&$5&$7)|($3&$6&$9)|($4&$5&$6)|($7&$8&$9)]; } f$@;w=$x f$(y $@) ([$x -eq 1 ]&&echo lose)||([ $w -eq 1 ]&&echo win)||echo cat  To execute bash tictactoe.sh 0 1 0 1 0 1 1 0 1 Inspired by this answer. VB.net With the example provide is encoded as the following bit-pattern q = &B_100101_100110_011010 ' 00 Empty, 01 = O, 10 = X  Now we can determine the result (or winner) by doing the following. Dim g = {21, 1344, 86016, 66576, 16644, 4161, 65379, 4368} Dim w = If(g.Any(Function(p)(q And p)=p),"Lose",If(g.Any(Function(p)(q And p*2)=p*2),"Win","Cat"))  ## J - 97 bytes Well, the simplest approach available. The input is taken as 111222333, where the numbers represent rows. Read left-to-right. Player is x and enemy is o. Empty squares can be anything except x or o. f=:(catlose>@{~'ooo'&c)('win'"_)@.('xxx'&c=:+./@(r,(r|:),((r=:-:"1)(0 4 8&{,:2 4 6&{)@,))3 3&$)


Examples: (NB. is a comment)

   f 'xoxxoxxox' NB. Victory from first and last column.
win
f 'oxxxooxxx' NB. Victory from last row.
win
f 'ooxxoxxxo' NB. The example case, lost to a diagonal.
lose
f 'xxooxxxoo' NB. Nobody won.
cat
f 'xoo xx ox' NB. Victory from diagonal.
win


### Ungolfed code an explanation

row   =: -:"1                        Checks if victory can be achieved from any row.
col   =: -:"1 |:                     Checks if victory can be achieved from any column.
diag  =: -:"1 (0 4 8&{ ,: 2 4 6&{)@, Checks if victory can be achieved from diagonals.
check =: +./@(row,col,diag) 3 3&$Checks all of the above and OR's them. f =: (catlose >@{~ 'ooo'&check)('win'"_)@.('xxx'&check) Check if you have won ........................@.('xxx'&check) If yes, return 'win' .............. ('win'"_) If not (catlose >@{~ 'ooo'&check) Check if enemy won ................... 'ooo'&check If yes, return 'lose' ---lose >@{~ If not, return 'cat' cat---- >@{~  Python 2, 120 bytes b=0b101001110 l=[448,56,7,292,146,73,273,84] print(['Win'for w in l if w&b==w]+['Lose'for w in l if w&~b==w]+['Cat'])[0]  Or Python, 115 bytes from the Python shell (2 or 3): b=0b101001110;l=[448,56,7,292,146,73,273,84];(['Win'for w in l if w&b==w]+['Lose'for w in l if w&~b==w]+['Cat'])[0]  The board variable is set to the binary format described in the question: 1 for X, 0 for O, left-to-right, top-to-bottom. In this case, 101001110 represents XOX OOX XXO  Which leads to output: Cat • What is the input format? – seequ Jun 24 '14 at 17:32 # Python (73 62 chars) The input is four lower-case strings representing four distinct views of the same board, all concatenated into a single string: by row, by column, right-diagonal, left-diagonal. # UPDATE Thanks to theRare for pointing this out with a good counter-example! Each view of the board, along with each segment (row or column) within a board has to be separated by a character that is neither an "x" or an "o" so that the structure of the board is preserved even after concatenation. The borders around each view of the board will be square brackets ("[" and "]"), and the separator between rows/columns will be a pipe character "|". This makes the algorithm simple--just look for "xxx" or "ooo" for a win or loss, respectively. Otherwise it's a tie (cat). E.g. the board (reading left-to-right, top-to-bottom)... X|X|X X|O|X O|X|O ...is represented as "[xxx|xox|oxo]" (by rows) + "[xxo|xox|xxo]" (by columns) + "[xoo]" (right diag) + [xoo]" (left diag) = "[xxx|xox|oxo][xxo|xox|xxo][xoo][xoo]". This Python statement prints the game result given the variable s as input: print 'win' if 'xxx' in s else 'lose' if 'ooo' in s else 'cat'  • Does this work for board OXX XOO XOX (it should be cat)? – seequ Jun 24 '14 at 18:50 • No...no it doesn't. Good catch! I guess my solution was a little too simple... Oops! – bob Jun 24 '14 at 19:41 • I can't say this type of solution didn't cross my mind. :) – seequ Jun 24 '14 at 19:47 ## Haskell (69 chars) i x=take 4$(x>>=(\y->case y of{'7'->"win";'0'->"lose";_->""}))++"cat"


This takes the same input as described by this answer. More specifically, the input is 8 octal values, describing the binary value of each row, column, and diagonal. The code makes every instance of 7 "win", every instance of 0 "lose", and removes everything else. Then it adds "cat" to the end and takes the first 4 chars from the result.

There will be 4 possible answers: "lose", "cat", "win" followed by an 'l', and "win" followed by a 'c', which the rules don't prohibit :)

Example usage:

i "65153806" --outputs "lose"


(;:'lose cat win'){::~>:*(-&(+/@:(*./"1)@;@(;((<0 1)&|:&.>@(;|.)(,<)|:)))-.)3 3$'x'=  Usage: just append a string of x's and o's and watch the magic work. eg. 'xxxoooxxx'. The inner verb (+/@:(*./"1)@;@(;((<0 1)&|:&.>@(;|.)(,<)|:))) basically boxes together the original binary matrix, with the transpose boxed together with the 2 diagonals. These results are razed together ; row sums are taken to determine wins, and then summed. further I'll call this verb Inner. For finding the winner, the difference of the scores between the normal and inversed binary matrices is taken by the hook (-&Inner -.). The rest of the code simply makes the outputs, and selects the right one. ## JavaScript, 133, 114 characters r = '/(1){3}|(1.{3}){2}1|(1.{4}){2}1|(1\|.1.\|1)/';alert(i.match(r)?'WIN':i.match(r.replace(/1/g,0))?'LOSS':'CAT')  The input i is a simple string with delimiters for the rows, i.e. 100|001|100 Edit: updated my method to replace the 1s in the regex with zeroes to check for the loss case. • You can remove the spaces around = and the quotes around the regex literal. Also, 1... is one character shorter than 1.{3}. – nyuszika7h Jul 5 '14 at 12:56 • r.test(i) is also one character shorter than i.match(r). – nyuszika7h Jul 5 '14 at 12:58 # J - 56 (26?) char Input is given a 3x3 matrix of nine characters, because J can support that as a datatype, LOL. (winlosecat{::~xxxooo<./@i.<"1,<"1@|:,2 7{</.,</.@|.)  Examples:  NB. 4 equivalent ways to input the example board (3 3$ 'xxoxoxoox') ; (_3 ]\ 'xxoxoxoox') ; ('xxo','xox',:'oox') ; (];._1 '|xxo|xox|oox')
+---+---+---+---+
|xxo|xxo|xxo|xxo|
|xox|xox|xox|xox|
|oox|oox|oox|oox|
+---+---+---+---+
(winlosecat{::~xxxooo<./@i.<"1,<"1@|:,2 7{</.,</.@|.) 3 3 $'xxoxoxoox' lose wlc =: (winlosecat{::~xxxooo<./@i.<"1,<"1@|:,2 7{</.,</.@|.) wlc (3 3$ 'xoxoxooxo')
cat
wlc (3 3 \$ 'xxxoooxxx')
win


If we are allowed the Golfscriptish encoding of octal digits redundantly representing the state of each row, column, and diagonal, then it's just 26 characters:

   winlosecat{::~7 0<./@i.] 6 5 1 6 4 3 5 0
lose
f=:winlosecat{::~7 0<./@i.]
f  7 0 7 5 5 5 5 5
win


# T-SQL (2012),110

select max(iif(@&m=0,'lose',iif(@&m=m,'win','cat')))from(VALUES(292),(146),(73),(448),(56),(7),(273),(84))z(m)

Input is a hex number. This is pretty much a translation of the ruby solution into T-SQL pretty nice and neat.

# Javascript 1.6, 71 chars

I'm assuming input as an array game which contains each row, each column and each diag as a 3 char string. Similar to bob's answer, but it comes in an array, not as a concatenated string.

alert(game.indexOf("xxx")>=0?"win":game.indexOf("ooo")>=0?"lose":"cat")


EDIT @nyuszika7h's comment (67 chars)

alert(~game.indexOf("xxx")?"win":~game.indexOf("ooo")?"lose":"cat")

• You can use ~game.indexOf("xxx") instead of game.indexOf("xxx")>=0, same for the other one. – nyuszika7h Jul 5 '14 at 12:54

# Java 7, 260 bytes

String c(int[]s){int a[]=new int[8],x=0,y;for(;x<3;x++){for(y=0;y<3;a[x]+=s[x*3+y++]);for(y=0;y<3;a[x+3]+=s[y++%3]);}for(x=0;x<9;y=s[x],a[6]+=x%4<1?y:0;a[7]+=x%2<1&x>0&x++<8?y:0);x=0;for(int i:a)if(i>2)return"win";for(int i:a)if(i<1)return"loose";return"cat";}


Ungolfed & test cases:

Try it here.

class M{
static String c(int[] s){
int a[] = new int[8],
x = 0,
y;
for(; x < 3; x++){
for(y = 0; y < 3; a[x] += s[x * 3 + y++]);
for (y = 0; y < 3; a[x + 3] += s[y++ % 3]);
}
for(x = 0; x < 9; y = s[x],
a[6] += x % 4 < 1
? y
: 0,
a[7] += x % 2 < 1 & x > 0 & x++ < 8
? y
: 0);
x = 0;
for(int i : a){
if(i > 2){
return "win";
}
}
for(int i : a){
if(i < 1){
return "loose";
}
}
return "cat";
}

public static void main(String[] a){
/*  xxo
xox
oox  */
System.out.println(c(new int[]{ 1, 1, 0, 1, 0, 1, 0, 0, 1 }));
/*  xxx
ooo
xxx  */
System.out.println(c(new int[]{ 1, 1, 1, 0, 0, 0, 1, 1, 1 }));
/*  xxo
oox
xox  */
System.out.println(c(new int[]{ 1, 1, 0, 0, 0, 1, 1, 0, 1 }));
}
}


Output:

loose
win
cat


# APL(NARS), 69 chars, 138 bytes

{w←3 3⍴⍵⋄x←(+/1 1⍉⊖w),(+/1 1⍉w),(+⌿w),+/w⋄3∊x:'win'⋄0∊x:'lose'⋄'cat'}


The input should be one 3x3 matrix or one linear array of 9 element that can be only 1 (for X) and 0 (for O), the result will be "cat" if nobody wins, "lose" if O wins, "win" if X wins. There is no check for one invalid board or input is one array has less than 9 element or more or check each element <2.

As a comment: it would convert the input in a 3x3 matrix, and build one array named "x" where elements are the sum each row column and diagonal.

Some test see example showed from others:

  f←{w←3 3⍴⍵⋄x←(+/1 1⍉⊖w),(+/1 1⍉w),(+⌿w),+/w⋄3∊x:'win'⋄0∊x:'lose'⋄'cat'}
f 1 2 3
win
f 0 0 0
lose
f 1 0 1  1 0 1  1 0 1
win
f 0 1 1  1 0 0  1 1 1
win
f 0 0 1  1 0 1  1 1 0
lose
f 1 1 0  0 1 1  1 0 0
cat
f 1 1 0  0 1 0  0 0 1
win
f 1 1 0  1 0 1  0 0 1
lose