@@ -9,140 +9,115 @@ import Std.Data.Nat.Lemmas
9
9
namespace Array
10
10
11
11
/--
12
- Merge arrays `xs` and `ys`, which must be sorted according to `compare`. The
13
- result is sorted as well. If two (or more) elements are equal according to
14
- `compare`, they are preserved.
12
+ `O(|xs| + |ys|)`. Merge arrays `xs` and `ys`. If the arrays are sorted according to `lt`, then the
13
+ result is sorted as well. If two (or more) elements are equal according to `lt`, they are preserved.
15
14
-/
16
- def mergeSortedPreservingDuplicates [ord : Ord α] (xs ys : Array α) :
17
- Array α :=
18
- let acc := Array.mkEmpty (xs.size + ys.size)
19
- go acc 0 0
15
+ def merge (lt : α → α → Bool) (xs ys : Array α) : Array α :=
16
+ go (Array.mkEmpty (xs.size + ys.size)) 0 0
20
17
where
21
- /-- Auxiliary definition for `mergeSortedPreservingDuplicates `. -/
18
+ /-- Auxiliary definition for `merge `. -/
22
19
go (acc : Array α) (i j : Nat) : Array α :=
23
20
if hi : i ≥ xs.size then
24
21
acc ++ ys[j:]
25
22
else if hj : j ≥ ys.size then
26
23
acc ++ xs[i:]
27
24
else
28
- have hi : i < xs.size := Nat.lt_of_not_le hi
29
- have hj : j < ys.size := Nat.lt_of_not_le hj
30
- have hij : i + j < xs.size + ys.size := Nat.add_lt_add hi hj
31
25
let x := xs[i]
32
26
let y := ys[j]
33
- if compare x y |>.isLE then
34
- have : xs.size + ys.size - (i + 1 + j) < xs.size + ys.size - (i + j) := by
35
- rw [show i + 1 + j = i + j + 1 by simp_arith]
36
- exact Nat.sub_succ_lt_self _ _ hij
37
- go (acc.push x) (i + 1 ) j
38
- else
39
- have : xs.size + ys.size - (i + j + 1 ) < xs.size + ys.size - (i + j) :=
40
- Nat.sub_succ_lt_self _ _ hij
41
- go (acc.push y) i (j + 1 )
27
+ if lt x y then go (acc.push x) (i + 1 ) j else go (acc.push y) i (j + 1 )
42
28
termination_by xs.size + ys.size - (i + j)
43
29
30
+ set_option linter.unusedVariables false in
31
+ @[deprecated merge, inherit_doc merge]
32
+ def mergeSortedPreservingDuplicates [ord : Ord α] (xs ys : Array α) : Array α :=
33
+ merge (compare · · |>.isLT) xs ys
34
+
44
35
/--
45
- Merge arrays `xs` and `ys`, which must be sorted according to `compare` and must
46
- not contain duplicates. Equal elements are merged using `merge`. If `merge`
47
- respects the order (i.e. for all `x`, `y`, `y'`, `z`, if `x < y < z` and
48
- `x < y' < z` then `x < merge y y' < z`) then the resulting array is again
49
- sorted.
36
+ `O(|xs| + |ys|)`. Merge arrays `xs` and `ys`, which must be sorted according to `compare` and must
37
+ not contain duplicates. Equal elements are merged using `merge`. If `merge` respects the order
38
+ (i.e. for all `x`, `y`, `y'`, `z`, if `x < y < z` and `x < y' < z` then `x < merge y y' < z`)
39
+ then the resulting array is again sorted.
50
40
-/
51
- def mergeSortedMergingDuplicates [ord : Ord α] (xs ys : Array α)
52
- (merge : α → α → α) : Array α :=
53
- let acc := Array.mkEmpty (xs.size + ys.size)
54
- go acc 0 0
41
+ def mergeDedupWith [ord : Ord α] (xs ys : Array α) (merge : α → α → α) : Array α :=
42
+ go (Array.mkEmpty (xs.size + ys.size)) 0 0
55
43
where
56
- /-- Auxiliary definition for `mergeSortedMergingDuplicates `. -/
44
+ /-- Auxiliary definition for `mergeDedupWith `. -/
57
45
go (acc : Array α) (i j : Nat) : Array α :=
58
46
if hi : i ≥ xs.size then
59
47
acc ++ ys[j:]
60
48
else if hj : j ≥ ys.size then
61
49
acc ++ xs[i:]
62
50
else
63
- have hi : i < xs.size := Nat.lt_of_not_le hi
64
- have hj : j < ys.size := Nat.lt_of_not_le hj
65
- have hij : i + j < xs.size + ys.size := Nat.add_lt_add hi hj
66
51
let x := xs[i]
67
52
let y := ys[j]
68
53
match compare x y with
69
- | Ordering.lt =>
70
- have : xs.size + ys.size - (i + 1 + j) < xs.size + ys.size - (i + j) := by
71
- rw [show i + 1 + j = i + j + 1 by simp_arith]
72
- exact Nat.sub_succ_lt_self _ _ hij
73
- go (acc.push x) (i + 1 ) j
74
- | Ordering.gt =>
75
- have : xs.size + ys.size - (i + j + 1 ) < xs.size + ys.size - (i + j) :=
76
- Nat.sub_succ_lt_self _ _ hij
77
- go (acc.push y) i (j + 1 )
78
- | Ordering.eq =>
79
- have : xs.size + ys.size - (i + 1 + (j + 1 )) < xs.size + ys.size - (i + j) := by
80
- rw [show i + 1 + (j + 1 ) = i + j + 2 by simp_arith]
81
- apply Nat.sub_add_lt_sub _ (by decide)
82
- rw [show i + j + 2 = (i + 1 ) + (j + 1 ) by simp_arith]
83
- exact Nat.add_le_add hi hj
84
- go (acc.push (merge x y)) (i + 1 ) (j + 1 )
85
- termination_by xs.size + ys.size - (i + j)
54
+ | .lt => go (acc.push x) (i + 1 ) j
55
+ | .gt => go (acc.push y) i (j + 1 )
56
+ | .eq => go (acc.push (merge x y)) (i + 1 ) (j + 1 )
57
+ termination_by xs.size + ys.size - (i + j)
58
+
59
+ @[deprecated] alias mergeSortedMergingDuplicates := mergeDedupWith
86
60
87
61
/--
88
- Merge arrays `xs` and `ys`, which must be sorted according to `compare` and must
89
- not contain duplicates. If an element appears in both `xs` and `ys`, only one
90
- copy is kept.
62
+ `O(|xs| + |ys|)`. Merge arrays `xs` and `ys`, which must be sorted according to `compare` and must
63
+ not contain duplicates. If an element appears in both `xs` and `ys`, only one copy is kept.
91
64
-/
92
- @[inline]
93
- def mergeSortedDeduplicating [ord : Ord α] (xs ys : Array α) : Array α :=
94
- mergeSortedMergingDuplicates (ord := ord) xs ys fun x _ => x
65
+ @[inline] def mergeDedup [ord : Ord α] (xs ys : Array α) : Array α :=
66
+ mergeDedupWith (ord := ord) xs ys fun x _ => x
67
+
68
+ @[deprecated] alias mergeSortedDeduplicating := mergeDedup
95
69
96
70
set_option linter.unusedVariables false in
97
71
/--
98
- Merge `xs` and `ys`, which do not need to be sorted. Elements which occur in
99
- both `xs` and `ys` are only added once. If `xs` and `ys` do not contain
100
- duplicates, then neither does the result. O(n*m)!
72
+ `O(|xs| * |ys|)`. Merge `xs` and `ys`, which do not need to be sorted. Elements which occur in
73
+ both `xs` and `ys` are only added once. If `xs` and `ys` do not contain duplicates, then neither
74
+ does the result.
101
75
-/
102
- def mergeUnsortedDeduplicating [eq : BEq α] (xs ys : Array α) : Array α :=
76
+ def mergeUnsortedDedup [eq : BEq α] (xs ys : Array α) : Array α :=
103
77
-- Ideally we would check whether `xs` or `ys` have spare capacity, to prevent
104
78
-- copying if possible. But Lean arrays don't expose their capacity.
105
79
if xs.size < ys.size then go ys xs else go xs ys
106
80
where
107
- /-- Auxiliary definition for `mergeUnsortedDeduplicating`. -/
108
- @[inline]
109
- go (xs ys : Array α) :=
81
+ /-- Auxiliary definition for `mergeUnsortedDedup`. -/
82
+ @[inline] go (xs ys : Array α) :=
110
83
let xsSize := xs.size
111
84
ys.foldl (init := xs) fun xs y =>
112
85
if xs.any (· == y) (stop := xsSize) then xs else xs.push y
113
86
87
+ @[deprecated] alias mergeUnsortedDeduplicating := mergeUnsortedDedup
88
+
114
89
/--
115
- Replace each run `[x₁, ⋯, xₙ]` of equal elements in `xs` with
90
+ `O(|xs|)`. Replace each run `[x₁, ⋯, xₙ]` of equal elements in `xs` with
116
91
`f ⋯ (f (f x₁ x₂) x₃) ⋯ xₙ`.
117
92
-/
118
- def mergeAdjacentDuplicates [eq : BEq α] (f : α → α → α) (xs : Array α) :
119
- Array α :=
120
- if h : 0 < xs.size then go #[] 1 (xs.get ⟨0 , h⟩) else xs
93
+ def mergeAdjacentDups [eq : BEq α] (f : α → α → α) (xs : Array α) : Array α :=
94
+ if h : 0 < xs.size then go (mkEmpty xs.size) 1 (xs.get ⟨0 , h⟩) else xs
121
95
where
122
- /-- Auxiliary definition for `mergeAdjacentDuplicates `. -/
96
+ /-- Auxiliary definition for `mergeAdjacentDups `. -/
123
97
go (acc : Array α) (i : Nat) (hd : α) :=
124
98
if h : i < xs.size then
125
99
let x := xs[i]
126
- if x == hd then
127
- go acc (i + 1 ) (f hd x)
128
- else
129
- go (acc.push hd) (i + 1 ) x
100
+ if x == hd then go acc (i + 1 ) (f hd x) else go (acc.push hd) (i + 1 ) x
130
101
else
131
102
acc.push hd
132
103
termination_by xs.size - i
133
104
134
- /--
135
- Deduplicate a sorted array. The array must be sorted with to an order which
136
- agrees with `==`, i.e. whenever `x == y` then `compare x y == .eq`.
137
- -/
138
- def deduplicateSorted [eq : BEq α] (xs : Array α) : Array α :=
139
- xs.mergeAdjacentDuplicates (eq := eq) fun x _ => x
105
+ @[deprecated] alias mergeAdjacentDuplicates := mergeAdjacentDups
140
106
141
107
/--
142
- Sort and deduplicate an array.
108
+ `O(|xs|)`. Deduplicate a sorted array. The array must be sorted with to an order which agrees with
109
+ `==`, i.e. whenever `x == y` then `compare x y == .eq`.
143
110
-/
144
- def sortAndDeduplicate [ord : Ord α] (xs : Array α) : Array α :=
111
+ def dedupSorted [eq : BEq α] (xs : Array α) : Array α :=
112
+ xs.mergeAdjacentDups (eq := eq) fun x _ => x
113
+
114
+ @[deprecated] alias deduplicateSorted := dedupSorted
115
+
116
+ /-- `O(|xs| log |xs|)`. Sort and deduplicate an array. -/
117
+ def sortDedup [ord : Ord α] (xs : Array α) : Array α :=
145
118
have := ord.toBEq
146
- deduplicateSorted <| xs.qsort (compare · · |>.isLT)
119
+ dedupSorted <| xs.qsort (compare · · |>.isLT)
120
+
121
+ @[deprecated] alias sortAndDeduplicate := sortDedup
147
122
148
123
end Array
0 commit comments