├── README.md └── str8ts.pl /README.md: -------------------------------------------------------------------------------- 1 | str8ts solver with constraint programming 2 | ====== 3 | written in [SWI-Prolog](http://www.swi-prolog.org/) using the [clpfd library](http://www.swi-prolog.org/man/clpfd.html) 4 | 5 | more about str8ts puzzles and their rules at [http://www.str8ts.com/](http://www.str8ts.com/) 6 | 7 | usage 8 | ----- 9 | Puzzle = [[1,2,3,4,5,6,7,_,"b"], 10 | [2,3,4,5,_,7,8,9,"b"], 11 | [3,_,"b",6,7,_,"b","b","b"], 12 | [_,5,6,7,8,"b",1,_,"b"], 13 | [5,6,7,8,9,1,2,3,4], 14 | [_,7,8,_,"b",2,_,4,5], 15 | [7,_,"b",1,2,_,4,"b",_], 16 | [_,9,"b",2,3,4,_,6,7], 17 | ["b",1,_,3,4,"b5",6,_,8]], str8ts(Puzzle). 18 | 19 | 20 | known issues 21 | -------- 22 | - depending on the puzzle more than ~25 empty cells will result in very long computation times with an exponential increase with each additional empty cell 23 | -------------------------------------------------------------------------------- /str8ts.pl: -------------------------------------------------------------------------------- 1 | :- use_module(library(clpfd)). 2 | 3 | str8ts(Puzzle):- 4 | maplist(magic, Puzzle), 5 | transpose(Puzzle, PuzzleT), 6 | maplist(magic, PuzzleT), 7 | printstr8ts(Puzzle). 8 | 9 | compartment([]). 10 | compartment(Compartment) :- 11 | length(Compartment,Laenge), 12 | minimum(Compartment,Min), 13 | maximum(Compartment,Max), 14 | Laenge-1 #= Max-Min. 15 | 16 | minimum([Min],Min). 17 | minimum([X,Y|Tail],Min) :- X #=< Y, minimum([X|Tail],Min). 18 | minimum([X,Y|Tail],Min) :- X #> Y, minimum([Y|Tail],Min). 19 | 20 | maximum([Max],Max). 21 | maximum([X,Y|Tail],Max) :- X #>= Y, maximum([X|Tail],Max). 22 | maximum([X,Y|Tail],Max) :- X #< Y, maximum([Y|Tail],Max). 23 | 24 | magic([]). 25 | magic(Row):- 26 | findcompartment(Row, ListC), 27 | findbnumbers(Row, ListB), 28 | append(ListC, ListCmerged), 29 | ListCmerged ins 1..9, 30 | append(ListB, ListCmerged, List), 31 | all_different(List), 32 | maplist(compartment, ListC). 33 | 34 | findcompartment([],[]). 35 | findcompartment(Row, [Comp|ListC]):- 36 | split(Row, Comp, Rest), 37 | findcompartment(Rest, ListC), !. 38 | 39 | 40 | split([],[],[]). 41 | split([X|Tail], [], Rest):- 42 | is_list(X), 43 | X = [A|_], 44 | [A] == "b", 45 | Rest = Tail, !. 46 | split([X|Tail], [X|Start], Rest):- 47 | split(Tail, Start, Rest). 48 | 49 | findbnumbers([],[]). 50 | findbnumbers([X|Tail], [S|Bs]):- 51 | is_list(X), 52 | length(X,2), 53 | X = [A,B], 54 | [A] == "b", 55 | number_codes(S, [B]), 56 | number(S), 57 | findbnumbers(Tail, Bs), !. 58 | findbnumbers([_|Tail], Bs):- findbnumbers(Tail, Bs). 59 | 60 | printstr8ts(Puzzle):- 61 | maplist(printrow, Puzzle). 62 | 63 | printrow(Row):- 64 | printzeichen(Row), 65 | writeln(''). 66 | 67 | printzeichen([]). 68 | printzeichen([X|Tail]):- 69 | is_list(X), 70 | length(X,2), 71 | writef("%s", [X]), 72 | write(' '), 73 | printzeichen(Tail), !. 74 | printzeichen([X|Tail]):- 75 | is_list(X), 76 | length(X,1), 77 | writef(" %s", [X]), 78 | write(' '), 79 | printzeichen(Tail), !. 80 | printzeichen([X|Tail]):- 81 | write(' '), 82 | write(X), 83 | write(' '), 84 | printzeichen(Tail). 85 | 86 | --------------------------------------------------------------------------------