-
Notifications
You must be signed in to change notification settings - Fork 1
/
074-total_match.dfy
63 lines (58 loc) · 1.61 KB
/
074-total_match.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
method TotalMatch(list1: seq<string>, list2: seq<string>) returns (result: seq<string>)
// post-conditions-start
ensures |result| == |list1| || |result| == |list2|
ensures result == list1 || result == list2
ensures sum_chars_rec(result) <= sum_chars_rec(list1)
ensures sum_chars_rec(result) <= sum_chars_rec(list2)
ensures sum_chars_rec(list1) == sum_chars_rec(list2) ==> result == list1
// post-conditions-end
{
// impl-start
var sum1 := SumChars(list1);
var sum2 := SumChars(list2);
if sum1 <= sum2 {
return list1;
} else {
return list2;
}
// impl-end
}
function sum_chars_rec(list: seq<string>): nat
{
if |list| == 0 then 0
else |list[0]| + sum_chars_rec(list[1..])
}
lemma sum_prop(s: seq<string>)
requires |s| > 0
ensures sum_chars_rec(s) == sum_chars_rec(s[..|s| - 1]) + |s[ |s| - 1 ]|
{
if (|s| > 1) {
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1];
}
}
method SumChars(list: seq<string>) returns (sum: nat)
// post-conditions-start
ensures sum == sum_chars_rec(list)
// post-conditions-end
{
// impl-start
sum := 0;
var i := 0;
while (i < |list|)
// invariants-start
invariant 0 <= i <= |list|
invariant sum == sum_chars_rec(list[..i])
// invariants-end
{
sum := sum + |list[i]|;
// assert-start
assert sum_chars_rec(list[..i + 1]) == sum_chars_rec(list[..i]) + |list[i]| by {
assert list[..i+1][..i] == list[..i];
sum_prop(list[..i + 1]);
}
// assert-end
i := i + 1;
}
assert list == list[..|list|]; // assert-line
// impl-end
}