cleaning up

parent 1d032a37
module M
(* How many integers 0 <= n < 10^18 have the property that the sum
of the digits of n equals the sum of digits of 137n? *)
of the digits of n equals the sum of digits of 137n?
The answer is 20444710234716473.
It can be easily computer using memoization (or, equivalently, dynamic
programming) once the problem is generalized as follows:
How many integers 0 <= n < 10^m are such that sd(n) = sd(137n + a) + b?
(* answer: 20444710234716473 *)
In the following, we prove the correctness of a recursive function f
which takes m, a, and b as arguments and returns the number of such n.
Memoization must be added if one wants to solve the initial problem.
(See for instance fib_memo.mlw for an example of memoized function.) *)
module M
use import int.Int
use import module ref.Ref
use import int.EuclideanDivision
use import int.Power
(*
function sum_digits (n:int) : int =
if n = 0 then 0 else sum_digits (div n 10) + mod n 10
*)
function sum_digits int : int
axiom Sum_digits_def : forall n : int. sum_digits n =
......@@ -54,33 +60,33 @@ module M
use import int.ComputerDivision
let rec sd n =
{ n >= 0 }
if n = 0 then 0 else sd (div n 10) + mod n 10
{ result = sum_digits n }
(* f(m,a,b) = the number of 0 <= n < 10^m such that
digitsum(137n+a) + b = digitsum(n). *)
let rec f m a b =
{ 0 <= m /\ 0 <= a }
if m = 0 then begin
(* only n = 0 is possible *)
if sd a + b = 0 then 1 else 0
end else begin
let sum = ref 0 in
let c = ref 0 in
while !c <= 9 do (* n = 10n' + c *)
invariant { 0 <= !c <= 10 /\ !sum = P.num_of (a,b,!c) 0 (power 10 m) }
variant { 10 - !c }
let x = 137 * !c + a in
let q = div x 10 in
let r = mod x 10 in
sum := !sum + f (m-1) q (r + b - !c);
c := !c + 1
done;
!sum
end
{ result = solution a b m }
let rec sd n =
{ n >= 0 }
if n = 0 then 0 else sd (div n 10) + mod n 10
{ result = sum_digits n }
(* f(m,a,b) = the number of 0 <= n < 10^m such that
digitsum(137n+a) + b = digitsum(n). *)
let rec f m a b =
{ 0 <= m /\ 0 <= a }
if m = 0 then begin
(* only n = 0 is possible *)
if sd a + b = 0 then 1 else 0
end else begin
let sum = ref 0 in
let c = ref 0 in
while !c <= 9 do (* n = 10n' + c *)
invariant { 0 <= !c <= 10 /\ !sum = P.num_of (a,b,!c) 0 (power 10 m) }
variant { 10 - !c }
let x = 137 * !c + a in
let q = div x 10 in
let r = mod x 10 in
sum := !sum + f (m-1) q (r + b - !c);
c := !c + 1
done;
!sum
end
{ result = solution a b m }
end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment