
% rozmnoz(+L,-RL) ze vstupniho seznamu L rozmnozi kazdy prvek tolikrat, kolikata je to jeho pozice (bez aritmetiky)

rozmnoz(L,RL):-rozmnoz2([L],RL).

rozmnoz2([[]|_],[]).
rozmnoz2(T,Lout):-orez(T,[H|Torez],L),rozmnoz2([H,H|Torez],Lrest),append(L,Lrest,Lout).

% prvociselny rozklad(N,L) - v seznamu L je prvociselny rozklad cisla N 
prvociselny_rozklad(N,L) :- N > 0,  prvociselny_rozklad(N,L,2).

% prvociselny_rozklad(N,L,K) :- L je seznam obsahujici prvociselny rozklad N, od K niz jiz to je hotove
prvociselny_rozklad(1,[],_).
prvociselny_rozklad(N,[F|L],F) :-                           % N is multiple of F
   N mod F =:= 0, R is N // F, prvociselny_rozklad(R,L,F). 
prvociselny_rozklad(N,L,F) :- 
   N mod F =\= 0, F1 is F +1,prvociselny_rozklad(N,L,F1).        



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% datove struktury v prologu a testy
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%datove objekty
%  |-- struktura - slozeny objekt - napr. adresa(ulice,cislo,psc).
%  |-- jednoduchy objekt
%       |-- promenne - napr. X,Y,_G234
%       |-- konstanty
%             |-- atom - napr. pes, a,tttt
%             |-- cisla

% da se testovat na prilusnost k danemu typu objektu
% var(X) - uspeje, pokud X je NEzinstanciovana promenna
% nonvar(X) - uspeje, pokud X neni promenna nebo je to jiz zinstanciovana promenna
% atom(X) - uspeje, pokud X je atom
% integer(X) - uspeje, pokud Z je cele cislo
% real(X) - uspeje, pokud Z je realne cislo
% atomic(X) - uspeje, pokud X je integer nebo atom
% compound(X) - uspeje, pokud X je struktura

% prikazy vyse se hodi pro testovani korektnich vstupu algoritmu, ale jsou i pripady, kdy se bez nich neobejdeme
% napr count(X,L,N) - spocita pocet vyskytu N atomu X v L.
% prima implementace s unifikovanim hlavy seznamu selze na vstupech count(a,[a,b,X,Y],N).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% matice
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% matice muzeme brat jako seznam seznamu
% jematice(+X) - uspeje, pokud X je matice
% lze i pres pocitani delky seznamu, pokud si dovolime aritmetiku
jematice([[]|L]):-prazdneseznamy(L).
jematice(Rs):-orez(Rs,Rs2),jematice(Rs2).

% na rozmyslenou operatory pro praci s maticemi

% orez(M,Mo) - matice Mo vznikne z matice M odstranenim prvniho sloupce
% povidani o zapoctovych programech a pripomenuti testu pristi tyden

% orez(M,M1,Prv) - M1 vznikne z M odstranenim prvnich prvku z radku, ktere ulozi jako R
orez(R,R2,Prv):-R\=[],orez2(R,R2,Prv). % pokud mame radek s prazdnymi prvky, pak se nejdena o matici
orez2([],[],[]).
orez2([[H|R]|Rs],[R|Rs2],[H|Hr]):-orez2(Rs,Rs2,Hr).

% prazdneseznamy(L) - uspeje, pokud L obsahuje pouze prazdne seznamy
prazdneseznamy([]).
prazdneseznamy([[]|L]):-prazdneseznamy(L).

% diag(M,L) - L je seznam prvku na diagonale matice M
diag([],[]).
diag([[]|_],[]).
diag([[X|_]|Rs],[X|Rs2]):-orez(Rs,Rs1),diag(Rs1,Rs2).


transponse([],[]).
transponse([[]|_],[]).
transponse(M,[R|Mt]):-sloupec1(M,R,M1),transponse(M1,Mt).

% sloupec1(+M,-S1,-M1) - M1 je matice bez prvniho sloupce S1.
sloupec1([],[],[]).
sloupec1([[H|T]|TM],[H|T1],[T|T2]) :- sloupec1(TM,T1,T2).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Prace se soubory
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% zakladni predikaty pro praci se vstupem a vystupem
% nl. - nularni predikat, odradkuje
% write(X) - vypise term X na vstup. Pokud je X nezinstanciovana promenna, vypise interni hodnotu
% read(X) - zunifikuje X se vstupem. Pozor, vstup musi koncit teckou
% tab(N) - vypise n mezer.

% Zakladni predikaty pr praci se soubory
% pracuje se s IOstreamy, i IO s prikazovou radkou je prace se stremem
% see(X) - vstupni stream je zmenen na soubor X. Pri IO chybe neuspeje, pokud misto X dame user, presmeruje se vstup opet do prikazove radky
% seen. - uzavre vstupni soubor
% tell(X) - vystupni stream je zmenen na soubor X. Pri IO chybe neuspeje, pokud misto X dame user, presmeruje se vstup opet do prikazove radky
% told. - uzavre vystupni soubor
% obecne dva typy souboru - soubory termu a soubory znaku

% prace se souberem termu
% ..,see(F),processfile,see(user),..
processfile:-
	read(X),
    process(X).
process(end_of_file).
process(X):-
	do(X),
	processfile.
% kde predikat do zastupuje operaci, co chceme s termem delat

% prace se znaky
% odbocka - retezce v prologu
% pomoci jednoduchych uvozovek 'toto je retezec'
% dvojite uvozovky konvertuji text to retezce ascii hodnot znaku
% [97,98,99]="abc".
% pomoci name/2 muzeme prevest atom na seznam znaku a obracene
% name(X,[97,98,99]).
% name('abc',X).

% zpet k praci se znaky
% put(X) - vypise znak X do vystupniho streamu
% get0(X) - nacte znak X ze vstupniho streamu a zunifikuje to s X
% get(X) - stejne jako get0, ale preskoci vsechny netisknutelne znaky
