-
Notifications
You must be signed in to change notification settings - Fork 1
/
036-fizz_buzz.dfy
78 lines (74 loc) · 1.83 KB
/
036-fizz_buzz.dfy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
method fizz_buzz(n: nat) returns (result: nat)
// post-conditions-start
ensures result == sum(
seq(n, i requires 0 <= i < n => (if i % 11 == 0 || i % 13 == 0 then count7_r(i) else 0))
)
// post-conditions-end
{
// impl-start
ghost var values := [];
result := 0;
var i := 0;
while i < n
// invariants-start
invariant 0 <= i <= n
invariant |values| == i
invariant result == sum(values[..i])
invariant values == seq(i, j requires 0 <= j < i => (if j % 11 == 0 || j % 13 == 0 then count7_r(j) else 0))
// invariants-end
{
ghost var pre := values;
if i % 11 == 0 || i % 13 == 0 {
var cnt := count7(i);
result := result + cnt;
values := values + [cnt];
} else {
values := values + [0];
}
assert values[..i] == pre[..i]; // assert-line
// assert-start
assert sum(values[..i + 1]) == sum(values[..i]) + values[i] by {
assert values[..i+1][..i] == values[..i];
sum_prop(values[..i + 1]);
}
// assert-end
i := i + 1;
}
assert values[..|values|] == values; // assert-line
// impl-end
}
method count7(x: nat) returns (count: nat)
// post-conditions-start
ensures count == count7_r(x)
// post-conditions-end
{
// impl-start
count := 0;
var y := x;
while y > 0
// invariants-start
invariant count + count7_r(y) == count7_r(x)
// invariants-end
{
if y % 10 == 7 {
count := count + 1;
}
y := y / 10;
}
// impl-end
}
function count7_r(x: nat): nat {
var lst := if x % 10 == 7 then 1 else 0;
if x < 10 then lst else lst + count7_r(x / 10)
}
function sum(s: seq<int>) : int {
if |s| == 0 then 0 else s[0] + sum(s[1..])
}
lemma sum_prop(s: seq<int>)
requires |s| > 0
ensures sum(s) == sum(s[..|s| - 1]) + s[ |s| - 1 ]
{
if (|s| > 1) {
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1];
}
}