@@ -8,39 +8,50 @@ import Mathlib.Order.Basic
8
8
import Mathlib.Data.Nat.Basic
9
9
import Mathlib.Data.Option.Basic
10
10
11
- /-! ### List.scanl and List.scanr -/
11
+ /-!
12
+ # List scan
13
+
14
+ Prove basic results about `List.scanl` and `List.scanr`.
15
+ -/
12
16
13
17
open Nat
14
18
15
19
namespace List
16
20
17
21
variable {α β : Type *} {f : β → α → β} {b : β} {a : α} {l : List α}
18
22
19
- theorem length_scanl : ∀ a l, length ( scanl f a l) = l.length + 1
20
- | _, [] => rfl
21
- | a, x :: l => by
22
- rw [ scanl, length_cons, length_cons, ← succ_eq_add_one, congr_arg succ]
23
- exact length_scanl _ _
23
+ /-! ### List. scanl -/
24
+
25
+ @[simp]
26
+ theorem length_scanl (b : β) (l : List α) : length ( scanl f b l) = l.length + 1 := by
27
+ induction l generalizing b <;> simp_all
24
28
25
29
@[simp]
26
- theorem scanl_nil (b : β) : scanl f b nil = [b] :=
30
+ theorem scanl_nil (b : β) : scanl f b [] = [b] :=
27
31
rfl
28
32
33
+ @[simp]
34
+ theorem scanl_ne_nil : scanl f b l ≠ [] := by
35
+ cases l <;> simp
36
+
37
+ @[simp]
38
+ theorem scanl_iff_nil (c : β) : scanl f b l = [c] ↔ c = b ∧ l = [] := by
39
+ constructor <;> cases l <;> simp_all
40
+
29
41
@[simp]
30
42
theorem scanl_cons : scanl f b (a :: l) = [b] ++ scanl f (f b a) l := by
31
43
simp only [scanl, singleton_append]
32
44
33
- @[simp]
34
45
theorem getElem?_scanl_zero : (scanl f b l)[0 ]? = some b := by
35
- cases l
36
- · simp
37
- · simp
46
+ cases l <;> simp
47
+
48
+ @[simp]
49
+ theorem getElem_scanl_zero : (scanl f b l)[0 ] = b := by
50
+ cases l <;> simp
38
51
39
52
@[simp]
40
- theorem getElem_scanl_zero {h : 0 < (scanl f b l).length} : (scanl f b l)[0 ] = b := by
41
- cases l
42
- · simp
43
- · simp
53
+ theorem head_scanl (h : scanl f b l ≠ []) : (scanl f b l).head h = b := by
54
+ cases l <;> simp
44
55
45
56
theorem getElem?_succ_scanl {i : ℕ} : (scanl f b l)[i + 1 ]? =
46
57
(scanl f b l)[i]?.bind fun x => l[i]?.map fun y => f x y := by
@@ -74,17 +85,74 @@ theorem getElem_succ_scanl {i : ℕ} (h : i + 1 < (scanl f b l).length) :
74
85
· simp only [length, Nat.zero_add 1 , succ_add_sub_one, hi]; rfl
75
86
· simp only [length_singleton]; omega
76
87
77
- -- scanr
88
+ /-! ### List.scanr -/
89
+
90
+ variable {f : α → β → β}
91
+
78
92
@[simp]
79
- theorem scanr_nil (f : α → β → β) ( b : β) : scanr f b [] = [b] :=
93
+ theorem scanr_nil (b : β) : scanr f b [] = [b] :=
80
94
rfl
81
95
82
96
@[simp]
83
- theorem scanr_cons (f : α → β → β) (b : β) (a : α) (l : List α) :
84
- scanr f b (a :: l) = foldr f b (a :: l) :: scanr f b l := by
97
+ theorem scanr_ne_nil : scanr f b l ≠ [] := by
98
+ simp [scanr]
99
+
100
+ @[simp]
101
+ theorem scanr_cons : scanr f b (a :: l) = foldr f b (a :: l) :: scanr f b l := by
85
102
simp only [scanr, foldr, cons.injEq, and_true]
86
103
induction l generalizing a with
87
104
| nil => rfl
88
105
| cons hd tl ih => simp only [foldr, ih]
89
106
107
+ @[simp]
108
+ theorem scanr_iff_nil (c : β) : scanr f b l = [c] ↔ c = b ∧ l = [] := by
109
+ constructor <;> cases l <;> simp_all
110
+
111
+ @[simp]
112
+ theorem length_scanr (b : β) (l : List α) : length (scanr f b l) = l.length + 1 := by
113
+ induction l <;> simp_all
114
+
115
+ theorem scanr_append (l₁ l₂ : List α) :
116
+ scanr f b (l₁ ++ l₂) = (scanr f (foldr f b l₂) l₁) ++ (scanr f b l₂).tail := by
117
+ induction l₁ <;> induction l₂ <;> simp [*]
118
+
119
+ @[simp]
120
+ theorem head_scanr (h : scanr f b l ≠ []) : (scanr f b l).head h = foldr f b l := by
121
+ cases l <;> simp
122
+
123
+ theorem tail_scanr (h : 0 < l.length) : (scanr f b l).tail = scanr f b l.tail := by
124
+ induction l <;> simp_all
125
+
126
+ theorem drop_scanr {i : ℕ} (h : i ≤ l.length) : (scanr f b l).drop i = scanr f b (l.drop i) := by
127
+ induction i with
128
+ | zero => simp
129
+ | succ i ih =>
130
+ rw [← drop_drop]
131
+ simp [ih (by omega), tail_scanr (l := l.drop i) (by rw [length_drop]; omega)]
132
+
133
+ @[simp]
134
+ theorem getElem_scanr_zero : (scanr f b l)[0 ] = foldr f b l := by
135
+ cases l <;> simp
136
+
137
+ theorem getElem?_scanr_zero : (scanr f b l)[0 ]? = foldr f b l := by
138
+ simp
139
+
140
+ theorem getElem_scanr {i : ℕ} (h : i < (scanr f b l).length) :
141
+ (scanr f b l)[i] = foldr f b (l.drop i) := by
142
+ induction l generalizing i with
143
+ | nil => simp
144
+ | cons head tail ih =>
145
+ obtain rfl | h' := eq_or_ne i 0
146
+ · simp
147
+ · obtain ⟨m, rfl⟩ := Nat.exists_eq_succ_of_ne_zero h'
148
+ simp [@ih m (by simp_all [length_scanr])]
149
+
150
+ theorem getElem?_scanr {i : ℕ} (h : i < l.length + 1 ) :
151
+ (scanr f b l)[i]? = if i < l.length + 1 then some (foldr f b (l.drop i)) else none := by
152
+ split <;> simp_all [getElem_scanr]
153
+
154
+ theorem getElem?_scanr_of_lt {i : ℕ} (h : i < l.length + 1 ) :
155
+ (scanr f b l)[i]? = some (foldr f b (l.drop i)) := by
156
+ simpa [getElem?_scanr h]
157
+
90
158
end List
0 commit comments