How about machine-learning the Prolog version, using Inductive Logic Programming and Metagol [1]?
Here's one way to do it:
% e.g. place in metagol/examples/
:-['../metagol'].
% Second-order inductive bias.
metarule([P,Q],([P,A,A]:-[[Q,A]])).
metarule([P,Q,B,C],([P,A,B]:-[[Q,A,C]])).
% Learning primitives.
prim(positive_integer/1).
prim(exact_division/2).
% Primitives' definitions.
positive_integer(N):-
between(1,inf,N).
exact_division(X,Y):-
positive_integer(X)
,divisor(Y)
,0 is X mod Y.
divisor(3).
divisor(5).
divisor(15).
% Training setup.
learn_fizzbuzz:-
% Positive examples
Pos = [fizzbuzz(1,1)
,fizzbuzz(2,2)
,fizzbuzz(3,fizz)
,fizzbuzz(5,buzz)
,fizzbuzz(15,fizzbuzz)
]
% Negative examples
,Neg = [fizzbuzz(1,fizz)
,fizzbuzz(1,buzz)
,fizzbuzz(3,fizzbuzz)
,fizzbuzz(5,fizzbuzz)
]
% Train with metagol
,learn(Pos,Neg).
We can put that in a file, consult it and call learn_fizzbuzz at the Prolog repl:
?- learn_fizzbuzz.
% learning fizzbuzz/2
% clauses: 1
% clauses: 2
% clauses: 3
% clauses: 4
fizzbuzz(A,fizzbuzz):-exact_division(A,15).
fizzbuzz(A,buzz):-exact_division(A,5).
fizzbuzz(A,fizz):-exact_division(A,3).
fizzbuzz(A,A):-positive_integer(A).
true .
This will give us the fizzbuzz/2 function, mapping each integer N to {fizz,buzz,fizzbuzz,N}. Then we can simply loop over it:
print_fizzbuzz(N):-
forall(between(1,N,I)
,(fizzbuzz(I,FBN)
,writeln(FBN)
)
).
Note we learned a general version of fizzbuzz from only 5 positive and 4 negative examples. Just don't tell Joel Grus [2].
_______
[1] https://github.com/metagol/metagol
[2] http://joelgrus.com/2016/05/23/fizz-buzz-in-tensorflow/