Skip to content

Commit 0ad0ebc

Browse files
authored
chore: cleanup and shorten names in Array.Merge (#762)
1 parent db73659 commit 0ad0ebc

File tree

2 files changed

+57
-82
lines changed

2 files changed

+57
-82
lines changed

Std/Data/Array/Merge.lean

Lines changed: 56 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -9,140 +9,115 @@ import Std.Data.Nat.Lemmas
99
namespace Array
1010

1111
/--
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.
1514
-/
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
2017
where
21-
/-- Auxiliary definition for `mergeSortedPreservingDuplicates`. -/
18+
/-- Auxiliary definition for `merge`. -/
2219
go (acc : Array α) (i j : Nat) : Array α :=
2320
if hi : i ≥ xs.size then
2421
acc ++ ys[j:]
2522
else if hj : j ≥ ys.size then
2623
acc ++ xs[i:]
2724
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
3125
let x := xs[i]
3226
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)
4228
termination_by xs.size + ys.size - (i + j)
4329

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+
4435
/--
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.
5040
-/
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
5543
where
56-
/-- Auxiliary definition for `mergeSortedMergingDuplicates`. -/
44+
/-- Auxiliary definition for `mergeDedupWith`. -/
5745
go (acc : Array α) (i j : Nat) : Array α :=
5846
if hi : i ≥ xs.size then
5947
acc ++ ys[j:]
6048
else if hj : j ≥ ys.size then
6149
acc ++ xs[i:]
6250
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
6651
let x := xs[i]
6752
let y := ys[j]
6853
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
8660

8761
/--
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.
9164
-/
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
9569

9670
set_option linter.unusedVariables false in
9771
/--
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.
10175
-/
102-
def mergeUnsortedDeduplicating [eq : BEq α] (xs ys : Array α) : Array α :=
76+
def mergeUnsortedDedup [eq : BEq α] (xs ys : Array α) : Array α :=
10377
-- Ideally we would check whether `xs` or `ys` have spare capacity, to prevent
10478
-- copying if possible. But Lean arrays don't expose their capacity.
10579
if xs.size < ys.size then go ys xs else go xs ys
10680
where
107-
/-- Auxiliary definition for `mergeUnsortedDeduplicating`. -/
108-
@[inline]
109-
go (xs ys : Array α) :=
81+
/-- Auxiliary definition for `mergeUnsortedDedup`. -/
82+
@[inline] go (xs ys : Array α) :=
11083
let xsSize := xs.size
11184
ys.foldl (init := xs) fun xs y =>
11285
if xs.any (· == y) (stop := xsSize) then xs else xs.push y
11386

87+
@[deprecated] alias mergeUnsortedDeduplicating := mergeUnsortedDedup
88+
11489
/--
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
11691
`f ⋯ (f (f x₁ x₂) x₃) ⋯ xₙ`.
11792
-/
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
12195
where
122-
/-- Auxiliary definition for `mergeAdjacentDuplicates`. -/
96+
/-- Auxiliary definition for `mergeAdjacentDups`. -/
12397
go (acc : Array α) (i : Nat) (hd : α) :=
12498
if h : i < xs.size then
12599
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
130101
else
131102
acc.push hd
132103
termination_by xs.size - i
133104

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
140106

141107
/--
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`.
143110
-/
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 α :=
145118
have := ord.toBEq
146-
deduplicateSorted <| xs.qsort (compare · · |>.isLT)
119+
dedupSorted <| xs.qsort (compare · · |>.isLT)
120+
121+
@[deprecated] alias sortAndDeduplicate := sortDedup
147122

148123
end Array

Std/Lean/Meta/DiscrTree.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ where
4242
/-- Auxiliary definition for `mergePreservingDuplicates`. -/
4343
mergeChildren (cs₁ cs₂ : Array (Key × Trie α)) :
4444
Array (Key × Trie α) :=
45-
Array.mergeSortedMergingDuplicates
45+
Array.mergeDedupWith
4646
(ord := ⟨compareOn (·.fst)⟩) cs₁ cs₂
4747
(fun (k₁, t₁) (_, t₂) => (k₁, mergePreservingDuplicates t₁ t₂))
4848

0 commit comments

Comments
 (0)