//////////////////////////////////////////////////////////////////////////////////////// // // Dean Clark's Problem (Clock Triplets Problem) // // The problem was originally posed by Dean Clark and then presented // to a larger audience by Martin Gardner. // // The problem was discussed in Dr. Dobbs's Journal, May 2004 in an article // by Timothy Rolfe. According to the article, in his August 1986 column for // Isaac Asimov's Science Fiction Magazine, Martin Gardner presented this problem: // // Now for a curious little combinatorial puzzle involving the twelve // numbers on the face of a clock. Can you rearrange the numbers (keeping // them in a circle) so no triplet of adjacent numbers has a sum higher // than 21? This is the smallest value that the highest sum of a triplet // can have. // // Timothy Rolfe solves the problem using a rather complex algorithm and also // presents a generic algorithm for numbers other than 12 (clock numbers) and // 21 (highest sums of triplets). The main emphasis of the algorithm was put // on the computational speed. The article stressed the fact that a simple // backtracking algorithm would be simply too slow due to the number of permutations. // // In this F1 sample, we achieve reasonable computational speeds while the code // is quite simple. The code, in the spirit of logical programming, does not require // us to specify any particular algorithm. // // Similar to Timothy Rolfe, we also use two optimizations to cut down on identical // solutions: // // 1. We nail down one number (number 12 to position 0). This reduces the // number of solutions by 12. // 2. We remove "mirror" solutions by postulating that the number right of 12 is // greater then the number left of 12. This reduces the number of solutions // by one half. // // These optimizations can be removed by simply commenting out the corresponding line. // // To solve the original problem, run the query // // all Cloque(x) // // The above query will generate all 261 solutions in about 12 seconds using a modest // AMD Athlon 1600+. // // The code for a general solution of the problem is in the predicate CloqueMN. // // For example, using the query: // // all CloqueMN(x,12,21) // // solves the original problem, // // all CloqueMN(x,13,23) // // will generate all solutions for a clock with 13 numbers with the highest sum of any // triplet being 23. // //////////////////////////////////////////////////////////////////////////////////////// pred Cloque(x::[0..11]->>L[1..12]) iff // 6264 solutions with no optimizations x(0) = 12 & // Optimization 1: nail down number 12 (522 solutions) x(1) > x(11) & // Optimization 2: remove mirror solutions (261 solutions) x(0) + x(1) + x(2) <= 21 & x(1) + x(2) + x(3) <= 21 & x(2) + x(3) + x(4) <= 21 & x(3) + x(4) + x(5) <= 21 & x(4) + x(5) + x(6) <= 21 & x(5) + x(6) + x(7) <= 21 & x(6) + x(7) + x(8) <= 21 & x(7) + x(8) + x(9) <= 21 & x(8) + x(9) + x(10) <= 21 & x(9) + x(10) + x(11) <= 21 & x(10) + x(11) + x(0) <= 21 & x(11) + x(0) + x(1) <= 21 // This is the code for the general case of an array of "m" elements // with the maximum value of the sum of any three consequitive elements being "n" pred CloqueMN(x::[0..]->>L[1..], m:<I,n:<I) iff Len(x,m) & // Set the length of the array to be "m" x(0) = m & // Optimization 1: nail down number "m" (reduce solutions to solutions/m) x(1) > x(m-1) & // Optimization 2: remove mirror solutions (reduce solutions by one half) CloqueMNEx(x,m,n,0) // Set the constraints for "m" and "n" local pred CloqueMNEx(x::[0..]->>L[1..], m:<I,n:<I,i:<I) iff if i < m then j = (i+1) mod m & k = (i+2) mod m & x(i) <= m & x(j) <= m & x(k) <= m & x(i) + x(j) + x(k) <= n & CloqueMNEx(x,m,n,i+1) end
This page was created by F1toHTML