sucet([], 0).
sucet([H|T], Y) :-
	sucet(T, X),
	Y is X + H.

mapa([], _, []).
mapa([H|T], F, [H2|T2]) :-
	call(F, H, H2),
	mapa(T,F,T2).

even(X) :- 0 is X mod 2.

rozdel([], _, _, [], []).
rozdel([H|T], P, Param, VA, VN) :-
	rozdel(T, P, Param, A, N),
	(
	call(P, H, Param), !,
	  VA = [H|A], VN = N;
	  VA = A,     VN = [H | N]
	).
	

inc(X,Y) :- Y is X + 1.

%qs(+Unsorted,-Sorted)
qs([], []).
qs([P|L], Vys):-
	rozdel(L, mensi, P, M, V),
	qs(M, Mm),
	qs(V, Vm),
	append(Mm, [P|Vm], Vys).

mensi(X,Y) :- X < Y.

fakt(X, Y):- tailf(X, Y, 1).
tailf(1, A, A).
tailf(X, Y, A) :-
	X >= 1,
	NA is A * X,
	NX is X - 1,
	tailf(NX, Y, NA).

otoc(X, Y) :- otoc(X, Y, []).
otoc([], A, A).
otoc([H|T], Y, A) :-
	NA = [H|A], otoc(T, Y, NA).

trans(M, []) :-
	rozdel(M, prazdny, _, _, []).
trans(M, [Z|ZZZ]) :-
	mapa(M, hlava, Z),
	mapa(M, zbytek, ZZ),
	trans(ZZ, ZZZ).

hlava([H|_], H).
zbytek([_|T], T).
prazdny([],_).

mult_mat_mat(X, Y, V) :-
	trans(Y, TY),
	mapa(X, mult_vec_mat, TY, V).

mapa([], _, _, []).
mapa([H|T], F, Param, [H2|T2]) :-
	call(F, H, Param, H2),
	mapa(T,F,Param,T2).

mult_vec_mat(V,M,NV) :- mapa(M,mult_vec_vec,V,NV).

zip([],[],_,[]).
zip([H1|T1],[H2|T2],F,[H3|T3]) :-
        call(F,H1,H2,H3),
	zip(T1,T2,F,T3).

mult(X,Y,Z) :- Z is X * Y.
add(X, Y, Z) :- Z is X + Y.

fold(_, [], _) :- fail. 
fold(_, [X], X).
fold(F, [H1,H2|T], Y) :- call(F,H1,H2,H3),
	fold(F,[H3|T], Y).

mult_vec_vec(V1,V2,R) :- zip(V1,V2,mult,X),
			fold(add,X,R).

snek([],[]).
snek([X|Y], R) :- trans(Y, T), 
                  otoc(T, U), 
		  snek(U, V), 
		  append(X,V,R).
