-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmerge.dfy
executable file
·72 lines (68 loc) · 2.09 KB
/
merge.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
module Merge {
predicate sorted(s: seq<int>)
{
forall i,j :: 0 <= i < j < |s| ==> s[i] <= s[j]
}
// Helper lemma that you will likely need to call.
// It states that if an element i is in the union of two multisets a and b,
// Then it is in a or in b
lemma set_union(a:multiset<int>, b:multiset<int>)
ensures forall i :: i in a + b <==> i in a || i in b
{ }
/** [merge(a, b)] takes two sorted arrays, and returns a new sorted array [c]
containing all elements of [a] and [b] */
method merge(a:array<int>, b:array<int>) returns (c:array<int>)
requires sorted(a[..])
requires sorted(b[..])
ensures sorted(c[..])
// Multiset returns sets of elements, where each element can occur multiple times.
// It is explained in more details in the online Dafny tutorial (https://rise4fun.com/Dafny/tutorial/Collections)
// You will very likely need the set_union lemma provided earlier
ensures multiset(a[..]) + multiset(b[..]) == multiset(c[..])
{
c := new int[a.Length + b.Length];
assert (a[..(a.Length)] == a[..]);
assert (b[..(b.Length)] == b[..]);
// TODO: Complete the implementation here.
// We recommend you leave the previous two assertions at the beginning of your code,
// and the last one at the end of your code
var ai := 0;
var bi := 0;
var ci := 0;
while ci < c.Length
invariant 0 <= ai <= a.Length
invariant 0 <= bi <= b.Length
invariant ci == ai + bi
invariant multiset(c[..ci]) == multiset(a[..ai]) + multiset(b[..bi])
invariant sorted(a[..ai])
invariant forall k :: bi < b.Length && 0 <= k < ai ==> a[k] <= b[bi]
invariant sorted(b[..bi])
invariant forall k :: ai < a.Length && 0 <= k < bi ==> b[k] <= a[ai]
invariant forall k :: 0 <= k < ci ==> c[k] in a[..ai] || c[k] in b[..bi]
invariant sorted(c[..ci])
{
if ai == a.Length
{
c[ci] := b[bi];
bi := bi + 1;
}
else if bi == b.Length
{
c[ci] := a[ai];
ai := ai + 1;
}
else if a[ai] <= b[bi]
{
c[ci] := a[ai];
ai := ai + 1;
}
else
{
c[ci] := b[bi];
bi := bi + 1;
}
ci := ci + 1;
}
assert (c[..(c.Length)] == c[..]);
}
}