-
Notifications
You must be signed in to change notification settings - Fork 1
/
072-will_it_fly.dfy
67 lines (62 loc) · 1.57 KB
/
072-will_it_fly.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
method will_it_fly(s: seq<int>, w: int) returns (result: bool)
// pre-conditions-start
requires |s| > 0
// pre-conditions-end
// post-conditions-start
ensures result <==> is_palindrome_pred(s) && sum(s) <= w
// post-conditions-end
{
// impl-start
result := true;
var i := 0;
var j := |s| - 1;
while (i < j)
// invariants-start
invariant 0 <= i < |s|
invariant 0 <= j < |s|
invariant j == |s| - i - 1
invariant forall k :: 0 <= k < i ==> s[k] == s[|s| - 1 - k]
// invariants-end
{
if (s[i] != s[j]) {
result := false;
return;
}
i := i + 1;
j := j - 1;
}
var total := 0;
i := 0;
while (i < |s|)
// invariants-start
invariant 0 <= i <= |s|
invariant total == sum(s[..i])
// invariants-end
{
total := total + s[i];
// assert-start
assert sum(s[..i + 1]) == sum(s[..i]) + s[i] by {
assert s[..i+1][..i] == s[..i];
sum_prop(s[..i + 1]);
}
// assert-end
i := i + 1;
}
assert s[..|s|] == s; // assert-line
result := total <= w;
// impl-end
}
predicate is_palindrome_pred(s : seq<int>) {
forall k :: 0 <= k < |s| ==> s[k] == s[|s| - 1 - k]
}
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];
}
}