should read xplusone(x) rather than xplusone(2). ]]>

Yes and to to the question about imperative logic in Prolog. “No”, because Prolog doesn’t have loops and destructive variable assignments in the sense of most other programming languages; “yes”, because you can usually write down a very efficient tail-recursive formulation of the looping computation that will be executed as if it had been an imperative loop.

Here’s the Fibonacci-up-to-N example:

fibonacci_sequence(N, FibonacciSequence) :-

fibonacci_sequence(0, 1, N, [], FibonacciSequence).

fibonacci_sequence(A, _B, N, Sequence, Sequence) :-

A > N,

!.

fibonacci_sequence(A, B, N, Sequence0, [A|Sequence1]) :-

A =< N,

C is A + B,

fibonacci_sequence(B, C, N, Sequence0, Sequence1).

This is somewhat similar to how it would be structured in Haskell or other functional languages: The "loop" is put into an auxiliary definition with extra arguments that are initialized to 0 and 1; inside the loop, you compare, compute, and recurse.

And here is how you can use this in the Prolog REPL to find a solution to the sum-of-even-Fibonacci-numbers example:

?- fibonacci_sequence(4000000, Seq), findall(E, (member(E, Seq), E mod 2 =:= 0), Evens), sumlist(Evens, Sum).

Seq = [0, 1, 1, 2, 3, 5, 8, 13, 21|…],

Evens = [0, 2, 8, 34, 144, 610, 2584, 10946, 46368|…],

Sum = 4613732.

thanks for your answer. Yes, the usual way of writing Prolog program is generic in the sense that it follows (or, rather, *can* follow) a generate-and-test approach as you describe in your post on specification driven design. And thanks for confirming that your derive-known-plaintext function can solve the original puzzle completely. That’s a very nice and powerful technique that you use there! ]]>