winner(L) :- L = [_,_,_], is_valid(L), triple(L, T), is_winning_triple(T).

triple(L, T) :- member(T, L).                    /* gets the rows */
triple(L, T) :- transpose(L, LT), member(T, LT). /* gets the columns */
triple([[A,_,_],[_,B,_],[_,_,C]], [A,B,C]).
triple([[_,_,A],[_,B,_],[C,_,_]], [A,B,C]).

transpose([[A,B,C],[D,E,F],[G,H,I]], [[A,D,G],[B,E,H],[C,F,I]]).

is_winning_triple([x,x,x]).
is_winning_triple([x,x,b]).
is_winning_triple([x,b,x]).
is_winning_triple([b,x,x]).

is_valid(L) :- c(L,x,X), c(L,o,O), (X = O -> true ; X =:= O+1).

c(L,E,N) :- flatten(L, F), findall(_, member(E,F), Cs), length(Cs, N).
