-
Notifications
You must be signed in to change notification settings - Fork 1
/
094-skjkasdkd.dfy
123 lines (112 loc) · 3 KB
/
094-skjkasdkd.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
method skjkasdkd(lst: seq<nat>) returns (dsum: nat)
// pre-conditions-start
requires exists i :: 0 <= i < |lst| && is_prime(lst[i])
// pre-conditions-end
// post-conditions-start
ensures dsum == digits_sum(max_seq(filter_primes(lst)))
// post-conditions-end
{
// impl-start
var primes := [];
var i := 0;
while i < |lst|
// invariants-start
invariant 0 <= i <= |lst|
invariant primes == filter_primes(lst[..i])
// invariants-end
{
if is_prime(lst[i]) {
primes := primes + [lst[i]];
}
// assert-start
assert filter_primes(lst[..i + 1]) == filter_primes(lst[..i]) + (
if is_prime(lst[i]) then [lst[i]] else []
) by {
assert lst[..i+1][..i] == lst[..i];
primes_prop(lst[..i + 1]);
}
// assert-end
i := i + 1;
}
assert lst[..|lst|] == lst; // assert-line
var max_prime := primes[0];
i := 1;
while i < |primes|
// invariants-start
invariant 1 <= i <= |primes|
invariant forall j :: 0 <= j < i ==> max_prime >= primes[j]
invariant max_prime == max_seq(primes[..i])
// invariants-end
{
max_prime := max(max_prime, primes[i]);
// assert-start
assert max_seq(primes[..i + 1]) == max(max_seq(primes[..i]), primes[i]) by {
assert primes[..i + 1][..i] == primes[..i];
max_prop(primes[..i + 1]);
}
// assert-end
i := i + 1;
}
assert primes[..|primes|] == primes; // assert-line
assert max_prime == max_seq(primes); // assert-line
dsum := digits_sum(max_prime);
// impl-end
}
function digits_sum(x: nat): nat {
if x == 0 then 0 else x % 10 + digits_sum(x / 10)
}
function max_seq(lst: seq<int>): (max: int)
// pre-conditions-start
requires |lst| > 0
// pre-conditions-end
// post-conditions-start
ensures forall i :: 0 <= i < |lst| ==> lst[i] <= max
// post-conditions-end
{
// impl-start
if |lst| == 1
then lst[0]
else
var suf := max_seq(lst[1..]);
max(lst[0], suf)
// impl-end
}
lemma max_prop(s: seq<int>)
requires |s| > 1
ensures max_seq(s) == max(max_seq(s[..|s| - 1]), s[|s| - 1])
{
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1];
}
function filter_primes(lst: seq<int>): (primes: seq<int>)
// post-conditions-start
ensures forall i :: 0 <= i < |primes| ==> is_prime(primes[i])
ensures forall i :: 0 <= i < |lst| && is_prime(lst[i]) ==> lst[i] in primes
// post-conditions-end
{
// impl-start
if |lst| == 0
then []
else
var tail := filter_primes(lst[1..]);
(if is_prime(lst[0]) then [lst[0]] else []) + tail
// impl-end
}
lemma primes_prop(s: seq<int>)
requires |s| > 0
ensures filter_primes(s) == filter_primes(s[..|s| - 1]) + (
if is_prime(s[|s| - 1]) then [s[|s| - 1]] else []
)
{
if (|s| > 1) {
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1];
}
}
function max(a: int, b: int): int
ensures max(a, b) == a || max(a, b) == b
ensures max(a, b) >= a && max(a, b) >= b
{
if a > b then a else b
}
predicate is_prime(k: int) {
k != 1 && forall i :: 2 <= i < k ==> k % i != 0
}