changeset 65:69eb40c46798

Add some "Eight Queens" solving Still trying to get my head in quite the right space.
author IBBoard <dev@ibboard.co.uk>
date Sun, 01 Oct 2017 19:59:48 +0100
parents f6fce6a54e94
children 2acc1ad8d365
files 3-Prolog/day3-8queens.pl
diffstat 1 files changed, 49 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/3-Prolog/day3-8queens.pl	Sun Oct 01 19:59:48 2017 +0100
@@ -0,0 +1,49 @@
+% Eight Queens problem, written from just the rules and a few hints on available approaches
+% which includes the "member/2" and other useful functions.
+% This will be MUCH more succinct than defining the entire board and trying
+% to operate on that! Half of the problem is approaching the problem correctly.
+
+eight_queens(List) :-
+    % Check we've got the right length
+    length(List, 8),
+    % Check our values are all valid positions
+    valid_board(List),
+    % Pull out the rows
+    rows(List, Rows),
+    % Pull out the columns
+    columns(List, Cols),
+    % Pull out the diagonals (North-East/South-West)
+    diagonals_sw_ne(List, Diags1),
+    % Pull out the diagonals (North-West/South-East)
+    diagonals_nw_se(List, Diags2),
+
+    % Make sure we have no duplicates - based on the simple Sudoku solver
+    fd_all_different(Rows),
+    fd_all_different(Cols),
+    fd_all_different(Diags1),
+    fd_all_different(Diags2).
+
+valid_board([]).
+valid_board([Head|Tail]) :- valid_queen(Head), valid_board(Tail).
+
+% Queen location defined as a tuple
+valid_queen((Row, Col)) :-
+    Range = [1,2,3,4,5,6,7,8],
+    member(Row, Range), member(Col, Range).
+
+rows([], []).
+% This is a bit weird - Tail on the left matches and populates Tail on the right
+% Then we invoke the sub-goal and generate RowTail recursively, which populates
+% RowTail on the left. Easier than assignment, and probably tail recursive.
+rows([(Row, _)|Tail], [Row|RowTail]) :- rows(Tail, RowTail).
+
+columns([], []).
+columns([(_, Col)|Tail], [Col|ColTail]) :- columns(Tail, ColTail).
+
+diagonals_nw_se([], []).
+% Diagonals intersec the axis at consistent places, which we can approximate with Row + Col
+diagonals_nw_se([(Row,Col)|Tail], [Diag|DiagTail]) :- Diag is Row + Col, diagonals_nw_se(Tail, DiagTail).
+
+diagonals_sw_ne([], []).
+% Ditto the other diagonal, but use Row - Col because they slope the other way
+diagonals_sw_ne([(Row,Col)|Tail], [Diag|DiagTail]) :- Diag is Row - Col, diagonals_sw_ne(Tail, DiagTail).
\ No newline at end of file