/* Dart scores in Picat. https://stackoverflow.com/questions/61892774/dart-scores-in-prolog """ I am trying to solve a task due tomorrow in Prolog. It's about the game of dart, and the program should calculate a way to reach an input score with three dart throws. The input program should be an integer n (1-180) and is the target score. The output should be a (any is okay) way of reaching the input score with max three throws. In other words, the sum of the accumulated points should add up to the input integer n. Each throw can either be a single, double or triple, just like in the game. Bullseyes are not a part of the problem. If the target score can't be reached, "impossible" should be printed. As an example: Input: 180 Output: triple 20, triple 20, triple 20 Input: 96 Output: triple 19, double 15, single 9 Input: 27 Output: triple 9 """ The first impossible score is 161. Here are all the impossible scores to reach: [161,163,164,166,167,169,170,172,173,175,176,178,179] 180 is - of course - the largest possible score to reach. This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go ?=> Score = 96, dart_scores(Score, Throws), println(Score=Throws), fail, nl. go => true. % % Check what numbers are impossible between 1..180. % go2 => Impossible = [], foreach(Score in 1..180) dart_scores(Score,Scores), println(Score=Scores), if Scores == [impossible] then Impossible := Impossible ++ [Score] end end, println(impossible=Impossible), nl. % % All scores has unique solutions. % go3 ?=> foreach(Score in 1..180) All=findall(Scores,dart_scores(Score,Scores)), println(Score=All) end, nl. go3 => true. % % Use a wrapper since some scores (e.g. 178) is detecting % to fail before solve/1. % dart_scores(Score,Scores) => if dart_scores_(Score, Scores_) then Scores = Scores_ else Scores = [impossible] end. dart_scores_(Score, Scores) => N = 3, Throws = new_list(N), Throws :: 0..20, Mult = new_list(N), Mult :: 0..3, Score #= sum([Throws[I]*Mult[I] : I in 1..N]), foreach(I in 1..N) Throws[I] #= 0 #<=> Mult[I] #= 0 end, Vars = Throws ++ Mult, solve(Vars), Mults = new_map([1=single,2=double,3=triple]), Scores = [to_fstring("%w %d",Mults.get(Mult[I]),Throws[I]) : I in 1..N, Mult[I] > 0].sort_down.