:- use_module(library(lists),[nth1/3]). :- use_module(contestlib,[for/3, map/3]). :- op(100,xfx,.). :- op(200,fy,\). board(InitialBoard,Min,HowMany) :- length(InitialBoard,Size), mknewboard(InitialBoard,NewBoard), setof(Value,NewBoard^value(NewBoard,Size,Value),[Min|_]), findall(Min,value(NewBoard,Size,Min),MinVals), length(MinVals,HowMany). value(Board,Size,Value) :- for(X,1,Size), for(Y,1,Size), keepmoving(Size*Size,X,Y,Board,Size,0,Value). keepmoving(N,X,Y,Board,Size,CurrentVal,Result) :- nth1(X,Board,XRow), nth1(Y,XRow,Lambda), eval(Lambda,CurrentVal,CurrentVal1), N1 is N - 1, ( N1 == 0 -> Result = CurrentVal1 ; next(X,Y,NextX,NextY), 0 < NextX, NextX =< Size, 0 < NextY, NextY =< Size, keepmoving(N1,NextX,NextY,Board,Size,CurrentVal1,Result) ). eval(\Z.Expr,In,Out) :- var(Z), Z = In, Out is Expr. next(X,Y,NextX,NextY) :- NextX = X, NextY is Y + 1. next(X,Y,NextX,NextY) :- NextX = X, NextY is Y - 1. next(X,Y,NextX,NextY) :- NextX is X + 1, NextY = Y. next(X,Y,NextX,NextY) :- NextX is X - 1, NextY = Y. mknewboard(In,Out) :- map(In,mknewrow,Out). mknewrow(In,Out) :- map(In,mknewsquare,Out). mknewsquare(op(A,B),\Z.Expr) :- Expr =.. [A,Z,B].