Skip to content

Commit c15ba02

Browse files
zaxioms0mo271
andcommitted
feat: Port/data.list.destutter (#1466)
feat: Port/Data.List.Destutter Co-authored-by: Moritz Firsching <firsching@google.com>
1 parent 61e7d4f commit c15ba02

File tree

2 files changed

+184
-0
lines changed

2 files changed

+184
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ import Mathlib.Data.List.Chain
254254
import Mathlib.Data.List.Count
255255
import Mathlib.Data.List.Dedup
256256
import Mathlib.Data.List.Defs
257+
import Mathlib.Data.List.Destutter
257258
import Mathlib.Data.List.Duplicate
258259
import Mathlib.Data.List.Forall2
259260
import Mathlib.Data.List.Func

Mathlib/Data/List/Destutter.lean

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/-
2+
Copyright (c) 2022 Eric Rodriguez. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Eric Rodriguez, Eric Wieser
5+
6+
! This file was ported from Lean 3 source module data.list.destutter
7+
! leanprover-community/mathlib commit 7b78d1776212a91ecc94cf601f83bdcc46b04213
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Data.List.Chain
12+
13+
/-!
14+
# Destuttering of Lists
15+
16+
This file proves theorems about `List.destutter` (in `Data.List.Defs`), which greedily removes all
17+
non-related items that are adjacent in a list, e.g. `[2, 2, 3, 3, 2].destutter (≠) = [2, 3, 2]`.
18+
Note that we make no guarantees of being the longest sublist with this property; e.g.,
19+
`[123, 1, 2, 5, 543, 1000].destutter (<) = [123, 543, 1000]`, but a longer ascending chain could be
20+
`[1, 2, 5, 543, 1000]`.
21+
22+
## Main statements
23+
24+
* `List.destutter_sublist`: `l.destutter` is a sublist of `l`.
25+
* `List.destutter_is_chain'`: `l.destutter` satisfies `Chain' R`.
26+
* Analogies of these theorems for `List.destutter'`, which is the `destutter` equivalent of `Chain`.
27+
28+
## Tags
29+
30+
adjacent, chain, duplicates, remove, list, stutter, destutter
31+
-/
32+
33+
34+
variable {α : Type _} (l : List α) (R : α → α → Prop) [DecidableRel R] {a b : α}
35+
36+
namespace List
37+
38+
@[simp]
39+
theorem destutter'_nil : destutter' R a [] = [a] :=
40+
rfl
41+
#align list.destutter'_nil List.destutter'_nil
42+
43+
theorem destutter'_cons :
44+
(b :: l).destutter' R a = if R a b then a :: destutter' R b l else destutter' R a l :=
45+
rfl
46+
#align list.destutter'_cons List.destutter'_cons
47+
48+
variable {R}
49+
50+
@[simp]
51+
theorem destutter'_cons_pos (h : R b a) : (a :: l).destutter' R b = b :: l.destutter' R a := by
52+
rw [destutter', if_pos h]
53+
#align list.destutter'_cons_pos List.destutter'_cons_pos
54+
55+
@[simp]
56+
theorem destutter'_cons_neg (h : ¬R b a) : (a :: l).destutter' R b = l.destutter' R b := by
57+
rw [destutter', if_neg h]
58+
#align list.destutter'_cons_neg List.destutter'_cons_neg
59+
60+
variable (R)
61+
62+
@[simp]
63+
theorem destutter'_singleton : [b].destutter' R a = if R a b then [a, b] else [a] := by
64+
split_ifs with h <;> simp! [h]
65+
#align list.destutter'_singleton List.destutter'_singleton
66+
67+
theorem destutter'_sublist (a) : l.destutter' R a <+ a :: l :=
68+
by
69+
induction' l with b l hl generalizing a
70+
· simp
71+
rw [destutter']
72+
split_ifs
73+
· exact Sublist.cons₂ a (hl b)
74+
· exact (hl a).trans ((l.sublist_cons b).cons_cons a)
75+
#align list.destutter'_sublist List.destutter'_sublist
76+
77+
theorem mem_destutter' (a) : a ∈ l.destutter' R a :=
78+
by
79+
induction' l with b l hl
80+
· simp
81+
rw [destutter']
82+
split_ifs
83+
· simp
84+
· assumption
85+
#align list.mem_destutter' List.mem_destutter'
86+
87+
theorem destutter'_is_chain : ∀ l : List α, ∀ {a b}, R a b → (l.destutter' R b).Chain R a
88+
| [], a, b, h => chain_singleton.mpr h
89+
| c :: l, a, b, h => by
90+
rw [destutter']
91+
split_ifs with hbc
92+
· rw [chain_cons]
93+
exact ⟨h, destutter'_is_chain l hbc⟩
94+
· exact destutter'_is_chain l h
95+
#align list.destutter'_is_chain List.destutter'_is_chain
96+
97+
theorem destutter'_is_chain' (a) : (l.destutter' R a).Chain' R :=
98+
by
99+
induction' l with b l hl generalizing a
100+
· simp
101+
rw [destutter']
102+
split_ifs with h
103+
· exact destutter'_is_chain R l h
104+
· exact hl a
105+
#align list.destutter'_is_chain' List.destutter'_is_chain'
106+
107+
theorem destutter'_of_chain (h : l.Chain R a) : l.destutter' R a = a :: l :=
108+
by
109+
induction' l with b l hb generalizing a
110+
· simp
111+
obtain ⟨h, hc⟩ := chain_cons.mp h
112+
rw [l.destutter'_cons_pos h, hb hc]
113+
#align list.destutter'_of_chain List.destutter'_of_chain
114+
115+
@[simp]
116+
theorem destutter'_eq_self_iff (a) : l.destutter' R a = a :: l ↔ l.Chain R a :=
117+
fun h => by
118+
suffices Chain' R (a::l) by
119+
assumption
120+
rw [← h]
121+
exact l.destutter'_is_chain' R a, destutter'_of_chain _ _⟩
122+
#align list.destutter'_eq_self_iff List.destutter'_eq_self_iff
123+
124+
theorem destutter'_ne_nil : l.destutter' R a ≠ [] :=
125+
ne_nil_of_mem <| l.mem_destutter' R a
126+
#align list.destutter'_ne_nil List.destutter'_ne_nil
127+
128+
@[simp]
129+
theorem destutter_nil : ([] : List α).destutter R = [] :=
130+
rfl
131+
#align list.destutter_nil List.destutter_nil
132+
133+
theorem destutter_cons' : (a :: l).destutter R = destutter' R a l :=
134+
rfl
135+
#align list.destutter_cons' List.destutter_cons'
136+
137+
theorem destutter_cons_cons :
138+
(a :: b :: l).destutter R = if R a b then a :: destutter' R b l else destutter' R a l :=
139+
rfl
140+
#align list.destutter_cons_cons List.destutter_cons_cons
141+
142+
@[simp]
143+
theorem destutter_singleton : destutter R [a] = [a] :=
144+
rfl
145+
#align list.destutter_singleton List.destutter_singleton
146+
147+
@[simp]
148+
theorem destutter_pair : destutter R [a, b] = if R a b then [a, b] else [a] :=
149+
destutter_cons_cons _ R
150+
#align list.destutter_pair List.destutter_pair
151+
152+
theorem destutter_sublist : ∀ l : List α, l.destutter R <+ l
153+
| [] => Sublist.slnil
154+
| h :: l => l.destutter'_sublist R h
155+
#align list.destutter_sublist List.destutter_sublist
156+
157+
theorem destutter_is_chain' : ∀ l : List α, (l.destutter R).Chain' R
158+
| [] => List.chain'_nil
159+
| h :: l => l.destutter'_is_chain' R h
160+
#align list.destutter_is_chain' List.destutter_is_chain'
161+
162+
theorem destutter_of_chain' : ∀ l : List α, l.Chain' R → l.destutter R = l
163+
| [], _ => rfl
164+
| _ :: l, h => l.destutter'_of_chain _ h
165+
#align list.destutter_of_chain' List.destutter_of_chain'
166+
167+
@[simp]
168+
theorem destutter_eq_self_iff : ∀ l : List α, l.destutter R = l ↔ l.Chain' R
169+
| [] => by simp
170+
| a :: l => l.destutter'_eq_self_iff R a
171+
#align list.destutter_eq_self_iff List.destutter_eq_self_iff
172+
173+
theorem destutter_idem : (l.destutter R).destutter R = l.destutter R :=
174+
destutter_of_chain' R _ <| l.destutter_is_chain' R
175+
#align list.destutter_idem List.destutter_idem
176+
177+
@[simp]
178+
theorem destutter_eq_nil : ∀ {l : List α}, destutter R l = [] ↔ l = []
179+
| [] => Iff.rfl
180+
| _ :: l => ⟨fun h => absurd h <| l.destutter'_ne_nil R, fun h => nomatch h⟩
181+
#align list.destutter_eq_nil List.destutter_eq_nil
182+
183+
end List

0 commit comments

Comments
 (0)