Guest User

Untitled

a guest
Jan 18th, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.29 KB | None | 0 0
  1. % COMP30020 - Declarative Programming 2017 Semester 2
  2. % Written by Jie Jenny Yan - 693839
  3.  
  4. % Written for the purpose of solving maths puzzles.
  5. % A maths puzzle is a square grid of squares, each to be filled in
  6. % with a single digit from 1 to 9. It must satisfy the following
  7. % constraints:
  8. % - each row and each column contains no repeated digits
  9. % - all squares on the diagonal line from upper left to lower right
  10. % contain the same value
  11. % - the heading of each row and column (leftmost square in a row and topmost
  12. % square in a column) holds either the sum or the product of all the digits
  13. % in that row or column
  14. % This program solves this puzzle and filles in the blanks (finds the values
  15. % that satisfy the above mentioned conditions) and produces a solution ONLY if
  16. % one solution for that puzzle exists.
  17. % (We assume that the row and column headings are not considered to be part of
  18. % the row or column and so do not need to conform to the first 2 conditions.
  19.  
  20. :- use_module(library(clpfd)).
  21. :- ensure_loaded(library(clpfd)).
  22.  
  23. % puzzle_solution takes a list of lists (size N x N) and checks whether
  24. % the puzzle satisfies each of the conditions of a maths puzzle.
  25. puzzle_solution(Puzzle) :-
  26. Puzzle = [_|Tail],
  27. check_diagonal(_, 1, Tail),
  28. maplist(check, Tail),
  29. transpose(Puzzle, [_|Columns]),
  30. maplist(check, Columns),
  31. maplist(label, Puzzle).
  32.  
  33. % checks whether the diagonal digits all have the same value
  34. % base case: each list in the list of lists has been checked
  35. % recurse over the list of lists, checking each diagonal element, starting
  36. % at index 1 of the first row since index 0 refers to the row header
  37. check_diagonal(_, _, []).
  38. check_diagonal(Diag, N, [Head|Tail]) :-
  39. N0 is N + 1,
  40. get_diag_elem(Head, N, Diag),
  41. check_diagonal(Diag, N0, Tail).
  42.  
  43. % helper function that gets the diagonal element of a particular row at
  44. % index 'N' and checks that this value is equal to our first diagonal element
  45. get_diag_elem( [Head|_], 0, Head).
  46. get_diag_elem( [_|Tail], N, Diag):-
  47. N0 is N - 1,
  48. get_diag_elem(Tail, N0, Diag).
  49.  
  50. % checking if all Tail elements are distinct and whether the sum or prod
  51. % of the tail is equal to their respective head values, where head is the
  52. % first element in the given list and tail is the remaining elements.
  53. check([Head|Tail]) :-
  54. (sum_list(Tail, Head); prod_list(Tail, Head)),
  55. all_distinct(Tail).
  56.  
  57. % checks if the sum of a list matches the given sum value (row/col header)
  58. sum_list(List, Sum) :-
  59. sum_list(List, 0, Sum).
  60.  
  61. % recursively adds the elements to sum0 (initial sum), until we have
  62. % cycled through all elements in the list and checks that the final sum matches
  63. % our given sum (row/col header)
  64. sum_list([], Sum, Sum).
  65. sum_list([Head|Tail], Sum0, Sum) :-
  66. between(1,9,Head),
  67. Sum1 is Sum0 + Head,
  68. sum_list(Tail, Sum1, Sum).
  69.  
  70. % similar to the sum_list function, prod_list checks if the prod of the list
  71. % matches the given prod value (row/col header)
  72. prod_list(List, Sum) :-
  73. prod_list(List, 1, Sum).
  74.  
  75. % recursively multiplies the elements to prod0 (initial prod), until we have
  76. % cycled through all elements in the list and checks that the final prod
  77. % matches our given prod (row/col header)
  78. prod_list([], Prod, Prod).
  79. prod_list([Head|Tail], Prod0, Prod) :-
  80. between(1,9,Head),
  81. Prod1 is Prod0 * Head,
  82. prod_list(Tail, Prod1, Prod).
Add Comment
Please, Sign In to add comment