has_no_prime_factor(N, []).
has_no_prime_factor(N, [X|L]) :-
  not(0 is mod(N, X)),
  has_no_prime_factor(N, L).


nth_prime(0, Candidate, FoundPrimes) :-
  length(FoundPrimes, C),
  write("nth_prime("),write(0),write(", "),write(Candidate),write(", "),write(C),write(")"),nl,
  has_no_prime_factor(Candidate, FoundPrimes),
  write("Found: "),write(Candidate),nl.

nth_prime(N, Candidate, FoundPrimes) :-
  length(FoundPrimes, C),
  write("nth_prime("),write(N),write(", "),write(Candidate),write(", "),write(C),write(")"),nl,
  N >= 0,
  has_no_prime_factor(Candidate, FoundPrimes),
  NextN is N - 1,
  NextCandidate is Candidate + 2,
  nth_prime(NextN, NextCandidate, [Candidate|FoundPrimes]).

nth_prime(N, Candidate, FoundPrimes) :-
  length(FoundPrimes, C),
  write("nth_prime("),write(N),write(", "),write(Candidate),write(", "),write(C),write(")"),nl,
  N >= 0,
  not(has_no_prime_factor(Candidate, FoundPrimes)),
  NextCandidate is Candidate + 2,
  nth_prime(N, NextCandidate, FoundPrimes).

find_nth_prime(1) :-
  write("Found: "),write(2),nl.

find_nth_prime(N) :-
  M is N - 2,
  nth_prime(M, 3, []).


