-
Notifications
You must be signed in to change notification settings - Fork 1
/
104-unique_digits.dfy
71 lines (66 loc) · 2.11 KB
/
104-unique_digits.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
predicate HasNoEvenDigit(n: int)
decreases n
{
n >= 0 && ((n < 10 && n % 2 == 1) || (n % 2 == 1 && HasNoEvenDigit(n / 10)))
}
method UniqueDigits(x: seq<int>) returns (result: seq<int>)
// post-conditions-start
ensures forall i :: 0 <= i < |result| ==> HasNoEvenDigit(result[i])
ensures forall i, j :: 0 <= i < j < |result| ==> result[i] <= result[j]
ensures forall e :: e in x && HasNoEvenDigit(e) ==> e in result
ensures forall e :: e in result ==> e in x
// post-conditions-end
{
// impl-start
result := [];
for i := 0 to |x|
// invariants-start
invariant forall j :: 0 <= j < |result| ==> HasNoEvenDigit(result[j])
invariant forall e :: e in result ==> e in x[..i]
invariant forall e :: e in x[..i] && HasNoEvenDigit(e) ==> e in result
// invariants-end
{
if HasNoEvenDigit(x[i]) {
result := result + [x[i]];
}
}
ghost var unsorted := result;
var i := 0;
while i < |result|
// invariants-start
invariant 0 <= i <= |result|
invariant forall j, k :: 0 <= j < k < i ==> result[j] <= result[k]
invariant multiset(unsorted) == multiset(result)
invariant forall j :: 0 <= j < i ==> forall k :: i <= k < |result| ==> result[j] <= result[k]
invariant forall e :: e in result ==> HasNoEvenDigit(e)
invariant forall e :: e in result ==> e in x
// invariants-end
{
var minIndex := i;
var j := i + 1;
while j < |result|
// invariants-start
invariant i <= minIndex < j <= |result|
invariant forall k :: i <= k < j ==> result[minIndex] <= result[k]
// invariants-end
{
if result[j] < result[minIndex] {
minIndex := j;
}
j := j + 1;
}
if minIndex != i {
var temp := result[i];
result := result[i := result[minIndex]][minIndex := temp];
}
i := i + 1;
}
assert forall e :: e in result ==> HasNoEvenDigit(e); // assert-line
assert forall e :: e in result ==> e in x; // assert-line
// assert-start
assert forall e :: e in x && HasNoEvenDigit(e) ==> e in result by {
assert forall e :: e in unsorted ==> e in multiset(result);
}
// assert-end
// impl-end
}