% adapted from https://www.cpp.edu/~jrfisher/www/prolog_tutorial/2_15.html
% start with: swipl -s graph.pl

edge(1, 3).
edge(1, 5).
edge(2, 4).
edge(3, 2).
edge(3, 5).
edge(4, 3).
edge(6, 1).
edge(6, 5).

% "connected" if there is there a way to get from X to Z.
connected(X, Y) :- edge(X, Y).
connected(X, Y) :- edge(X, Z), connected(Z, Y).

% "path" if the third arg is a path from X to Y.
path(X, Y, [X,Y]) :- edge(X, Y).
path(X, Y, [X|Path]) :-
    edge(X, Z),
    path(Z, Y, Path).

% "noloop" if there is a path from X to Y using the listed visited nodes in the path.
noloop(X, Y, [X,Y]) :- edge(X, Y).
noloop(X, Y, [X|Path]) :-
    edge(X, Z),
    \+ member(X, Path),
    noloop(Z, Y, Path).

% "hailstone" if the list is the hailstone sequence after N.
hailstone(1, []).
hailstone(N, [H|Tail]) :-
    N > 1,
    mod(N, 2) =:= 0,
    H is div(N, 2),
    hailstone(H, Tail).
hailstone(N, [H|Tail]) :-
    N > 1,
    mod(N, 2) =:= 1,
    H is 3*N + 1,
    hailstone(H, Tail).

% attempt to write my own not_member predicate that allows searching, but it doesn't.
not_member(_, []).
not_member(X, [Y|Tail]) :-
    X \= Y,
    not_member(X, Tail).

noloop2(X, Y, [X,Y]) :- edge(X, Y).
noloop2(X, Y, [X|Path]) :-
    edge(X, Z),
    not_member(X, Path),
    noloop2(Z, Y, Path).
