data.list.range
⟷
Mathlib.Data.List.Range
The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(last sync)
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -3,8 +3,8 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau, Scott Morrison
-/
-import Mathbin.Data.List.Chain
-import Mathbin.Data.List.Zip
+import Data.List.Chain
+import Data.List.Zip
#align_import data.list.range from "leanprover-community/mathlib"@"be24ec5de6701447e5df5ca75400ffee19d65659"
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -2,15 +2,12 @@
Copyright (c) 2018 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau, Scott Morrison
-
-! This file was ported from Lean 3 source module data.list.range
-! leanprover-community/mathlib commit be24ec5de6701447e5df5ca75400ffee19d65659
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathbin.Data.List.Chain
import Mathbin.Data.List.Zip
+#align_import data.list.range from "leanprover-community/mathlib"@"be24ec5de6701447e5df5ca75400ffee19d65659"
+
/-!
# Ranges of naturals as lists
mathlib commit https://github.com/leanprover-community/mathlib/commit/9fb8964792b4237dac6200193a0d533f1b3f7423
@@ -34,16 +34,21 @@ namespace List
variable {α : Type u}
+#print List.length_range' /-
@[simp]
theorem length_range' : ∀ s n : ℕ, length (range' s n) = n
| s, 0 => rfl
| s, n + 1 => congr_arg succ (length_range' _ _)
#align list.length_range' List.length_range'
+-/
+#print List.range'_eq_nil /-
@[simp]
theorem range'_eq_nil {s n : ℕ} : range' s n = [] ↔ n = 0 := by rw [← length_eq_zero, length_range']
#align list.range'_eq_nil List.range'_eq_nil
+-/
+#print List.mem_range'_1 /-
@[simp]
theorem mem_range'_1 {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧ m < s + n
| s, 0 => (false_iff_iff _).2 fun ⟨H1, H2⟩ => not_le_of_lt H2 H1
@@ -54,12 +59,16 @@ theorem mem_range'_1 {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m
(mem_cons _ _ _).trans <| by
simp only [mem_range', or_and_left, or_iff_right_of_imp this, l, add_right_comm] <;> rfl
#align list.mem_range' List.mem_range'_1
+-/
+#print List.map_add_range' /-
theorem map_add_range' (a) : ∀ s n : ℕ, map ((· + ·) a) (range' s n) = range' (a + s) n
| s, 0 => rfl
| s, n + 1 => congr_arg (cons _) (map_add_range' (s + 1) n)
#align list.map_add_range' List.map_add_range'
+-/
+#print List.map_sub_range' /-
theorem map_sub_range' (a) :
∀ (s n : ℕ) (h : a ≤ s), map (fun x => x - a) (range' s n) = range' (s - a) n
| s, 0, _ => rfl
@@ -69,25 +78,35 @@ theorem map_sub_range' (a) :
rw [Nat.succ_sub h]
rfl
#align list.map_sub_range' List.map_sub_range'
+-/
+#print List.chain_succ_range' /-
theorem chain_succ_range' : ∀ s n : ℕ, Chain (fun a b => b = succ a) s (range' (s + 1) n)
| s, 0 => Chain.nil
| s, n + 1 => (chain_succ_range' (s + 1) n).cons rfl
#align list.chain_succ_range' List.chain_succ_range'
+-/
+#print List.chain_lt_range' /-
theorem chain_lt_range' (s n : ℕ) : Chain (· < ·) s (range' (s + 1) n) :=
(chain_succ_range' s n).imp fun a b e => e.symm ▸ lt_succ_self _
#align list.chain_lt_range' List.chain_lt_range'
+-/
+#print List.pairwise_lt_range' /-
theorem pairwise_lt_range' : ∀ s n : ℕ, Pairwise (· < ·) (range' s n)
| s, 0 => Pairwise.nil
| s, n + 1 => chain_iff_pairwise.1 (chain_lt_range' s n)
#align list.pairwise_lt_range' List.pairwise_lt_range'
+-/
+#print List.nodup_range' /-
theorem nodup_range' (s n : ℕ) : Nodup (range' s n) :=
(pairwise_lt_range' s n).imp fun a b => ne_of_lt
#align list.nodup_range' List.nodup_range'
+-/
+#print List.range'_append /-
@[simp]
theorem range'_append : ∀ s m n : ℕ, range' s m ++ range' (s + m) n = range' s (n + m)
| s, 0, n => rfl
@@ -95,12 +114,16 @@ theorem range'_append : ∀ s m n : ℕ, range' s m ++ range' (s + m) n = range'
show s :: (range' (s + 1) m ++ range' (s + m + 1) n) = s :: range' (s + 1) (n + m) by
rw [add_right_comm, range'_append]
#align list.range'_append List.range'_append
+-/
+#print List.range'_sublist_right /-
theorem range'_sublist_right {s m n : ℕ} : range' s m <+ range' s n ↔ m ≤ n :=
⟨fun h => by simpa only [length_range'] using h.length_le, fun h => by
rw [← tsub_add_cancel_of_le h, ← range'_append] <;> apply sublist_append_left⟩
#align list.range'_sublist_right List.range'_sublist_right
+-/
+#print List.range'_subset_right /-
theorem range'_subset_right {s m n : ℕ} : range' s m ⊆ range' s n ↔ m ≤ n :=
⟨fun h =>
le_of_not_lt fun hn =>
@@ -108,32 +131,43 @@ theorem range'_subset_right {s m n : ℕ} : range' s m ⊆ range' s n ↔ m ≤
(mem_range'_1.1 <| h <| mem_range'_1.2 ⟨Nat.le_add_right _ _, Nat.add_lt_add_left hn s⟩).2,
fun h => (range'_sublist_right.2 h).Subset⟩
#align list.range'_subset_right List.range'_subset_right
+-/
+#print List.get?_range' /-
theorem get?_range' : ∀ (s) {m n : ℕ}, m < n → get? (range' s n) m = some (s + m)
| s, 0, n + 1, _ => rfl
| s, m + 1, n + 1, h =>
(nth_range' (s + 1) (lt_of_add_lt_add_right h)).trans <| by rw [add_right_comm] <;> rfl
#align list.nth_range' List.get?_range'
+-/
+#print List.nthLe_range'_1 /-
@[simp]
theorem nthLe_range'_1 {n m} (i) (H : i < (range' n m).length) : nthLe (range' n m) i H = n + i :=
Option.some.inj <| by rw [← nth_le_nth _, nth_range' _ (by simpa using H)]
#align list.nth_le_range' List.nthLe_range'_1
+-/
+#print List.range'_concat /-
theorem range'_concat (s n : ℕ) : range' s (n + 1) = range' s n ++ [s + n] := by
rw [add_comm n 1] <;> exact (range'_append s n 1).symm
#align list.range'_concat List.range'_concat
+-/
+#print List.range_loop_range' /-
theorem range_loop_range' : ∀ s n : ℕ, List.range.loop s (range' s n) = range' 0 (n + s)
| 0, n => rfl
| s + 1, n => by
rw [show n + (s + 1) = n + 1 + s from add_right_comm n s 1] <;>
exact range_core_range' s (n + 1)
#align list.range_core_range' List.range_loop_range'
+-/
+#print List.range_eq_range' /-
theorem range_eq_range' (n : ℕ) : range n = range' 0 n :=
(range_loop_range' n 0).trans <| by rw [zero_add]
#align list.range_eq_range' List.range_eq_range'
+-/
#print List.range_succ_eq_map /-
theorem range_succ_eq_map (n : ℕ) : range (n + 1) = 0 :: map succ (range n) := by
@@ -142,9 +176,11 @@ theorem range_succ_eq_map (n : ℕ) : range (n + 1) = 0 :: map succ (range n) :=
#align list.range_succ_eq_map List.range_succ_eq_map
-/
+#print List.range'_eq_map_range /-
theorem range'_eq_map_range (s n : ℕ) : range' s n = map ((· + ·) s) (range n) := by
rw [range_eq_range', map_add_range'] <;> rfl
#align list.range'_eq_map_range List.range'_eq_map_range
+-/
#print List.length_range /-
@[simp]
@@ -258,11 +294,13 @@ theorem range_add (a : ℕ) : ∀ b, range (a + b) = range a ++ (range b).map fu
#align list.range_add List.range_add
-/
+#print List.iota_eq_reverse_range' /-
theorem iota_eq_reverse_range' : ∀ n : ℕ, iota n = reverse (range' 1 n)
| 0 => rfl
| n + 1 => by
simp only [iota, range'_concat, iota_eq_reverse_range' n, reverse_append, add_comm] <;> rfl
#align list.iota_eq_reverse_range' List.iota_eq_reverse_range'
+-/
#print List.length_iota /-
@[simp]
@@ -289,6 +327,7 @@ theorem mem_iota {m n : ℕ} : m ∈ iota n ↔ 1 ≤ m ∧ m ≤ n := by
#align list.mem_iota List.mem_iota
-/
+#print List.reverse_range' /-
theorem reverse_range' : ∀ s n : ℕ, reverse (range' s n) = map (fun i => s + n - 1 - i) (range n)
| s, 0 => rfl
| s, n + 1 => by
@@ -297,6 +336,7 @@ theorem reverse_range' : ∀ s n : ℕ, reverse (range' s n) = map (fun i => s +
show a - 1 - i = a - succ i from pred_sub _ _, reverse_singleton, map_cons, tsub_zero,
cons_append, nil_append, eq_self_iff_true, true_and_iff, map_map] using reverse_range' s n
#align list.reverse_range' List.reverse_range'
+-/
#print List.finRange /-
/-- All elements of `fin n`, from `0` to `n-1`. The corresponding finset is `finset.univ`. -/
@@ -339,13 +379,16 @@ theorem finRange_eq_nil {n : ℕ} : finRange n = [] ↔ n = 0 := by
#align list.fin_range_eq_nil List.finRange_eq_nil
-/
+#print List.prod_range_succ /-
@[to_additive]
theorem prod_range_succ {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
((range n.succ).map f).Prod = ((range n).map f).Prod * f n := by
rw [range_succ, map_append, map_singleton, prod_append, prod_cons, prod_nil, mul_one]
#align list.prod_range_succ List.prod_range_succ
#align list.sum_range_succ List.sum_range_succ
+-/
+#print List.prod_range_succ' /-
/-- A variant of `prod_range_succ` which pulls off the first
term in the product rather than the last.-/
@[to_additive
@@ -356,12 +399,15 @@ theorem prod_range_succ' {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
rw [List.prod_range_succ, hd, mul_assoc, ← List.prod_range_succ]
#align list.prod_range_succ' List.prod_range_succ'
#align list.sum_range_succ' List.sum_range_succ'
+-/
+#print List.enumFrom_map_fst /-
@[simp]
theorem enumFrom_map_fst : ∀ (n) (l : List α), map Prod.fst (enumFrom n l) = range' n l.length
| n, [] => rfl
| n, a :: l => congr_arg (cons _) (enum_from_map_fst _ _)
#align list.enum_from_map_fst List.enumFrom_map_fst
+-/
#print List.enum_map_fst /-
@[simp]
@@ -383,15 +429,19 @@ theorem unzip_enum_eq_prod (l : List α) : l.enum.unzip = (range l.length, l) :=
#align list.unzip_enum_eq_prod List.unzip_enum_eq_prod
-/
+#print List.enumFrom_eq_zip_range' /-
theorem enumFrom_eq_zip_range' (l : List α) {n : ℕ} : l.enumFrom n = (range' n l.length).zip l :=
zip_of_prod (enumFrom_map_fst _ _) (enumFrom_map_snd _ _)
#align list.enum_from_eq_zip_range' List.enumFrom_eq_zip_range'
+-/
+#print List.unzip_enumFrom_eq_prod /-
@[simp]
theorem unzip_enumFrom_eq_prod (l : List α) {n : ℕ} :
(l.enumFrom n).unzip = (range' n l.length, l) := by
simp only [enum_from_eq_zip_range', unzip_zip, length_range']
#align list.unzip_enum_from_eq_prod List.unzip_enumFrom_eq_prod
+-/
#print List.nthLe_range /-
@[simp]
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
@@ -45,7 +45,7 @@ theorem range'_eq_nil {s n : ℕ} : range' s n = [] ↔ n = 0 := by rw [← leng
#align list.range'_eq_nil List.range'_eq_nil
@[simp]
-theorem mem_range' {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧ m < s + n
+theorem mem_range'_1 {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧ m < s + n
| s, 0 => (false_iff_iff _).2 fun ⟨H1, H2⟩ => not_le_of_lt H2 H1
| s, succ n =>
have : m = s → m < s + n + 1 := fun e => e ▸ lt_succ_of_le (Nat.le_add_right _ _)
@@ -53,7 +53,7 @@ theorem mem_range' {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧
simpa only [eq_comm] using (@Decidable.le_iff_eq_or_lt _ _ _ s m).symm
(mem_cons _ _ _).trans <| by
simp only [mem_range', or_and_left, or_iff_right_of_imp this, l, add_right_comm] <;> rfl
-#align list.mem_range' List.mem_range'
+#align list.mem_range' List.mem_range'_1
theorem map_add_range' (a) : ∀ s n : ℕ, map ((· + ·) a) (range' s n) = range' (a + s) n
| s, 0 => rfl
@@ -105,7 +105,7 @@ theorem range'_subset_right {s m n : ℕ} : range' s m ⊆ range' s n ↔ m ≤
⟨fun h =>
le_of_not_lt fun hn =>
lt_irrefl (s + n) <|
- (mem_range'.1 <| h <| mem_range'.2 ⟨Nat.le_add_right _ _, Nat.add_lt_add_left hn s⟩).2,
+ (mem_range'_1.1 <| h <| mem_range'_1.2 ⟨Nat.le_add_right _ _, Nat.add_lt_add_left hn s⟩).2,
fun h => (range'_sublist_right.2 h).Subset⟩
#align list.range'_subset_right List.range'_subset_right
@@ -116,9 +116,9 @@ theorem get?_range' : ∀ (s) {m n : ℕ}, m < n → get? (range' s n) m = some
#align list.nth_range' List.get?_range'
@[simp]
-theorem nthLe_range' {n m} (i) (H : i < (range' n m).length) : nthLe (range' n m) i H = n + i :=
+theorem nthLe_range'_1 {n m} (i) (H : i < (range' n m).length) : nthLe (range' n m) i H = n + i :=
Option.some.inj <| by rw [← nth_le_nth _, nth_range' _ (by simpa using H)]
-#align list.nth_le_range' List.nthLe_range'
+#align list.nth_le_range' List.nthLe_range'_1
theorem range'_concat (s n : ℕ) : range' s (n + 1) = range' s n ++ [s + n] := by
rw [add_comm n 1] <;> exact (range'_append s n 1).symm
@@ -358,10 +358,10 @@ theorem prod_range_succ' {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
#align list.sum_range_succ' List.sum_range_succ'
@[simp]
-theorem enum_from_map_fst : ∀ (n) (l : List α), map Prod.fst (enumFrom n l) = range' n l.length
+theorem enumFrom_map_fst : ∀ (n) (l : List α), map Prod.fst (enumFrom n l) = range' n l.length
| n, [] => rfl
| n, a :: l => congr_arg (cons _) (enum_from_map_fst _ _)
-#align list.enum_from_map_fst List.enum_from_map_fst
+#align list.enum_from_map_fst List.enumFrom_map_fst
#print List.enum_map_fst /-
@[simp]
@@ -383,15 +383,15 @@ theorem unzip_enum_eq_prod (l : List α) : l.enum.unzip = (range l.length, l) :=
#align list.unzip_enum_eq_prod List.unzip_enum_eq_prod
-/
-theorem enum_from_eq_zip_range' (l : List α) {n : ℕ} : l.enumFrom n = (range' n l.length).zip l :=
- zip_of_prod (enum_from_map_fst _ _) (enumFrom_map_snd _ _)
-#align list.enum_from_eq_zip_range' List.enum_from_eq_zip_range'
+theorem enumFrom_eq_zip_range' (l : List α) {n : ℕ} : l.enumFrom n = (range' n l.length).zip l :=
+ zip_of_prod (enumFrom_map_fst _ _) (enumFrom_map_snd _ _)
+#align list.enum_from_eq_zip_range' List.enumFrom_eq_zip_range'
@[simp]
-theorem unzip_enum_from_eq_prod (l : List α) {n : ℕ} :
+theorem unzip_enumFrom_eq_prod (l : List α) {n : ℕ} :
(l.enumFrom n).unzip = (range' n l.length, l) := by
simp only [enum_from_eq_zip_range', unzip_zip, length_range']
-#align list.unzip_enum_from_eq_prod List.unzip_enum_from_eq_prod
+#align list.unzip_enum_from_eq_prod List.unzip_enumFrom_eq_prod
#print List.nthLe_range /-
@[simp]
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -34,34 +34,16 @@ namespace List
variable {α : Type u}
-/- warning: list.length_range' -> List.length_range' is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) (n : Nat), Eq.{1} Nat (List.length.{0} Nat (List.range' s n)) n
-but is expected to have type
- forall (s : Nat) (n : Nat), Eq.{1} Nat (List.length.{0} Nat (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) n
-Case conversion may be inaccurate. Consider using '#align list.length_range' List.length_range'ₓ'. -/
@[simp]
theorem length_range' : ∀ s n : ℕ, length (range' s n) = n
| s, 0 => rfl
| s, n + 1 => congr_arg succ (length_range' _ _)
#align list.length_range' List.length_range'
-/- warning: list.range'_eq_nil -> List.range'_eq_nil is a dubious translation:
-lean 3 declaration is
- forall {s : Nat} {n : Nat}, Iff (Eq.{1} (List.{0} Nat) (List.range' s n) (List.nil.{0} Nat)) (Eq.{1} Nat n (OfNat.ofNat.{0} Nat 0 (OfNat.mk.{0} Nat 0 (Zero.zero.{0} Nat Nat.hasZero))))
-but is expected to have type
- forall {s : Nat} {n : Nat}, Iff (Eq.{1} (List.{0} Nat) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.nil.{0} Nat)) (Eq.{1} Nat n (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0)))
-Case conversion may be inaccurate. Consider using '#align list.range'_eq_nil List.range'_eq_nilₓ'. -/
@[simp]
theorem range'_eq_nil {s n : ℕ} : range' s n = [] ↔ n = 0 := by rw [← length_eq_zero, length_range']
#align list.range'_eq_nil List.range'_eq_nil
-/- warning: list.mem_range' -> List.mem_range' is a dubious translation:
-lean 3 declaration is
- forall {m : Nat} {s : Nat} {n : Nat}, Iff (Membership.Mem.{0, 0} Nat (List.{0} Nat) (List.hasMem.{0} Nat) m (List.range' s n)) (And (LE.le.{0} Nat Nat.hasLe s m) (LT.lt.{0} Nat Nat.hasLt m (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s n)))
-but is expected to have type
- forall {m : Nat} {s : Nat} {n : Nat}, Iff (Membership.mem.{0, 0} Nat (List.{0} Nat) (List.instMembershipList.{0} Nat) m (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (And (LE.le.{0} Nat instLENat s m) (LT.lt.{0} Nat instLTNat m (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s n)))
-Case conversion may be inaccurate. Consider using '#align list.mem_range' List.mem_range'ₓ'. -/
@[simp]
theorem mem_range' {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧ m < s + n
| s, 0 => (false_iff_iff _).2 fun ⟨H1, H2⟩ => not_le_of_lt H2 H1
@@ -73,23 +55,11 @@ theorem mem_range' {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧
simp only [mem_range', or_and_left, or_iff_right_of_imp this, l, add_right_comm] <;> rfl
#align list.mem_range' List.mem_range'
-/- warning: list.map_add_range' -> List.map_add_range' is a dubious translation:
-lean 3 declaration is
- forall (a : Nat) (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.map.{0, 0} Nat Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) a) (List.range' s n)) (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) a s) n)
-but is expected to have type
- forall (a : Nat) (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.map.{0, 0} Nat Nat ((fun (x._@.Mathlib.Data.List.Range._hyg.391 : Nat) (x._@.Mathlib.Data.List.Range._hyg.393 : Nat) => HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) x._@.Mathlib.Data.List.Range._hyg.391 x._@.Mathlib.Data.List.Range._hyg.393) a) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) a s) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
-Case conversion may be inaccurate. Consider using '#align list.map_add_range' List.map_add_range'ₓ'. -/
theorem map_add_range' (a) : ∀ s n : ℕ, map ((· + ·) a) (range' s n) = range' (a + s) n
| s, 0 => rfl
| s, n + 1 => congr_arg (cons _) (map_add_range' (s + 1) n)
#align list.map_add_range' List.map_add_range'
-/- warning: list.map_sub_range' -> List.map_sub_range' is a dubious translation:
-lean 3 declaration is
- forall (a : Nat) (s : Nat) (n : Nat), (LE.le.{0} Nat Nat.hasLe a s) -> (Eq.{1} (List.{0} Nat) (List.map.{0, 0} Nat Nat (fun (x : Nat) => HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat Nat.hasSub) x a) (List.range' s n)) (List.range' (HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat Nat.hasSub) s a) n))
-but is expected to have type
- forall (a : Nat) (s : Nat) (n : Nat), (LE.le.{0} Nat instLENat a s) -> (Eq.{1} (List.{0} Nat) (List.map.{0, 0} Nat Nat (fun (x : Nat) => HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat instSubNat) x a) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (List.range' (HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat instSubNat) s a) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))))
-Case conversion may be inaccurate. Consider using '#align list.map_sub_range' List.map_sub_range'ₓ'. -/
theorem map_sub_range' (a) :
∀ (s n : ℕ) (h : a ≤ s), map (fun x => x - a) (range' s n) = range' (s - a) n
| s, 0, _ => rfl
@@ -100,54 +70,24 @@ theorem map_sub_range' (a) :
rfl
#align list.map_sub_range' List.map_sub_range'
-/- warning: list.chain_succ_range' -> List.chain_succ_range' is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) (n : Nat), List.Chain.{0} Nat (fun (a : Nat) (b : Nat) => Eq.{1} Nat b (Nat.succ a)) s (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne)))) n)
-but is expected to have type
- forall (s : Nat) (n : Nat), List.Chain.{0} Nat (fun (a : Nat) (b : Nat) => Eq.{1} Nat b (Nat.succ a)) s (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
-Case conversion may be inaccurate. Consider using '#align list.chain_succ_range' List.chain_succ_range'ₓ'. -/
theorem chain_succ_range' : ∀ s n : ℕ, Chain (fun a b => b = succ a) s (range' (s + 1) n)
| s, 0 => Chain.nil
| s, n + 1 => (chain_succ_range' (s + 1) n).cons rfl
#align list.chain_succ_range' List.chain_succ_range'
-/- warning: list.chain_lt_range' -> List.chain_lt_range' is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) (n : Nat), List.Chain.{0} Nat (LT.lt.{0} Nat Nat.hasLt) s (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne)))) n)
-but is expected to have type
- forall (s : Nat) (n : Nat), List.Chain.{0} Nat (fun (x._@.Mathlib.Data.List.Range._hyg.791 : Nat) (x._@.Mathlib.Data.List.Range._hyg.793 : Nat) => LT.lt.{0} Nat instLTNat x._@.Mathlib.Data.List.Range._hyg.791 x._@.Mathlib.Data.List.Range._hyg.793) s (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
-Case conversion may be inaccurate. Consider using '#align list.chain_lt_range' List.chain_lt_range'ₓ'. -/
theorem chain_lt_range' (s n : ℕ) : Chain (· < ·) s (range' (s + 1) n) :=
(chain_succ_range' s n).imp fun a b e => e.symm ▸ lt_succ_self _
#align list.chain_lt_range' List.chain_lt_range'
-/- warning: list.pairwise_lt_range' -> List.pairwise_lt_range' is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) (n : Nat), List.Pairwise.{0} Nat (LT.lt.{0} Nat Nat.hasLt) (List.range' s n)
-but is expected to have type
- forall (s : Nat) (n : Nat), List.Pairwise.{0} Nat (fun (x._@.Mathlib.Data.List.Range._hyg.852 : Nat) (x._@.Mathlib.Data.List.Range._hyg.854 : Nat) => LT.lt.{0} Nat instLTNat x._@.Mathlib.Data.List.Range._hyg.852 x._@.Mathlib.Data.List.Range._hyg.854) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
-Case conversion may be inaccurate. Consider using '#align list.pairwise_lt_range' List.pairwise_lt_range'ₓ'. -/
theorem pairwise_lt_range' : ∀ s n : ℕ, Pairwise (· < ·) (range' s n)
| s, 0 => Pairwise.nil
| s, n + 1 => chain_iff_pairwise.1 (chain_lt_range' s n)
#align list.pairwise_lt_range' List.pairwise_lt_range'
-/- warning: list.nodup_range' -> List.nodup_range' is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) (n : Nat), List.Nodup.{0} Nat (List.range' s n)
-but is expected to have type
- forall (s : Nat) (n : Nat), List.Nodup.{0} Nat (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
-Case conversion may be inaccurate. Consider using '#align list.nodup_range' List.nodup_range'ₓ'. -/
theorem nodup_range' (s n : ℕ) : Nodup (range' s n) :=
(pairwise_lt_range' s n).imp fun a b => ne_of_lt
#align list.nodup_range' List.nodup_range'
-/- warning: list.range'_append -> List.range'_append is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) (m : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (Append.append.{0} (List.{0} Nat) (List.hasAppend.{0} Nat) (List.range' s m) (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s m) n)) (List.range' s (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n m))
-but is expected to have type
- forall (s : Nat) (m : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (HAppend.hAppend.{0, 0, 0} (List.{0} Nat) (List.{0} Nat) (List.{0} Nat) (instHAppend.{0} (List.{0} Nat) (List.instAppendList.{0} Nat)) (List.range' s m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s m) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (List.range' s (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n m) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
-Case conversion may be inaccurate. Consider using '#align list.range'_append List.range'_appendₓ'. -/
@[simp]
theorem range'_append : ∀ s m n : ℕ, range' s m ++ range' (s + m) n = range' s (n + m)
| s, 0, n => rfl
@@ -156,23 +96,11 @@ theorem range'_append : ∀ s m n : ℕ, range' s m ++ range' (s + m) n = range'
rw [add_right_comm, range'_append]
#align list.range'_append List.range'_append
-/- warning: list.range'_sublist_right -> List.range'_sublist_right is a dubious translation:
-lean 3 declaration is
- forall {s : Nat} {m : Nat} {n : Nat}, Iff (List.Sublist.{0} Nat (List.range' s m) (List.range' s n)) (LE.le.{0} Nat Nat.hasLe m n)
-but is expected to have type
- forall {s : Nat} {m : Nat} {n : Nat}, Iff (List.Sublist.{0} Nat (List.range' s m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (LE.le.{0} Nat instLENat m n)
-Case conversion may be inaccurate. Consider using '#align list.range'_sublist_right List.range'_sublist_rightₓ'. -/
theorem range'_sublist_right {s m n : ℕ} : range' s m <+ range' s n ↔ m ≤ n :=
⟨fun h => by simpa only [length_range'] using h.length_le, fun h => by
rw [← tsub_add_cancel_of_le h, ← range'_append] <;> apply sublist_append_left⟩
#align list.range'_sublist_right List.range'_sublist_right
-/- warning: list.range'_subset_right -> List.range'_subset_right is a dubious translation:
-lean 3 declaration is
- forall {s : Nat} {m : Nat} {n : Nat}, Iff (HasSubset.Subset.{0} (List.{0} Nat) (List.hasSubset.{0} Nat) (List.range' s m) (List.range' s n)) (LE.le.{0} Nat Nat.hasLe m n)
-but is expected to have type
- forall {s : Nat} {m : Nat} {n : Nat}, Iff (HasSubset.Subset.{0} (List.{0} Nat) (List.instHasSubsetList.{0} Nat) (List.range' s m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (LE.le.{0} Nat instLENat m n)
-Case conversion may be inaccurate. Consider using '#align list.range'_subset_right List.range'_subset_rightₓ'. -/
theorem range'_subset_right {s m n : ℕ} : range' s m ⊆ range' s n ↔ m ≤ n :=
⟨fun h =>
le_of_not_lt fun hn =>
@@ -181,45 +109,21 @@ theorem range'_subset_right {s m n : ℕ} : range' s m ⊆ range' s n ↔ m ≤
fun h => (range'_sublist_right.2 h).Subset⟩
#align list.range'_subset_right List.range'_subset_right
-/- warning: list.nth_range' -> List.get?_range' is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) {m : Nat} {n : Nat}, (LT.lt.{0} Nat Nat.hasLt m n) -> (Eq.{1} (Option.{0} Nat) (List.get?.{0} Nat (List.range' s n) m) (Option.some.{0} Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s m)))
-but is expected to have type
- forall (s : Nat) {m : Nat} {n : Nat}, (LT.lt.{0} Nat instLTNat m n) -> (Eq.{1} (Option.{0} Nat) (List.get?.{0} Nat (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) m) (Option.some.{0} Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s m)))
-Case conversion may be inaccurate. Consider using '#align list.nth_range' List.get?_range'ₓ'. -/
theorem get?_range' : ∀ (s) {m n : ℕ}, m < n → get? (range' s n) m = some (s + m)
| s, 0, n + 1, _ => rfl
| s, m + 1, n + 1, h =>
(nth_range' (s + 1) (lt_of_add_lt_add_right h)).trans <| by rw [add_right_comm] <;> rfl
#align list.nth_range' List.get?_range'
-/- warning: list.nth_le_range' -> List.nthLe_range' is a dubious translation:
-lean 3 declaration is
- forall {n : Nat} {m : Nat} (i : Nat) (H : LT.lt.{0} Nat Nat.hasLt i (List.length.{0} Nat (List.range' n m))), Eq.{1} Nat (List.nthLe.{0} Nat (List.range' n m) i H) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n i)
-but is expected to have type
- forall {n : Nat} {m : Nat} (i : Nat) (H : LT.lt.{0} Nat instLTNat i (List.length.{0} Nat (List.range' n m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))))), Eq.{1} Nat (List.nthLe.{0} Nat (List.range' n m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) i H) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n i)
-Case conversion may be inaccurate. Consider using '#align list.nth_le_range' List.nthLe_range'ₓ'. -/
@[simp]
theorem nthLe_range' {n m} (i) (H : i < (range' n m).length) : nthLe (range' n m) i H = n + i :=
Option.some.inj <| by rw [← nth_le_nth _, nth_range' _ (by simpa using H)]
#align list.nth_le_range' List.nthLe_range'
-/- warning: list.range'_concat -> List.range'_concat is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range' s (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne))))) (Append.append.{0} (List.{0} Nat) (List.hasAppend.{0} Nat) (List.range' s n) (List.cons.{0} Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s n) (List.nil.{0} Nat)))
-but is expected to have type
- forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range' s (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (HAppend.hAppend.{0, 0, 0} (List.{0} Nat) (List.{0} Nat) (List.{0} Nat) (instHAppend.{0} (List.{0} Nat) (List.instAppendList.{0} Nat)) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.cons.{0} Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s n) (List.nil.{0} Nat)))
-Case conversion may be inaccurate. Consider using '#align list.range'_concat List.range'_concatₓ'. -/
theorem range'_concat (s n : ℕ) : range' s (n + 1) = range' s n ++ [s + n] := by
rw [add_comm n 1] <;> exact (range'_append s n 1).symm
#align list.range'_concat List.range'_concat
-/- warning: list.range_core_range' -> List.range_loop_range' is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range.loop s (List.range' s n)) (List.range' (OfNat.ofNat.{0} Nat 0 (OfNat.mk.{0} Nat 0 (Zero.zero.{0} Nat Nat.hasZero))) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n s))
-but is expected to have type
- forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range.loop s (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (List.range' (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0)) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n s) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
-Case conversion may be inaccurate. Consider using '#align list.range_core_range' List.range_loop_range'ₓ'. -/
theorem range_loop_range' : ∀ s n : ℕ, List.range.loop s (range' s n) = range' 0 (n + s)
| 0, n => rfl
| s + 1, n => by
@@ -227,12 +131,6 @@ theorem range_loop_range' : ∀ s n : ℕ, List.range.loop s (range' s n) = rang
exact range_core_range' s (n + 1)
#align list.range_core_range' List.range_loop_range'
-/- warning: list.range_eq_range' -> List.range_eq_range' is a dubious translation:
-lean 3 declaration is
- forall (n : Nat), Eq.{1} (List.{0} Nat) (List.range n) (List.range' (OfNat.ofNat.{0} Nat 0 (OfNat.mk.{0} Nat 0 (Zero.zero.{0} Nat Nat.hasZero))) n)
-but is expected to have type
- forall (n : Nat), Eq.{1} (List.{0} Nat) (List.range n) (List.range' (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0)) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
-Case conversion may be inaccurate. Consider using '#align list.range_eq_range' List.range_eq_range'ₓ'. -/
theorem range_eq_range' (n : ℕ) : range n = range' 0 n :=
(range_loop_range' n 0).trans <| by rw [zero_add]
#align list.range_eq_range' List.range_eq_range'
@@ -244,12 +142,6 @@ theorem range_succ_eq_map (n : ℕ) : range (n + 1) = 0 :: map succ (range n) :=
#align list.range_succ_eq_map List.range_succ_eq_map
-/
-/- warning: list.range'_eq_map_range -> List.range'_eq_map_range is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range' s n) (List.map.{0, 0} Nat Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s) (List.range n))
-but is expected to have type
- forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.map.{0, 0} Nat Nat (fun (x._@.Mathlib.Data.List.Range._hyg.1967 : Nat) => HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s x._@.Mathlib.Data.List.Range._hyg.1967) (List.range n))
-Case conversion may be inaccurate. Consider using '#align list.range'_eq_map_range List.range'_eq_map_rangeₓ'. -/
theorem range'_eq_map_range (s n : ℕ) : range' s n = map ((· + ·) s) (range n) := by
rw [range_eq_range', map_add_range'] <;> rfl
#align list.range'_eq_map_range List.range'_eq_map_range
@@ -366,12 +258,6 @@ theorem range_add (a : ℕ) : ∀ b, range (a + b) = range a ++ (range b).map fu
#align list.range_add List.range_add
-/
-/- warning: list.iota_eq_reverse_range' -> List.iota_eq_reverse_range' is a dubious translation:
-lean 3 declaration is
- forall (n : Nat), Eq.{1} (List.{0} Nat) (List.iota n) (List.reverse.{0} Nat (List.range' (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne))) n))
-but is expected to have type
- forall (n : Nat), Eq.{1} (List.{0} Nat) (List.iota n) (List.reverse.{0} Nat (List.range' (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))))
-Case conversion may be inaccurate. Consider using '#align list.iota_eq_reverse_range' List.iota_eq_reverse_range'ₓ'. -/
theorem iota_eq_reverse_range' : ∀ n : ℕ, iota n = reverse (range' 1 n)
| 0 => rfl
| n + 1 => by
@@ -403,12 +289,6 @@ theorem mem_iota {m n : ℕ} : m ∈ iota n ↔ 1 ≤ m ∧ m ≤ n := by
#align list.mem_iota List.mem_iota
-/
-/- warning: list.reverse_range' -> List.reverse_range' is a dubious translation:
-lean 3 declaration is
- forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.reverse.{0} Nat (List.range' s n)) (List.map.{0, 0} Nat Nat (fun (i : Nat) => HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat Nat.hasSub) (HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat Nat.hasSub) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s n) (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne)))) i) (List.range n))
-but is expected to have type
- forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.reverse.{0} Nat (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (List.map.{0, 0} Nat Nat (fun (i : Nat) => HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat instSubNat) (HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat instSubNat) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s n) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) i) (List.range n))
-Case conversion may be inaccurate. Consider using '#align list.reverse_range' List.reverse_range'ₓ'. -/
theorem reverse_range' : ∀ s n : ℕ, reverse (range' s n) = map (fun i => s + n - 1 - i) (range n)
| s, 0 => rfl
| s, n + 1 => by
@@ -459,12 +339,6 @@ theorem finRange_eq_nil {n : ℕ} : finRange n = [] ↔ n = 0 := by
#align list.fin_range_eq_nil List.finRange_eq_nil
-/
-/- warning: list.prod_range_succ -> List.prod_range_succ is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : Monoid.{u1} α] (f : Nat -> α) (n : Nat), Eq.{succ u1} α (List.prod.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (MulOneClass.toHasOne.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (List.map.{0, u1} Nat α f (List.range (Nat.succ n)))) (HMul.hMul.{u1, u1, u1} α α α (instHMul.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1))) (List.prod.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (MulOneClass.toHasOne.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (List.map.{0, u1} Nat α f (List.range n))) (f n))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : Monoid.{u1} α] (f : Nat -> α) (n : Nat), Eq.{succ u1} α (List.prod.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (Monoid.toOne.{u1} α _inst_1) (List.map.{0, u1} Nat α f (List.range (Nat.succ n)))) (HMul.hMul.{u1, u1, u1} α α α (instHMul.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1))) (List.prod.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (Monoid.toOne.{u1} α _inst_1) (List.map.{0, u1} Nat α f (List.range n))) (f n))
-Case conversion may be inaccurate. Consider using '#align list.prod_range_succ List.prod_range_succₓ'. -/
@[to_additive]
theorem prod_range_succ {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
((range n.succ).map f).Prod = ((range n).map f).Prod * f n := by
@@ -472,12 +346,6 @@ theorem prod_range_succ {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
#align list.prod_range_succ List.prod_range_succ
#align list.sum_range_succ List.sum_range_succ
-/- warning: list.prod_range_succ' -> List.prod_range_succ' is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : Monoid.{u1} α] (f : Nat -> α) (n : Nat), Eq.{succ u1} α (List.prod.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (MulOneClass.toHasOne.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (List.map.{0, u1} Nat α f (List.range (Nat.succ n)))) (HMul.hMul.{u1, u1, u1} α α α (instHMul.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1))) (f (OfNat.ofNat.{0} Nat 0 (OfNat.mk.{0} Nat 0 (Zero.zero.{0} Nat Nat.hasZero)))) (List.prod.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (MulOneClass.toHasOne.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (List.map.{0, u1} Nat α (fun (i : Nat) => f (Nat.succ i)) (List.range n))))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : Monoid.{u1} α] (f : Nat -> α) (n : Nat), Eq.{succ u1} α (List.prod.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (Monoid.toOne.{u1} α _inst_1) (List.map.{0, u1} Nat α f (List.range (Nat.succ n)))) (HMul.hMul.{u1, u1, u1} α α α (instHMul.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1))) (f (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0))) (List.prod.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (Monoid.toOne.{u1} α _inst_1) (List.map.{0, u1} Nat α (fun (i : Nat) => f (Nat.succ i)) (List.range n))))
-Case conversion may be inaccurate. Consider using '#align list.prod_range_succ' List.prod_range_succ'ₓ'. -/
/-- A variant of `prod_range_succ` which pulls off the first
term in the product rather than the last.-/
@[to_additive
@@ -489,12 +357,6 @@ theorem prod_range_succ' {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
#align list.prod_range_succ' List.prod_range_succ'
#align list.sum_range_succ' List.sum_range_succ'
-/- warning: list.enum_from_map_fst -> List.enum_from_map_fst is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (n : Nat) (l : List.{u1} α), Eq.{1} (List.{0} Nat) (List.map.{u1, 0} (Prod.{0, u1} Nat α) Nat (Prod.fst.{0, u1} Nat α) (List.enumFrom.{u1} α n l)) (List.range' n (List.length.{u1} α l))
-but is expected to have type
- forall {α : Type.{u1}} (n : Nat) (l : List.{u1} α), Eq.{1} (List.{0} Nat) (List.map.{u1, 0} (Prod.{0, u1} Nat α) Nat (Prod.fst.{0, u1} Nat α) (List.enumFrom.{u1} α n l)) (List.range' n (List.length.{u1} α l) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
-Case conversion may be inaccurate. Consider using '#align list.enum_from_map_fst List.enum_from_map_fstₓ'. -/
@[simp]
theorem enum_from_map_fst : ∀ (n) (l : List α), map Prod.fst (enumFrom n l) = range' n l.length
| n, [] => rfl
@@ -521,22 +383,10 @@ theorem unzip_enum_eq_prod (l : List α) : l.enum.unzip = (range l.length, l) :=
#align list.unzip_enum_eq_prod List.unzip_enum_eq_prod
-/
-/- warning: list.enum_from_eq_zip_range' -> List.enum_from_eq_zip_range' is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (l : List.{u1} α) {n : Nat}, Eq.{succ u1} (List.{u1} (Prod.{0, u1} Nat α)) (List.enumFrom.{u1} α n l) (List.zip.{0, u1} Nat α (List.range' n (List.length.{u1} α l)) l)
-but is expected to have type
- forall {α : Type.{u1}} (l : List.{u1} α) {n : Nat}, Eq.{succ u1} (List.{u1} (Prod.{0, u1} Nat α)) (List.enumFrom.{u1} α n l) (List.zip.{0, u1} Nat α (List.range' n (List.length.{u1} α l) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) l)
-Case conversion may be inaccurate. Consider using '#align list.enum_from_eq_zip_range' List.enum_from_eq_zip_range'ₓ'. -/
theorem enum_from_eq_zip_range' (l : List α) {n : ℕ} : l.enumFrom n = (range' n l.length).zip l :=
zip_of_prod (enum_from_map_fst _ _) (enumFrom_map_snd _ _)
#align list.enum_from_eq_zip_range' List.enum_from_eq_zip_range'
-/- warning: list.unzip_enum_from_eq_prod -> List.unzip_enum_from_eq_prod is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (l : List.{u1} α) {n : Nat}, Eq.{succ u1} (Prod.{0, u1} (List.{0} Nat) (List.{u1} α)) (List.unzip.{0, u1} Nat α (List.enumFrom.{u1} α n l)) (Prod.mk.{0, u1} (List.{0} Nat) (List.{u1} α) (List.range' n (List.length.{u1} α l)) l)
-but is expected to have type
- forall {α : Type.{u1}} (l : List.{u1} α) {n : Nat}, Eq.{succ u1} (Prod.{0, u1} (List.{0} Nat) (List.{u1} α)) (List.unzip.{0, u1} Nat α (List.enumFrom.{u1} α n l)) (Prod.mk.{0, u1} (List.{0} Nat) (List.{u1} α) (List.range' n (List.length.{u1} α l) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) l)
-Case conversion may be inaccurate. Consider using '#align list.unzip_enum_from_eq_prod List.unzip_enum_from_eq_prodₓ'. -/
@[simp]
theorem unzip_enum_from_eq_prod (l : List α) {n : ℕ} :
(l.enumFrom n).unzip = (range' n l.length, l) := by
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -435,10 +435,7 @@ theorem finRange_zero : finRange 0 = [] :=
#print List.mem_finRange /-
@[simp]
theorem mem_finRange {n : ℕ} (a : Fin n) : a ∈ finRange n :=
- mem_pmap.2
- ⟨a.1, mem_range.2 a.2, by
- cases a
- rfl⟩
+ mem_pmap.2 ⟨a.1, mem_range.2 a.2, by cases a; rfl⟩
#align list.mem_fin_range List.mem_finRange
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/8d33f09cd7089ecf074b4791907588245aec5d1b
@@ -34,21 +34,34 @@ namespace List
variable {α : Type u}
-#print List.length_range' /-
+/- warning: list.length_range' -> List.length_range' is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) (n : Nat), Eq.{1} Nat (List.length.{0} Nat (List.range' s n)) n
+but is expected to have type
+ forall (s : Nat) (n : Nat), Eq.{1} Nat (List.length.{0} Nat (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) n
+Case conversion may be inaccurate. Consider using '#align list.length_range' List.length_range'ₓ'. -/
@[simp]
theorem length_range' : ∀ s n : ℕ, length (range' s n) = n
| s, 0 => rfl
| s, n + 1 => congr_arg succ (length_range' _ _)
#align list.length_range' List.length_range'
--/
-#print List.range'_eq_nil /-
+/- warning: list.range'_eq_nil -> List.range'_eq_nil is a dubious translation:
+lean 3 declaration is
+ forall {s : Nat} {n : Nat}, Iff (Eq.{1} (List.{0} Nat) (List.range' s n) (List.nil.{0} Nat)) (Eq.{1} Nat n (OfNat.ofNat.{0} Nat 0 (OfNat.mk.{0} Nat 0 (Zero.zero.{0} Nat Nat.hasZero))))
+but is expected to have type
+ forall {s : Nat} {n : Nat}, Iff (Eq.{1} (List.{0} Nat) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.nil.{0} Nat)) (Eq.{1} Nat n (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0)))
+Case conversion may be inaccurate. Consider using '#align list.range'_eq_nil List.range'_eq_nilₓ'. -/
@[simp]
theorem range'_eq_nil {s n : ℕ} : range' s n = [] ↔ n = 0 := by rw [← length_eq_zero, length_range']
#align list.range'_eq_nil List.range'_eq_nil
--/
-#print List.mem_range' /-
+/- warning: list.mem_range' -> List.mem_range' is a dubious translation:
+lean 3 declaration is
+ forall {m : Nat} {s : Nat} {n : Nat}, Iff (Membership.Mem.{0, 0} Nat (List.{0} Nat) (List.hasMem.{0} Nat) m (List.range' s n)) (And (LE.le.{0} Nat Nat.hasLe s m) (LT.lt.{0} Nat Nat.hasLt m (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s n)))
+but is expected to have type
+ forall {m : Nat} {s : Nat} {n : Nat}, Iff (Membership.mem.{0, 0} Nat (List.{0} Nat) (List.instMembershipList.{0} Nat) m (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (And (LE.le.{0} Nat instLENat s m) (LT.lt.{0} Nat instLTNat m (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s n)))
+Case conversion may be inaccurate. Consider using '#align list.mem_range' List.mem_range'ₓ'. -/
@[simp]
theorem mem_range' {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧ m < s + n
| s, 0 => (false_iff_iff _).2 fun ⟨H1, H2⟩ => not_le_of_lt H2 H1
@@ -59,16 +72,24 @@ theorem mem_range' {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧
(mem_cons _ _ _).trans <| by
simp only [mem_range', or_and_left, or_iff_right_of_imp this, l, add_right_comm] <;> rfl
#align list.mem_range' List.mem_range'
--/
-#print List.map_add_range' /-
+/- warning: list.map_add_range' -> List.map_add_range' is a dubious translation:
+lean 3 declaration is
+ forall (a : Nat) (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.map.{0, 0} Nat Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) a) (List.range' s n)) (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) a s) n)
+but is expected to have type
+ forall (a : Nat) (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.map.{0, 0} Nat Nat ((fun (x._@.Mathlib.Data.List.Range._hyg.391 : Nat) (x._@.Mathlib.Data.List.Range._hyg.393 : Nat) => HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) x._@.Mathlib.Data.List.Range._hyg.391 x._@.Mathlib.Data.List.Range._hyg.393) a) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) a s) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
+Case conversion may be inaccurate. Consider using '#align list.map_add_range' List.map_add_range'ₓ'. -/
theorem map_add_range' (a) : ∀ s n : ℕ, map ((· + ·) a) (range' s n) = range' (a + s) n
| s, 0 => rfl
| s, n + 1 => congr_arg (cons _) (map_add_range' (s + 1) n)
#align list.map_add_range' List.map_add_range'
--/
-#print List.map_sub_range' /-
+/- warning: list.map_sub_range' -> List.map_sub_range' is a dubious translation:
+lean 3 declaration is
+ forall (a : Nat) (s : Nat) (n : Nat), (LE.le.{0} Nat Nat.hasLe a s) -> (Eq.{1} (List.{0} Nat) (List.map.{0, 0} Nat Nat (fun (x : Nat) => HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat Nat.hasSub) x a) (List.range' s n)) (List.range' (HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat Nat.hasSub) s a) n))
+but is expected to have type
+ forall (a : Nat) (s : Nat) (n : Nat), (LE.le.{0} Nat instLENat a s) -> (Eq.{1} (List.{0} Nat) (List.map.{0, 0} Nat Nat (fun (x : Nat) => HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat instSubNat) x a) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (List.range' (HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat instSubNat) s a) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))))
+Case conversion may be inaccurate. Consider using '#align list.map_sub_range' List.map_sub_range'ₓ'. -/
theorem map_sub_range' (a) :
∀ (s n : ℕ) (h : a ≤ s), map (fun x => x - a) (range' s n) = range' (s - a) n
| s, 0, _ => rfl
@@ -78,35 +99,55 @@ theorem map_sub_range' (a) :
rw [Nat.succ_sub h]
rfl
#align list.map_sub_range' List.map_sub_range'
--/
-#print List.chain_succ_range' /-
+/- warning: list.chain_succ_range' -> List.chain_succ_range' is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) (n : Nat), List.Chain.{0} Nat (fun (a : Nat) (b : Nat) => Eq.{1} Nat b (Nat.succ a)) s (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne)))) n)
+but is expected to have type
+ forall (s : Nat) (n : Nat), List.Chain.{0} Nat (fun (a : Nat) (b : Nat) => Eq.{1} Nat b (Nat.succ a)) s (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
+Case conversion may be inaccurate. Consider using '#align list.chain_succ_range' List.chain_succ_range'ₓ'. -/
theorem chain_succ_range' : ∀ s n : ℕ, Chain (fun a b => b = succ a) s (range' (s + 1) n)
| s, 0 => Chain.nil
| s, n + 1 => (chain_succ_range' (s + 1) n).cons rfl
#align list.chain_succ_range' List.chain_succ_range'
--/
-#print List.chain_lt_range' /-
+/- warning: list.chain_lt_range' -> List.chain_lt_range' is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) (n : Nat), List.Chain.{0} Nat (LT.lt.{0} Nat Nat.hasLt) s (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne)))) n)
+but is expected to have type
+ forall (s : Nat) (n : Nat), List.Chain.{0} Nat (fun (x._@.Mathlib.Data.List.Range._hyg.791 : Nat) (x._@.Mathlib.Data.List.Range._hyg.793 : Nat) => LT.lt.{0} Nat instLTNat x._@.Mathlib.Data.List.Range._hyg.791 x._@.Mathlib.Data.List.Range._hyg.793) s (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
+Case conversion may be inaccurate. Consider using '#align list.chain_lt_range' List.chain_lt_range'ₓ'. -/
theorem chain_lt_range' (s n : ℕ) : Chain (· < ·) s (range' (s + 1) n) :=
(chain_succ_range' s n).imp fun a b e => e.symm ▸ lt_succ_self _
#align list.chain_lt_range' List.chain_lt_range'
--/
-#print List.pairwise_lt_range' /-
+/- warning: list.pairwise_lt_range' -> List.pairwise_lt_range' is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) (n : Nat), List.Pairwise.{0} Nat (LT.lt.{0} Nat Nat.hasLt) (List.range' s n)
+but is expected to have type
+ forall (s : Nat) (n : Nat), List.Pairwise.{0} Nat (fun (x._@.Mathlib.Data.List.Range._hyg.852 : Nat) (x._@.Mathlib.Data.List.Range._hyg.854 : Nat) => LT.lt.{0} Nat instLTNat x._@.Mathlib.Data.List.Range._hyg.852 x._@.Mathlib.Data.List.Range._hyg.854) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
+Case conversion may be inaccurate. Consider using '#align list.pairwise_lt_range' List.pairwise_lt_range'ₓ'. -/
theorem pairwise_lt_range' : ∀ s n : ℕ, Pairwise (· < ·) (range' s n)
| s, 0 => Pairwise.nil
| s, n + 1 => chain_iff_pairwise.1 (chain_lt_range' s n)
#align list.pairwise_lt_range' List.pairwise_lt_range'
--/
-#print List.nodup_range' /-
+/- warning: list.nodup_range' -> List.nodup_range' is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) (n : Nat), List.Nodup.{0} Nat (List.range' s n)
+but is expected to have type
+ forall (s : Nat) (n : Nat), List.Nodup.{0} Nat (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
+Case conversion may be inaccurate. Consider using '#align list.nodup_range' List.nodup_range'ₓ'. -/
theorem nodup_range' (s n : ℕ) : Nodup (range' s n) :=
(pairwise_lt_range' s n).imp fun a b => ne_of_lt
#align list.nodup_range' List.nodup_range'
--/
-#print List.range'_append /-
+/- warning: list.range'_append -> List.range'_append is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) (m : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (Append.append.{0} (List.{0} Nat) (List.hasAppend.{0} Nat) (List.range' s m) (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s m) n)) (List.range' s (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n m))
+but is expected to have type
+ forall (s : Nat) (m : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (HAppend.hAppend.{0, 0, 0} (List.{0} Nat) (List.{0} Nat) (List.{0} Nat) (instHAppend.{0} (List.{0} Nat) (List.instAppendList.{0} Nat)) (List.range' s m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.range' (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s m) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (List.range' s (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n m) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
+Case conversion may be inaccurate. Consider using '#align list.range'_append List.range'_appendₓ'. -/
@[simp]
theorem range'_append : ∀ s m n : ℕ, range' s m ++ range' (s + m) n = range' s (n + m)
| s, 0, n => rfl
@@ -114,16 +155,24 @@ theorem range'_append : ∀ s m n : ℕ, range' s m ++ range' (s + m) n = range'
show s :: (range' (s + 1) m ++ range' (s + m + 1) n) = s :: range' (s + 1) (n + m) by
rw [add_right_comm, range'_append]
#align list.range'_append List.range'_append
--/
-#print List.range'_sublist_right /-
+/- warning: list.range'_sublist_right -> List.range'_sublist_right is a dubious translation:
+lean 3 declaration is
+ forall {s : Nat} {m : Nat} {n : Nat}, Iff (List.Sublist.{0} Nat (List.range' s m) (List.range' s n)) (LE.le.{0} Nat Nat.hasLe m n)
+but is expected to have type
+ forall {s : Nat} {m : Nat} {n : Nat}, Iff (List.Sublist.{0} Nat (List.range' s m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (LE.le.{0} Nat instLENat m n)
+Case conversion may be inaccurate. Consider using '#align list.range'_sublist_right List.range'_sublist_rightₓ'. -/
theorem range'_sublist_right {s m n : ℕ} : range' s m <+ range' s n ↔ m ≤ n :=
⟨fun h => by simpa only [length_range'] using h.length_le, fun h => by
rw [← tsub_add_cancel_of_le h, ← range'_append] <;> apply sublist_append_left⟩
#align list.range'_sublist_right List.range'_sublist_right
--/
-#print List.range'_subset_right /-
+/- warning: list.range'_subset_right -> List.range'_subset_right is a dubious translation:
+lean 3 declaration is
+ forall {s : Nat} {m : Nat} {n : Nat}, Iff (HasSubset.Subset.{0} (List.{0} Nat) (List.hasSubset.{0} Nat) (List.range' s m) (List.range' s n)) (LE.le.{0} Nat Nat.hasLe m n)
+but is expected to have type
+ forall {s : Nat} {m : Nat} {n : Nat}, Iff (HasSubset.Subset.{0} (List.{0} Nat) (List.instHasSubsetList.{0} Nat) (List.range' s m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (LE.le.{0} Nat instLENat m n)
+Case conversion may be inaccurate. Consider using '#align list.range'_subset_right List.range'_subset_rightₓ'. -/
theorem range'_subset_right {s m n : ℕ} : range' s m ⊆ range' s n ↔ m ≤ n :=
⟨fun h =>
le_of_not_lt fun hn =>
@@ -131,43 +180,62 @@ theorem range'_subset_right {s m n : ℕ} : range' s m ⊆ range' s n ↔ m ≤
(mem_range'.1 <| h <| mem_range'.2 ⟨Nat.le_add_right _ _, Nat.add_lt_add_left hn s⟩).2,
fun h => (range'_sublist_right.2 h).Subset⟩
#align list.range'_subset_right List.range'_subset_right
--/
-#print List.get?_range' /-
+/- warning: list.nth_range' -> List.get?_range' is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) {m : Nat} {n : Nat}, (LT.lt.{0} Nat Nat.hasLt m n) -> (Eq.{1} (Option.{0} Nat) (List.get?.{0} Nat (List.range' s n) m) (Option.some.{0} Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s m)))
+but is expected to have type
+ forall (s : Nat) {m : Nat} {n : Nat}, (LT.lt.{0} Nat instLTNat m n) -> (Eq.{1} (Option.{0} Nat) (List.get?.{0} Nat (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) m) (Option.some.{0} Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s m)))
+Case conversion may be inaccurate. Consider using '#align list.nth_range' List.get?_range'ₓ'. -/
theorem get?_range' : ∀ (s) {m n : ℕ}, m < n → get? (range' s n) m = some (s + m)
| s, 0, n + 1, _ => rfl
| s, m + 1, n + 1, h =>
(nth_range' (s + 1) (lt_of_add_lt_add_right h)).trans <| by rw [add_right_comm] <;> rfl
#align list.nth_range' List.get?_range'
--/
-#print List.nthLe_range' /-
+/- warning: list.nth_le_range' -> List.nthLe_range' is a dubious translation:
+lean 3 declaration is
+ forall {n : Nat} {m : Nat} (i : Nat) (H : LT.lt.{0} Nat Nat.hasLt i (List.length.{0} Nat (List.range' n m))), Eq.{1} Nat (List.nthLe.{0} Nat (List.range' n m) i H) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n i)
+but is expected to have type
+ forall {n : Nat} {m : Nat} (i : Nat) (H : LT.lt.{0} Nat instLTNat i (List.length.{0} Nat (List.range' n m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))))), Eq.{1} Nat (List.nthLe.{0} Nat (List.range' n m (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) i H) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n i)
+Case conversion may be inaccurate. Consider using '#align list.nth_le_range' List.nthLe_range'ₓ'. -/
@[simp]
theorem nthLe_range' {n m} (i) (H : i < (range' n m).length) : nthLe (range' n m) i H = n + i :=
Option.some.inj <| by rw [← nth_le_nth _, nth_range' _ (by simpa using H)]
#align list.nth_le_range' List.nthLe_range'
--/
-#print List.range'_concat /-
+/- warning: list.range'_concat -> List.range'_concat is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range' s (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne))))) (Append.append.{0} (List.{0} Nat) (List.hasAppend.{0} Nat) (List.range' s n) (List.cons.{0} Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s n) (List.nil.{0} Nat)))
+but is expected to have type
+ forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range' s (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (HAppend.hAppend.{0, 0, 0} (List.{0} Nat) (List.{0} Nat) (List.{0} Nat) (instHAppend.{0} (List.{0} Nat) (List.instAppendList.{0} Nat)) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.cons.{0} Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s n) (List.nil.{0} Nat)))
+Case conversion may be inaccurate. Consider using '#align list.range'_concat List.range'_concatₓ'. -/
theorem range'_concat (s n : ℕ) : range' s (n + 1) = range' s n ++ [s + n] := by
rw [add_comm n 1] <;> exact (range'_append s n 1).symm
#align list.range'_concat List.range'_concat
--/
-#print List.range_loop_range' /-
+/- warning: list.range_core_range' -> List.range_loop_range' is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range.loop s (List.range' s n)) (List.range' (OfNat.ofNat.{0} Nat 0 (OfNat.mk.{0} Nat 0 (Zero.zero.{0} Nat Nat.hasZero))) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) n s))
+but is expected to have type
+ forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range.loop s (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (List.range' (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0)) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) n s) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
+Case conversion may be inaccurate. Consider using '#align list.range_core_range' List.range_loop_range'ₓ'. -/
theorem range_loop_range' : ∀ s n : ℕ, List.range.loop s (range' s n) = range' 0 (n + s)
| 0, n => rfl
| s + 1, n => by
rw [show n + (s + 1) = n + 1 + s from add_right_comm n s 1] <;>
exact range_core_range' s (n + 1)
#align list.range_core_range' List.range_loop_range'
--/
-#print List.range_eq_range' /-
+/- warning: list.range_eq_range' -> List.range_eq_range' is a dubious translation:
+lean 3 declaration is
+ forall (n : Nat), Eq.{1} (List.{0} Nat) (List.range n) (List.range' (OfNat.ofNat.{0} Nat 0 (OfNat.mk.{0} Nat 0 (Zero.zero.{0} Nat Nat.hasZero))) n)
+but is expected to have type
+ forall (n : Nat), Eq.{1} (List.{0} Nat) (List.range n) (List.range' (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0)) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
+Case conversion may be inaccurate. Consider using '#align list.range_eq_range' List.range_eq_range'ₓ'. -/
theorem range_eq_range' (n : ℕ) : range n = range' 0 n :=
(range_loop_range' n 0).trans <| by rw [zero_add]
#align list.range_eq_range' List.range_eq_range'
--/
#print List.range_succ_eq_map /-
theorem range_succ_eq_map (n : ℕ) : range (n + 1) = 0 :: map succ (range n) := by
@@ -176,11 +244,15 @@ theorem range_succ_eq_map (n : ℕ) : range (n + 1) = 0 :: map succ (range n) :=
#align list.range_succ_eq_map List.range_succ_eq_map
-/
-#print List.range'_eq_map_range /-
+/- warning: list.range'_eq_map_range -> List.range'_eq_map_range is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range' s n) (List.map.{0, 0} Nat Nat (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s) (List.range n))
+but is expected to have type
+ forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) (List.map.{0, 0} Nat Nat (fun (x._@.Mathlib.Data.List.Range._hyg.1967 : Nat) => HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s x._@.Mathlib.Data.List.Range._hyg.1967) (List.range n))
+Case conversion may be inaccurate. Consider using '#align list.range'_eq_map_range List.range'_eq_map_rangeₓ'. -/
theorem range'_eq_map_range (s n : ℕ) : range' s n = map ((· + ·) s) (range n) := by
rw [range_eq_range', map_add_range'] <;> rfl
#align list.range'_eq_map_range List.range'_eq_map_range
--/
#print List.length_range /-
@[simp]
@@ -294,13 +366,17 @@ theorem range_add (a : ℕ) : ∀ b, range (a + b) = range a ++ (range b).map fu
#align list.range_add List.range_add
-/
-#print List.iota_eq_reverse_range' /-
+/- warning: list.iota_eq_reverse_range' -> List.iota_eq_reverse_range' is a dubious translation:
+lean 3 declaration is
+ forall (n : Nat), Eq.{1} (List.{0} Nat) (List.iota n) (List.reverse.{0} Nat (List.range' (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne))) n))
+but is expected to have type
+ forall (n : Nat), Eq.{1} (List.{0} Nat) (List.iota n) (List.reverse.{0} Nat (List.range' (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)) n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))))
+Case conversion may be inaccurate. Consider using '#align list.iota_eq_reverse_range' List.iota_eq_reverse_range'ₓ'. -/
theorem iota_eq_reverse_range' : ∀ n : ℕ, iota n = reverse (range' 1 n)
| 0 => rfl
| n + 1 => by
simp only [iota, range'_concat, iota_eq_reverse_range' n, reverse_append, add_comm] <;> rfl
#align list.iota_eq_reverse_range' List.iota_eq_reverse_range'
--/
#print List.length_iota /-
@[simp]
@@ -327,7 +403,12 @@ theorem mem_iota {m n : ℕ} : m ∈ iota n ↔ 1 ≤ m ∧ m ≤ n := by
#align list.mem_iota List.mem_iota
-/
-#print List.reverse_range' /-
+/- warning: list.reverse_range' -> List.reverse_range' is a dubious translation:
+lean 3 declaration is
+ forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.reverse.{0} Nat (List.range' s n)) (List.map.{0, 0} Nat Nat (fun (i : Nat) => HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat Nat.hasSub) (HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat Nat.hasSub) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) s n) (OfNat.ofNat.{0} Nat 1 (OfNat.mk.{0} Nat 1 (One.one.{0} Nat Nat.hasOne)))) i) (List.range n))
+but is expected to have type
+ forall (s : Nat) (n : Nat), Eq.{1} (List.{0} Nat) (List.reverse.{0} Nat (List.range' s n (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))) (List.map.{0, 0} Nat Nat (fun (i : Nat) => HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat instSubNat) (HSub.hSub.{0, 0, 0} Nat Nat Nat (instHSub.{0} Nat instSubNat) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) s n) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) i) (List.range n))
+Case conversion may be inaccurate. Consider using '#align list.reverse_range' List.reverse_range'ₓ'. -/
theorem reverse_range' : ∀ s n : ℕ, reverse (range' s n) = map (fun i => s + n - 1 - i) (range n)
| s, 0 => rfl
| s, n + 1 => by
@@ -336,7 +417,6 @@ theorem reverse_range' : ∀ s n : ℕ, reverse (range' s n) = map (fun i => s +
show a - 1 - i = a - succ i from pred_sub _ _, reverse_singleton, map_cons, tsub_zero,
cons_append, nil_append, eq_self_iff_true, true_and_iff, map_map] using reverse_range' s n
#align list.reverse_range' List.reverse_range'
--/
#print List.finRange /-
/-- All elements of `fin n`, from `0` to `n-1`. The corresponding finset is `finset.univ`. -/
@@ -412,13 +492,17 @@ theorem prod_range_succ' {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
#align list.prod_range_succ' List.prod_range_succ'
#align list.sum_range_succ' List.sum_range_succ'
-#print List.enum_from_map_fst /-
+/- warning: list.enum_from_map_fst -> List.enum_from_map_fst is a dubious translation:
+lean 3 declaration is
+ forall {α : Type.{u1}} (n : Nat) (l : List.{u1} α), Eq.{1} (List.{0} Nat) (List.map.{u1, 0} (Prod.{0, u1} Nat α) Nat (Prod.fst.{0, u1} Nat α) (List.enumFrom.{u1} α n l)) (List.range' n (List.length.{u1} α l))
+but is expected to have type
+ forall {α : Type.{u1}} (n : Nat) (l : List.{u1} α), Eq.{1} (List.{0} Nat) (List.map.{u1, 0} (Prod.{0, u1} Nat α) Nat (Prod.fst.{0, u1} Nat α) (List.enumFrom.{u1} α n l)) (List.range' n (List.length.{u1} α l) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))
+Case conversion may be inaccurate. Consider using '#align list.enum_from_map_fst List.enum_from_map_fstₓ'. -/
@[simp]
theorem enum_from_map_fst : ∀ (n) (l : List α), map Prod.fst (enumFrom n l) = range' n l.length
| n, [] => rfl
| n, a :: l => congr_arg (cons _) (enum_from_map_fst _ _)
#align list.enum_from_map_fst List.enum_from_map_fst
--/
#print List.enum_map_fst /-
@[simp]
@@ -440,19 +524,27 @@ theorem unzip_enum_eq_prod (l : List α) : l.enum.unzip = (range l.length, l) :=
#align list.unzip_enum_eq_prod List.unzip_enum_eq_prod
-/
-#print List.enum_from_eq_zip_range' /-
+/- warning: list.enum_from_eq_zip_range' -> List.enum_from_eq_zip_range' is a dubious translation:
+lean 3 declaration is
+ forall {α : Type.{u1}} (l : List.{u1} α) {n : Nat}, Eq.{succ u1} (List.{u1} (Prod.{0, u1} Nat α)) (List.enumFrom.{u1} α n l) (List.zip.{0, u1} Nat α (List.range' n (List.length.{u1} α l)) l)
+but is expected to have type
+ forall {α : Type.{u1}} (l : List.{u1} α) {n : Nat}, Eq.{succ u1} (List.{u1} (Prod.{0, u1} Nat α)) (List.enumFrom.{u1} α n l) (List.zip.{0, u1} Nat α (List.range' n (List.length.{u1} α l) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) l)
+Case conversion may be inaccurate. Consider using '#align list.enum_from_eq_zip_range' List.enum_from_eq_zip_range'ₓ'. -/
theorem enum_from_eq_zip_range' (l : List α) {n : ℕ} : l.enumFrom n = (range' n l.length).zip l :=
zip_of_prod (enum_from_map_fst _ _) (enumFrom_map_snd _ _)
#align list.enum_from_eq_zip_range' List.enum_from_eq_zip_range'
--/
-#print List.unzip_enum_from_eq_prod /-
+/- warning: list.unzip_enum_from_eq_prod -> List.unzip_enum_from_eq_prod is a dubious translation:
+lean 3 declaration is
+ forall {α : Type.{u1}} (l : List.{u1} α) {n : Nat}, Eq.{succ u1} (Prod.{0, u1} (List.{0} Nat) (List.{u1} α)) (List.unzip.{0, u1} Nat α (List.enumFrom.{u1} α n l)) (Prod.mk.{0, u1} (List.{0} Nat) (List.{u1} α) (List.range' n (List.length.{u1} α l)) l)
+but is expected to have type
+ forall {α : Type.{u1}} (l : List.{u1} α) {n : Nat}, Eq.{succ u1} (Prod.{0, u1} (List.{0} Nat) (List.{u1} α)) (List.unzip.{0, u1} Nat α (List.enumFrom.{u1} α n l)) (Prod.mk.{0, u1} (List.{0} Nat) (List.{u1} α) (List.range' n (List.length.{u1} α l) (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1))) l)
+Case conversion may be inaccurate. Consider using '#align list.unzip_enum_from_eq_prod List.unzip_enum_from_eq_prodₓ'. -/
@[simp]
theorem unzip_enum_from_eq_prod (l : List α) {n : ℕ} :
(l.enumFrom n).unzip = (range' n l.length, l) := by
simp only [enum_from_eq_zip_range', unzip_zip, length_range']
#align list.unzip_enum_from_eq_prod List.unzip_enum_from_eq_prod
--/
#print List.nthLe_range /-
@[simp]
mathlib commit https://github.com/leanprover-community/mathlib/commit/bd9851ca476957ea4549eb19b40e7b5ade9428cc
@@ -4,9 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau, Scott Morrison
-/
import Mathlib.Data.List.Chain
+import Mathlib.Data.List.Enum
import Mathlib.Data.List.Nodup
-import Mathlib.Data.List.Zip
import Mathlib.Data.List.Pairwise
+import Mathlib.Data.List.Zip
#align_import data.list.range from "leanprover-community/mathlib"@"7b78d1776212a91ecc94cf601f83bdcc46b04213"
Data.List.Count
, Data.List.Dedup
, Data.List.ProdSigma
, Data.List.Range
, Data.List.Rotate
, Data.List.Zip
not depend on Data.List.BigOperators.Basic
.Data.List.BigOperators.Basic
. For the lemmas that were Nat
-specific, keep a version of them in the original file but stated using Nat.sum
.Nat.sum_eq_listSum (l : List Nat) : Nat.sum l = l.sum
.@@ -165,24 +165,6 @@ theorem pairwise_lt_finRange (n : ℕ) : Pairwise (· < ·) (finRange n) :=
theorem pairwise_le_finRange (n : ℕ) : Pairwise (· ≤ ·) (finRange n) :=
(List.pairwise_le_range n).pmap (by simp) (by simp)
-@[to_additive]
-theorem prod_range_succ {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
- ((range n.succ).map f).prod = ((range n).map f).prod * f n := by
- rw [range_succ, map_append, map_singleton, prod_append, prod_cons, prod_nil, mul_one]
-#align list.prod_range_succ List.prod_range_succ
-#align list.sum_range_succ List.sum_range_succ
-
-/-- A variant of `prod_range_succ` which pulls off the first
- term in the product rather than the last.-/
-@[to_additive
- "A variant of `sum_range_succ` which pulls off the first term in the sum rather than the last."]
-theorem prod_range_succ' {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
- ((range n.succ).map f).prod = f 0 * ((range n).map fun i => f (succ i)).prod :=
- Nat.recOn n (show 1 * f 0 = f 0 * 1 by rw [one_mul, mul_one]) fun _ hd => by
- rw [List.prod_range_succ, hd, mul_assoc, ← List.prod_range_succ]
-#align list.prod_range_succ' List.prod_range_succ'
-#align list.sum_range_succ' List.sum_range_succ'
-
#align list.enum_from_map_fst List.enumFrom_map_fst
#align list.enum_map_fst List.enum_map_fst
@@ -259,7 +241,7 @@ theorem ranges_disjoint (l : List ℕ) :
rw [mem_map]
rintro ⟨v, _, rfl⟩
rw [mem_range] at hu
- exact lt_iff_not_le.mp hu le_self_add
+ omega
· rw [pairwise_map]
apply Pairwise.imp _ hl
intro u v
@@ -279,26 +261,20 @@ theorem ranges_length (l : List ℕ) :
intro s _
simp only [Function.comp_apply, length_map]
-theorem ranges_join (l : List ℕ) :
- l.ranges.join = range l.sum := by
- induction l with
- | nil => exact rfl
- | cons a l hl =>
- simp only [sum_cons, join]
- rw [← map_join, hl]
- rw [range_add]
+/-- See `List.ranges_join` for the version about `List.sum`. -/
+lemma ranges_join' : ∀ l : List ℕ, l.ranges.join = range (Nat.sum l)
+ | [] => rfl
+ | a :: l => by simp only [sum_cons, join, ← map_join, ranges_join', range_add]
-/-- Any entry of any member of `l.ranges` is strictly smaller than `l.sum` -/
-theorem mem_mem_ranges_iff_lt_sum (l : List ℕ) {n : ℕ} :
- (∃ s ∈ List.ranges l, n ∈ s) ↔ n < l.sum := by
- rw [← mem_range, ← ranges_join, mem_join]
+/-- Any entry of any member of `l.ranges` is strictly smaller than `Nat.sum l`.
+See `List.mem_mem_ranges_iff_lt_sum` for the version about `List.sum`. -/
+lemma mem_mem_ranges_iff_lt_natSum (l : List ℕ) {n : ℕ} :
+ (∃ s ∈ l.ranges, n ∈ s) ↔ n < Nat.sum l := by
+ rw [← mem_range, ← ranges_join', mem_join]
/-- The members of `l.ranges` have no duplicate -/
-theorem ranges_nodup {l s : List ℕ} (hs : s ∈ ranges l) :
- s.Nodup := by
- refine (List.pairwise_join.mp ?_).1 s hs
- rw [ranges_join]
- exact nodup_range (sum l)
+theorem ranges_nodup {l s : List ℕ} (hs : s ∈ ranges l) : s.Nodup :=
+ (List.pairwise_join.mp $ by rw [ranges_join']; exact nodup_range _).1 s hs
end Ranges
@@ -211,13 +211,13 @@ theorem nthLe_range {n} (i) (H : i < (range n).length) : nthLe (range n) i H = i
get_range i H
#align list.nth_le_range List.nthLe_range
--- Porting note: new theorem
+-- Porting note (#10756): new theorem
@[simp]
theorem get_finRange {n : ℕ} {i : ℕ} (h) :
(finRange n).get ⟨i, h⟩ = ⟨i, length_finRange n ▸ h⟩ := by
simp only [finRange, get_range, get_pmap]
--- Porting note: new theorem, corresponding theorem used to be in Data.List.FinRange
+-- Porting note (#10756): new theorem, corresponding theorem used to be in Data.List.FinRange
@[simp]
theorem finRange_map_get (l : List α) : (finRange l.length).map l.get = l :=
List.ext_get (by simp) (by simp)
Homogenises porting notes via capitalisation and addition of whitespace.
It makes the following changes:
@@ -217,7 +217,7 @@ theorem get_finRange {n : ℕ} {i : ℕ} (h) :
(finRange n).get ⟨i, h⟩ = ⟨i, length_finRange n ▸ h⟩ := by
simp only [finRange, get_range, get_pmap]
---Porting note: new theorem, corresponding theorem used to be in Data.List.FinRange
+-- Porting note: new theorem, corresponding theorem used to be in Data.List.FinRange
@[simp]
theorem finRange_map_get (l : List α) : (finRange l.length).map l.get = l :=
List.ext_get (by simp) (by simp)
@@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau, Scott Morrison
-/
import Mathlib.Data.List.Chain
-import Mathlib.Data.List.Join
import Mathlib.Data.List.Nodup
import Mathlib.Data.List.Zip
+import Mathlib.Data.List.Pairwise
#align_import data.list.range from "leanprover-community/mathlib"@"7b78d1776212a91ecc94cf601f83bdcc46b04213"
@@ -243,7 +243,7 @@ section Ranges
* Example: `[1,2,3].ranges = [[0],[1,2],[3,4,5]]` -/
def ranges : List ℕ → List (List ℕ)
| [] => nil
- | a::l => range a::(ranges l).map (map (Nat.add a))
+ | a::l => range a::(ranges l).map (map (a + ·))
/-- The members of `l.ranges` are pairwise disjoint -/
theorem ranges_disjoint (l : List ℕ) :
@@ -287,7 +287,6 @@ theorem ranges_join (l : List ℕ) :
simp only [sum_cons, join]
rw [← map_join, hl]
rw [range_add]
- rfl
/-- Any entry of any member of `l.ranges` is strictly smaller than `l.sum` -/
theorem mem_mem_ranges_iff_lt_sum (l : List ℕ) {n : ℕ} :
This is the supremum of
along with some minor fixes from failures on nightly-testing as Mathlib master
is merged into it.
Note that some PRs for changes that are already compatible with the current toolchain and will be necessary have already been split out: #8380.
I am hopeful that in future we will be able to progressively merge adaptation PRs into a bump/v4.X.0
branch, so we never end up with a "big merge" like this. However one of these adaptation PRs (#8056) predates my new scheme for combined CI, and it wasn't possible to keep that PR viable in the meantime.
In particular this includes adjustments for the Lean PRs
We can get rid of all the
local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue [lean4#2220](https://github.com/leanprover/lean4/pull/2220)
macros across Mathlib (and in any projects that want to write natural number powers of reals).
Changes the default behaviour of simp
to (config := {decide := false})
. This makes simp
(and consequentially norm_num
) less powerful, but also more consistent, and less likely to blow up in long failures. This requires a variety of changes: changing some previously by simp
or norm_num
to decide
or rfl
, or adding (config := {decide := true})
.
This changed the behaviour of simp
so that simp [f]
will only unfold "fully applied" occurrences of f
. The old behaviour can be recovered with simp (config := { unfoldPartialApp := true })
. We may in future add a syntax for this, e.g. simp [!f]
; please provide feedback! In the meantime, we have made the following changes:
(config := { unfoldPartialApp := true })
in some places, to recover the old behaviour@[eqns]
to manually adjust the equation lemmas for a particular definition, recovering the old behaviour just for that definition. See #8371, where we do this for Function.comp
and Function.flip
.This change in Lean may require further changes down the line (e.g. adding the !f
syntax, and/or upstreaming the special treatment for Function.comp
and Function.flip
, and/or removing this special treatment). Please keep an open and skeptical mind about these changes!
Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Mauricio Collares <mauricio@collares.org>
@@ -76,14 +76,15 @@ theorem nthLe_range'_1 {n m} (i) (H : i < (range' n m).length) :
#align list.range_eq_nil List.range_eq_nil
theorem pairwise_lt_range (n : ℕ) : Pairwise (· < ·) (range n) := by
- simp only [range_eq_range', pairwise_lt_range']
+ simp (config := {decide := true}) only [range_eq_range', pairwise_lt_range']
#align list.pairwise_lt_range List.pairwise_lt_range
theorem pairwise_le_range (n : ℕ) : Pairwise (· ≤ ·) (range n) :=
Pairwise.imp (@le_of_lt ℕ _) (pairwise_lt_range _)
#align list.pairwise_le_range List.pairwise_le_range
-theorem nodup_range (n : ℕ) : Nodup (range n) := by simp only [range_eq_range', nodup_range']
+theorem nodup_range (n : ℕ) : Nodup (range n) := by
+ simp (config := {decide := true}) only [range_eq_range', nodup_range']
#align list.nodup_range List.nodup_range
#align list.range_sublist List.range_sublist
#align list.range_subset List.range_subset
Characterize the possible types of permutations: given m : Multiset ℕ
,
there are permutations in Equiv.Perm α
with cycleType m
if and only if
m.sum
is at most Fintype.card α
and the members of m
are at least 2.
This result will be used in later PR which computes the cardinality of
conjugacy classes in Equiv.Perm α
and alternatingGroup α
Co-authored-by: Antoine Chambert-Loir <antoine.chambert-loir@math.univ-paris-diderot.fr>
@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau, Scott Morrison
-/
import Mathlib.Data.List.Chain
+import Mathlib.Data.List.Join
import Mathlib.Data.List.Nodup
import Mathlib.Data.List.Zip
@@ -234,4 +235,71 @@ theorem nthLe_finRange {n : ℕ} {i : ℕ} (h) :
have h₂ : (finRange k).get ⟨i, by simp⟩ = i := get_finRange _
simpa using (Nodup.get_inj_iff (nodup_finRange k)).mp (Eq.trans h₁ h₂.symm)
+section Ranges
+
+/-- From `l : List ℕ`, construct `l.ranges : List (List ℕ)` such that
+ `l.ranges.map List.length = l` and `l.ranges.join = range l.sum`
+* Example: `[1,2,3].ranges = [[0],[1,2],[3,4,5]]` -/
+def ranges : List ℕ → List (List ℕ)
+ | [] => nil
+ | a::l => range a::(ranges l).map (map (Nat.add a))
+
+/-- The members of `l.ranges` are pairwise disjoint -/
+theorem ranges_disjoint (l : List ℕ) :
+ Pairwise Disjoint (ranges l) := by
+ induction l with
+ | nil => exact Pairwise.nil
+ | cons a l hl =>
+ simp only [ranges, pairwise_cons]
+ constructor
+ · intro s hs
+ obtain ⟨s', _, rfl⟩ := mem_map.mp hs
+ intro u hu
+ rw [mem_map]
+ rintro ⟨v, _, rfl⟩
+ rw [mem_range] at hu
+ exact lt_iff_not_le.mp hu le_self_add
+ · rw [pairwise_map]
+ apply Pairwise.imp _ hl
+ intro u v
+ apply disjoint_map
+ exact fun u v => Nat.add_left_cancel
+#align list.ranges_disjoint List.ranges_disjoint
+
+/-- The lengths of the members of `l.ranges` are those given by `l` -/
+theorem ranges_length (l : List ℕ) :
+ l.ranges.map length = l := by
+ induction l with
+ | nil => simp only [ranges, map_nil]
+ | cons a l hl => -- (a :: l)
+ simp only [map, length_range, map_map, cons.injEq, true_and]
+ conv_rhs => rw [← hl]
+ apply map_congr
+ intro s _
+ simp only [Function.comp_apply, length_map]
+
+theorem ranges_join (l : List ℕ) :
+ l.ranges.join = range l.sum := by
+ induction l with
+ | nil => exact rfl
+ | cons a l hl =>
+ simp only [sum_cons, join]
+ rw [← map_join, hl]
+ rw [range_add]
+ rfl
+
+/-- Any entry of any member of `l.ranges` is strictly smaller than `l.sum` -/
+theorem mem_mem_ranges_iff_lt_sum (l : List ℕ) {n : ℕ} :
+ (∃ s ∈ List.ranges l, n ∈ s) ↔ n < l.sum := by
+ rw [← mem_range, ← ranges_join, mem_join]
+
+ /-- The members of `l.ranges` have no duplicate -/
+theorem ranges_nodup {l s : List ℕ} (hs : s ∈ ranges l) :
+ s.Nodup := by
+ refine (List.pairwise_join.mp ?_).1 s hs
+ rw [ranges_join]
+ exact nodup_range (sum l)
+
+end Ranges
+
end List
Prove Fin.sort_univ and List.indexOf_finRange discussed in https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/.E2.9C.94.20value.20of.20.60fintypeEquivFin.60
Co-authored-by: palalansoukî <73170405+iehality@users.noreply.github.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau, Scott Morrison
-/
import Mathlib.Data.List.Chain
+import Mathlib.Data.List.Nodup
import Mathlib.Data.List.Zip
#align_import data.list.range from "leanprover-community/mathlib"@"7b78d1776212a91ecc94cf601f83bdcc46b04213"
@@ -156,6 +157,12 @@ theorem finRange_eq_nil {n : ℕ} : finRange n = [] ↔ n = 0 := by
rw [← length_eq_zero, length_finRange]
#align list.fin_range_eq_nil List.finRange_eq_nil
+theorem pairwise_lt_finRange (n : ℕ) : Pairwise (· < ·) (finRange n) :=
+ (List.pairwise_lt_range n).pmap (by simp) (by simp)
+
+theorem pairwise_le_finRange (n : ℕ) : Pairwise (· ≤ ·) (finRange n) :=
+ (List.pairwise_le_range n).pmap (by simp) (by simp)
+
@[to_additive]
theorem prod_range_succ {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
((range n.succ).map f).prod = ((range n).map f).prod * f n := by
@@ -221,4 +228,10 @@ theorem nthLe_finRange {n : ℕ} {i : ℕ} (h) :
get_finRange h
#align list.nth_le_fin_range List.nthLe_finRange
+@[simp] theorem indexOf_finRange (i : Fin k) : (finRange k).indexOf i = i := by
+ have : (finRange k).indexOf i < (finRange k).length := indexOf_lt_length.mpr (by simp)
+ have h₁ : (finRange k).get ⟨(finRange k).indexOf i, this⟩ = i := indexOf_get this
+ have h₂ : (finRange k).get ⟨i, by simp⟩ = i := get_finRange _
+ simpa using (Nodup.get_inj_iff (nodup_finRange k)).mp (Eq.trans h₁ h₂.symm)
+
end List
Autoimplicits are highly controversial and also defeat the performance-improving work in #6474.
The intent of this PR is to make autoImplicit
opt-in on a per-file basis, by disabling it in the lakefile and enabling it again with set_option autoImplicit true
in the few files that rely on it.
That also keeps this PR small, as opposed to attempting to "fix" files to not need it any more.
I claim that many of the uses of autoImplicit
in these files are accidental; situations such as:
variables
are in scope, but pasting the lemma in the wrong sectionHaving set_option autoImplicit false
as the default prevents these types of mistake being made in the 90% of files where autoImplicit
s are not used at all, and causes them to be caught by CI during review.
I think there were various points during the port where we encouraged porters to delete the universes u v
lines; I think having autoparams for universe variables only would cover a lot of the cases we actually use them, while avoiding any real shortcomings.
A Zulip poll (after combining overlapping votes accordingly) was in favor of this change with 5:5:18
as the no:dontcare:yes
vote ratio.
While this PR was being reviewed, a handful of files gained some more likely-accidental autoImplicits. In these places, set_option autoImplicit true
has been placed locally within a section, rather than at the top of the file.
@@ -19,6 +19,8 @@ tactics. `range' a b = [a, ..., a + b - 1]` is there to help prove properties ab
Actual maths should use `List.Ico` instead.
-/
+set_option autoImplicit true
+
universe u
@@ -2,15 +2,12 @@
Copyright (c) 2018 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau, Scott Morrison
-
-! This file was ported from Lean 3 source module data.list.range
-! leanprover-community/mathlib commit 7b78d1776212a91ecc94cf601f83bdcc46b04213
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathlib.Data.List.Chain
import Mathlib.Data.List.Zip
+#align_import data.list.range from "leanprover-community/mathlib"@"7b78d1776212a91ecc94cf601f83bdcc46b04213"
+
/-!
# Ranges of naturals as lists
We disable the "relaxed" auto-implicit feature, so only single character identifiers become eligible as auto-implicits. See discussion on zulip and 2.
Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@anu.edu.au>
@@ -31,7 +31,7 @@ namespace List
variable {α : Type u}
-@[simp] theorem range'_one : range' s 1 step = [s] := rfl
+@[simp] theorem range'_one {step} : range' s 1 step = [s] := rfl
#align list.length_range' List.length_range'
#align list.range'_eq_nil List.range'_eq_nil
Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Mario Carneiro <di.gama@gmail.com> Co-authored-by: Floris van Doorn <fpvdoorn@gmail.com> Co-authored-by: Jeremy Tan Jie Rui <reddeloostw@gmail.com> Co-authored-by: Alex J Best <alex.j.best@gmail.com>
@@ -14,8 +14,8 @@ import Mathlib.Data.List.Zip
/-!
# Ranges of naturals as lists
-This file shows basic results about `List.iota`, `List.range`, `List.range'` (all defined in
-`data.list.defs`) and defines `List.finRange`.
+This file shows basic results about `List.iota`, `List.range`, `List.range'`
+and defines `List.finRange`.
`finRange n` is the list of elements of `Fin n`.
`iota n = [n, n - 1, ..., 1]` and `range n = [0, ..., n - 1]` are basic list constructions used for
tactics. `range' a b = [a, ..., a + b - 1]` is there to help prove properties about them.
@@ -31,133 +31,47 @@ namespace List
variable {α : Type u}
-@[simp]
-theorem length_range' : ∀ s n : ℕ, length (range' s n) = n
- | _, 0 => rfl
- | _, _ + 1 => congr_arg succ (length_range' _ _)
-#align list.length_range' List.length_range'
+@[simp] theorem range'_one : range' s 1 step = [s] := rfl
-@[simp]
-theorem range'_eq_nil {s n : ℕ} : range' s n = [] ↔ n = 0 := by rw [← length_eq_zero, length_range']
+#align list.length_range' List.length_range'
#align list.range'_eq_nil List.range'_eq_nil
-
-@[simp]
-theorem mem_range' {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧ m < s + n
- | s, 0 => by
- simp only [range', find?, not_mem_nil, add_zero, false_iff, not_and, not_lt, imp_self]
- | s, n + 1 =>
- have : m = s → m < s + n + 1 := fun e => e ▸ lt_succ_of_le (Nat.le_add_right _ _)
- have l : m = s ∨ s + 1 ≤ m ↔ s ≤ m := by
- simpa only [eq_comm] using (@Decidable.le_iff_eq_or_lt _ _ _ s m).symm
- mem_cons.trans <| by
- simp only [@mem_range' m (s + 1) n, or_and_left, or_iff_right_of_imp this, l,
- add_right_comm, add_eq, add_zero, and_congr_right_iff, add_assoc, or_iff_right_iff_imp]
- intro; exact this
-#align list.mem_range' List.mem_range'
-
-theorem map_add_range' (a) : ∀ s n : ℕ, map ((· + ·) a) (range' s n) = range' (a + s) n
- | _, 0 => rfl
- | s, n + 1 => congr_arg (cons _) (map_add_range' _ (s + 1) n)
+#align list.mem_range' List.mem_range'_1
#align list.map_add_range' List.map_add_range'
-
-theorem map_sub_range' (a) :
- ∀ (s n : ℕ) (_ : a ≤ s), map (fun x => x - a) (range' s n) = range' (s - a) n
- | s, 0, _ => rfl
- | s, n + 1, h => by
- convert congr_arg (cons (s - a)) (map_sub_range' _ (s + 1) n (Nat.le_succ_of_le h)) using 1
- rw [Nat.succ_sub h]
- rfl
#align list.map_sub_range' List.map_sub_range'
-
-theorem chain_succ_range' : ∀ s n : ℕ, Chain (fun a b => b = succ a) s (range' (s + 1) n)
- | _, 0 => Chain.nil
- | s, n + 1 => (chain_succ_range' (s + 1) n).cons rfl
#align list.chain_succ_range' List.chain_succ_range'
-
-theorem chain_lt_range' (s n : ℕ) : Chain (· < ·) s (range' (s + 1) n) :=
- (chain_succ_range' s n).imp fun _ _ e => e.symm ▸ lt_succ_self _
#align list.chain_lt_range' List.chain_lt_range'
-theorem pairwise_lt_range' : ∀ s n : ℕ, Pairwise (· < ·) (range' s n)
- | _, 0 => Pairwise.nil
- | s, n + 1 => chain_iff_pairwise.1 (chain_lt_range' s n)
+theorem pairwise_lt_range' : ∀ s n (step := 1) (_ : 0 < step := by simp),
+ Pairwise (· < ·) (range' s n step)
+ | _, 0, _, _ => Pairwise.nil
+ | s, n + 1, _, h => chain_iff_pairwise.1 (chain_lt_range' s n h)
#align list.pairwise_lt_range' List.pairwise_lt_range'
-theorem nodup_range' (s n : ℕ) : Nodup (range' s n) :=
- (pairwise_lt_range' s n).imp _root_.ne_of_lt
+theorem nodup_range' (s n : ℕ) (step := 1) (h : 0 < step := by simp) : Nodup (range' s n step) :=
+ (pairwise_lt_range' s n step h).imp _root_.ne_of_lt
#align list.nodup_range' List.nodup_range'
-
-@[simp]
-theorem range'_append : ∀ s m n : ℕ, range' s m ++ range' (s + m) n = range' s (n + m)
- | s, 0, n => rfl
- | s, m + 1, n =>
- show s :: (range' (s + 1) m ++ range' (s + m + 1) n) = s :: range' (s + 1) (n + m) by
- rw [add_right_comm, range'_append (s + 1) m n]
#align list.range'_append List.range'_append
-
-theorem range'_sublist_right {s m n : ℕ} : range' s m <+ range' s n ↔ m ≤ n :=
- ⟨fun h => by simpa only [length_range'] using h.length_le, fun h => by
- rw [← tsub_add_cancel_of_le h, ← range'_append] ; apply sublist_append_left⟩
#align list.range'_sublist_right List.range'_sublist_right
-
-theorem range'_subset_right {s m n : ℕ} : range' s m ⊆ range' s n ↔ m ≤ n :=
- ⟨fun h =>
- le_of_not_lt fun hn =>
- lt_irrefl (s + n) <|
- (mem_range'.1 <| h <| mem_range'.2 ⟨Nat.le_add_right _ _, Nat.add_lt_add_left hn s⟩).2,
- fun h => (range'_sublist_right.2 h).subset⟩
#align list.range'_subset_right List.range'_subset_right
-
-theorem get?_range' : ∀ (s) {m n : ℕ}, m < n → get? (range' s n) m = some (s + m)
- | s, 0, n + 1, _ => rfl
- | s, m + 1, n + 1, h =>
- (get?_range' (s + 1) (lt_of_add_lt_add_right h)).trans <| by rw [add_right_comm] ; rfl
#align list.nth_range' List.get?_range'
--- Porting note: new theorem
+set_option linter.deprecated false in
@[simp]
-theorem get_range' {n m} (i) (H : i < (range' n m).length) : get (range' n m) ⟨i, H⟩ = n + i :=
- Option.some.inj <| by rw [← get?_eq_get _, get?_range' _ (by simpa using H)]
+theorem nthLe_range' {n m step} (i) (H : i < (range' n m step).length) :
+ nthLe (range' n m step) i H = n + step * i := get_range' i H
set_option linter.deprecated false in
-@[simp]
-theorem nthLe_range' {n m} (i) (H : i < (range' n m).length) : nthLe (range' n m) i H = n + i :=
- get_range' i H
-#align list.nth_le_range' List.nthLe_range'
+theorem nthLe_range'_1 {n m} (i) (H : i < (range' n m).length) :
+ nthLe (range' n m) i H = n + i := by simp
+#align list.nth_le_range' List.nthLe_range'_1
-theorem range'_concat (s n : ℕ) : range' s (n + 1) = range' s n ++ [s + n] := by
- rw [add_comm n 1] ; exact (range'_append s n 1).symm
#align list.range'_concat List.range'_concat
-
#align list.range_core List.range.loop
-
-theorem range_loop_range' : ∀ s n : ℕ, range.loop s (range' s n) = range' 0 (n + s)
- | 0, n => rfl
- | s + 1, n => by
- rw [show n + (s + 1) = n + 1 + s from add_right_comm n s 1]
- exact range_loop_range' s (n + 1)
#align list.range_core_range' List.range_loop_range'
-
-theorem range_eq_range' (n : ℕ) : range n = range' 0 n :=
- (range_loop_range' n 0).trans <| by rw [zero_add]
#align list.range_eq_range' List.range_eq_range'
-
-theorem range_succ_eq_map (n : ℕ) : range (n + 1) = 0 :: map succ (range n) := by
- rw [range_eq_range', range_eq_range', range', add_comm, ← map_add_range']
- congr
- exact funext one_add
#align list.range_succ_eq_map List.range_succ_eq_map
-
-theorem range'_eq_map_range (s n : ℕ) : range' s n = map (s + ·) (range n) := by
- rw [range_eq_range', map_add_range'] ; rfl
#align list.range'_eq_map_range List.range'_eq_map_range
-
-@[simp]
-theorem length_range (n : ℕ) : length (range n) = n := by simp only [range_eq_range', length_range']
#align list.length_range List.length_range
-
-@[simp]
-theorem range_eq_nil {n : ℕ} : range n = [] ↔ n = 0 := by rw [← length_eq_zero, length_range]
#align list.range_eq_nil List.range_eq_nil
theorem pairwise_lt_range (n : ℕ) : Pairwise (· < ·) (range n) := by
@@ -170,41 +84,13 @@ theorem pairwise_le_range (n : ℕ) : Pairwise (· ≤ ·) (range n) :=
theorem nodup_range (n : ℕ) : Nodup (range n) := by simp only [range_eq_range', nodup_range']
#align list.nodup_range List.nodup_range
-
-theorem range_sublist {m n : ℕ} : range m <+ range n ↔ m ≤ n := by
- simp only [range_eq_range', range'_sublist_right]
#align list.range_sublist List.range_sublist
-
-theorem range_subset {m n : ℕ} : range m ⊆ range n ↔ m ≤ n := by
- simp only [range_eq_range', range'_subset_right]
#align list.range_subset List.range_subset
-
-@[simp]
-theorem mem_range {m n : ℕ} : m ∈ range n ↔ m < n := by
- simp only [range_eq_range', mem_range', Nat.zero_le, true_and_iff, zero_add]
#align list.mem_range List.mem_range
-
--- @[simp] -- Porting note: simp can prove this
-theorem not_mem_range_self {n : ℕ} : n ∉ range n :=
- mt mem_range.1 <| lt_irrefl _
#align list.not_mem_range_self List.not_mem_range_self
-
--- @[simp] -- Porting note: simp can prove this
-theorem self_mem_range_succ (n : ℕ) : n ∈ range (n + 1) := by
- simp only [succ_pos', lt_add_iff_pos_right, mem_range]
#align list.self_mem_range_succ List.self_mem_range_succ
-
-theorem get?_range {m n : ℕ} (h : m < n) : get? (range n) m = some m := by
- simp only [range_eq_range', get?_range' _ h, zero_add]
#align list.nth_range List.get?_range
-
-theorem range_succ (n : ℕ) : range (succ n) = range n ++ [n] := by
- simp only [range_eq_range', range'_concat, zero_add]
#align list.range_succ List.range_succ
-
-@[simp]
-theorem range_zero : range 0 = [] :=
- rfl
#align list.range_zero List.range_zero
theorem chain'_range_succ (r : ℕ → ℕ → Prop) (n : ℕ) :
@@ -224,22 +110,8 @@ theorem chain_range_succ (r : ℕ → ℕ → Prop) (n a : ℕ) :
exact fun _ => Iff.rfl
#align list.chain_range_succ List.chain_range_succ
-theorem range_add (a : ℕ) : ∀ b, range (a + b) = range a ++ (range b).map fun x => a + x
- | 0 => by rw [add_zero, range_zero, map_nil, append_nil]
- | b + 1 => by
- rw [Nat.add_succ, range_succ, range_add a b, range_succ, map_append,
- map_singleton, append_assoc]
#align list.range_add List.range_add
-
-theorem iota_eq_reverse_range' : ∀ n : ℕ, iota n = reverse (range' 1 n)
- | 0 => rfl
- | n + 1 => by
- simp only [iota, range'_concat, iota_eq_reverse_range' (n.add 0), reverse_append, add_comm]; rfl
#align list.iota_eq_reverse_range' List.iota_eq_reverse_range'
-
-@[simp]
-theorem length_iota (n : ℕ) : length (iota n) = n := by
- simp only [iota_eq_reverse_range', length_reverse, length_range']
#align list.length_iota List.length_iota
theorem pairwise_gt_iota (n : ℕ) : Pairwise (· > ·) (iota n) := by
@@ -250,17 +122,7 @@ theorem nodup_iota (n : ℕ) : Nodup (iota n) :=
(pairwise_gt_iota n).imp _root_.ne_of_gt
#align list.nodup_iota List.nodup_iota
-theorem mem_iota {m n : ℕ} : m ∈ iota n ↔ 1 ≤ m ∧ m ≤ n := by
- simp only [iota_eq_reverse_range', mem_reverse, mem_range', add_comm, lt_succ_iff]
#align list.mem_iota List.mem_iota
-
-theorem reverse_range' : ∀ s n : ℕ, reverse (range' s n) = map (fun i => s + n - 1 - i) (range n)
- | s, 0 => rfl
- | s, n + 1 => by
- rw [range'_concat, reverse_append, range_succ_eq_map]
- simp only [show s + (n + 1) - 1 = s + n from rfl, (· ∘ ·), fun a i =>
- show a - 1 - i = a - succ i from pred_sub _ _, reverse_singleton, map_cons, tsub_zero,
- cons_append, nil_append, eq_self_iff_true, true_and_iff, map_map, reverse_range' s n]
#align list.reverse_range' List.reverse_range'
/-- All elements of `Fin n`, from `0` to `n-1`. The corresponding finset is `Finset.univ`. -/
@@ -313,15 +175,7 @@ theorem prod_range_succ' {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
#align list.prod_range_succ' List.prod_range_succ'
#align list.sum_range_succ' List.sum_range_succ'
-@[simp]
-theorem enum_from_map_fst : ∀ (n) (l : List α), map Prod.fst (enumFrom n l) = range' n l.length
- | _, [] => rfl
- | _, _ :: _ => congr_arg (cons _) (enum_from_map_fst _ _)
-#align list.enum_from_map_fst List.enum_from_map_fst
-
-@[simp]
-theorem enum_map_fst (l : List α) : map Prod.fst (enum l) = range l.length := by
- simp only [enum, enum_from_map_fst, range_eq_range']
+#align list.enum_from_map_fst List.enumFrom_map_fst
#align list.enum_map_fst List.enum_map_fst
theorem enum_eq_zip_range (l : List α) : l.enum = (range l.length).zip l :=
@@ -333,20 +187,15 @@ theorem unzip_enum_eq_prod (l : List α) : l.enum.unzip = (range l.length, l) :=
simp only [enum_eq_zip_range, unzip_zip, length_range]
#align list.unzip_enum_eq_prod List.unzip_enum_eq_prod
-theorem enum_from_eq_zip_range' (l : List α) {n : ℕ} : l.enumFrom n = (range' n l.length).zip l :=
- zip_of_prod (enum_from_map_fst _ _) (enumFrom_map_snd _ _)
-#align list.enum_from_eq_zip_range' List.enum_from_eq_zip_range'
+theorem enumFrom_eq_zip_range' (l : List α) {n : ℕ} : l.enumFrom n = (range' n l.length).zip l :=
+ zip_of_prod (enumFrom_map_fst _ _) (enumFrom_map_snd _ _)
+#align list.enum_from_eq_zip_range' List.enumFrom_eq_zip_range'
@[simp]
-theorem unzip_enum_from_eq_prod (l : List α) {n : ℕ} :
+theorem unzip_enumFrom_eq_prod (l : List α) {n : ℕ} :
(l.enumFrom n).unzip = (range' n l.length, l) := by
- simp only [enum_from_eq_zip_range', unzip_zip, length_range']
-#align list.unzip_enum_from_eq_prod List.unzip_enum_from_eq_prod
-
--- Porting note: new theorem
-@[simp]
-theorem get_range {n} (i) (H : i < (range n).length) : get (range n) ⟨i, H⟩ = i :=
- Option.some.inj <| by rw [← get?_eq_get _, get?_range (by simpa using H)]
+ simp only [enumFrom_eq_zip_range', unzip_zip, length_range']
+#align list.unzip_enum_from_eq_prod List.unzip_enumFrom_eq_prod
set_option linter.deprecated false in
@[simp]
congr!
and convert
(#2606)
congr!
, convert
, and convert_to
to control parts of the congruence algorithm, in particular transparency settings when applying congruence lemmas.congr!
now applies congruence lemmas with reducible transparency by default. This prevents it from unfolding definitions when applying congruence lemmas. It also now tries both the LHS-biased and RHS-biased simp congruence lemmas, with a configuration option to set which it should try first.HEq
congruence lemma generator that gives each hypothesis access to the proofs of previous hypotheses. This means that if you have an equality ⊢ ⟨a, x⟩ = ⟨b, y⟩
of sigma types, congr!
turns this into goals ⊢ a = b
and ⊢ a = b → HEq x y
(note that congr!
will also auto-introduce a = b
for you in the second goal). This congruence lemma generator applies to more cases than the simp congruence lemma generator does.congr!
(and hence convert
) are more careful about applying lemmas that don't force definitions to unfold. There were a number of cases in mathlib where the implementation of congr
was being abused to unfold definitions.set_option trace.congr! true
you can see what congr!
sees when it is deciding on congruence lemmas.convert_to
to do using 1
when there is no using
clause, to match its documentation.Note that congr!
is more capable than congr
at finding a way to equate left-hand sides and right-hand sides, so you will frequently need to limit its depth with a using
clause. However, there is also a new heuristic to prevent considering unlikely-to-be-provable type equalities (controlled by the typeEqs
option), which can help limit the depth automatically.
There is also a predefined configuration that you can invoke with, for example, convert (config := .unfoldSameFun) h
, that causes it to behave more like congr
, including using default transparency when unfolding.
@@ -64,7 +64,7 @@ theorem map_sub_range' (a) :
∀ (s n : ℕ) (_ : a ≤ s), map (fun x => x - a) (range' s n) = range' (s - a) n
| s, 0, _ => rfl
| s, n + 1, h => by
- convert congr_arg (cons (s - a)) (map_sub_range' _ (s + 1) n (Nat.le_succ_of_le h))
+ convert congr_arg (cons (s - a)) (map_sub_range' _ (s + 1) n (Nat.le_succ_of_le h)) using 1
rw [Nat.succ_sub h]
rfl
#align list.map_sub_range' List.map_sub_range'
@@ -14,12 +14,12 @@ import Mathlib.Data.List.Zip
/-!
# Ranges of naturals as lists
-This file shows basic results about `list.iota`, `list.range`, `list.range'` (all defined in
-`data.list.defs`) and defines `list.fin_range`.
-`fin_range n` is the list of elements of `fin n`.
+This file shows basic results about `List.iota`, `List.range`, `List.range'` (all defined in
+`data.list.defs`) and defines `List.finRange`.
+`finRange n` is the list of elements of `Fin n`.
`iota n = [n, n - 1, ..., 1]` and `range n = [0, ..., n - 1]` are basic list constructions used for
tactics. `range' a b = [a, ..., a + b - 1]` is there to help prove properties about them.
-Actual maths should use `list.Ico` instead.
+Actual maths should use `List.Ico` instead.
-/
@@ -121,9 +121,9 @@ theorem get_range' {n m} (i) (H : i < (range' n m).length) : get (range' n m)
set_option linter.deprecated false in
@[simp]
-theorem nth_le_range' {n m} (i) (H : i < (range' n m).length) : nthLe (range' n m) i H = n + i :=
+theorem nthLe_range' {n m} (i) (H : i < (range' n m).length) : nthLe (range' n m) i H = n + i :=
get_range' i H
-#align list.nth_le_range' List.nth_le_range'
+#align list.nth_le_range' List.nthLe_range'
theorem range'_concat (s n : ℕ) : range' s (n + 1) = range' s n ++ [s + n] := by
rw [add_comm n 1] ; exact (range'_append s n 1).symm
@@ -134,8 +134,8 @@ theorem range'_concat (s n : ℕ) : range' s (n + 1) = range' s n ++ [s + n] :=
theorem range_loop_range' : ∀ s n : ℕ, range.loop s (range' s n) = range' 0 (n + s)
| 0, n => rfl
| s + 1, n => by
- rw [show n + (s + 1) = n + 1 + s from add_right_comm n s 1] ;
- exact range_loop_range' s (n + 1)
+ rw [show n + (s + 1) = n + 1 + s from add_right_comm n s 1]
+ exact range_loop_range' s (n + 1)
#align list.range_core_range' List.range_loop_range'
theorem range_eq_range' (n : ℕ) : range n = range' 0 n :=
@@ -143,11 +143,12 @@ theorem range_eq_range' (n : ℕ) : range n = range' 0 n :=
#align list.range_eq_range' List.range_eq_range'
theorem range_succ_eq_map (n : ℕ) : range (n + 1) = 0 :: map succ (range n) := by
- rw [range_eq_range', range_eq_range', range', add_comm, ← map_add_range'] ; congr ;
- exact funext one_add
+ rw [range_eq_range', range_eq_range', range', add_comm, ← map_add_range']
+ congr
+ exact funext one_add
#align list.range_succ_eq_map List.range_succ_eq_map
-theorem range'_eq_map_range (s n : ℕ) : range' s n = map ((· + ·) s) (range n) := by
+theorem range'_eq_map_range (s n : ℕ) : range' s n = map (s + ·) (range n) := by
rw [range_eq_range', map_add_range'] ; rfl
#align list.range'_eq_map_range List.range'_eq_map_range
@@ -193,9 +194,9 @@ theorem self_mem_range_succ (n : ℕ) : n ∈ range (n + 1) := by
simp only [succ_pos', lt_add_iff_pos_right, mem_range]
#align list.self_mem_range_succ List.self_mem_range_succ
-theorem nth_range {m n : ℕ} (h : m < n) : get? (range n) m = some m := by
+theorem get?_range {m n : ℕ} (h : m < n) : get? (range n) m = some m := by
simp only [range_eq_range', get?_range' _ h, zero_add]
-#align list.nth_range List.nth_range
+#align list.nth_range List.get?_range
theorem range_succ (n : ℕ) : range (succ n) = range n ++ [n] := by
simp only [range_eq_range', range'_concat, zero_add]
@@ -345,7 +346,7 @@ theorem unzip_enum_from_eq_prod (l : List α) {n : ℕ} :
-- Porting note: new theorem
@[simp]
theorem get_range {n} (i) (H : i < (range n).length) : get (range n) ⟨i, H⟩ = i :=
- Option.some.inj <| by rw [← get?_eq_get _, nth_range (by simpa using H)]
+ Option.some.inj <| by rw [← get?_eq_get _, get?_range (by simpa using H)]
set_option linter.deprecated false in
@[simp]
@@ -262,7 +262,7 @@ theorem reverse_range' : ∀ s n : ℕ, reverse (range' s n) = map (fun i => s +
cons_append, nil_append, eq_self_iff_true, true_and_iff, map_map, reverse_range' s n]
#align list.reverse_range' List.reverse_range'
-/-- All elements of `fin n`, from `0` to `n-1`. The corresponding finset is `finset.univ`. -/
+/-- All elements of `Fin n`, from `0` to `n-1`. The corresponding finset is `Finset.univ`. -/
def finRange (n : ℕ) : List (Fin n) :=
(range n).pmap Fin.mk fun _ => List.mem_range.1
#align list.fin_range List.finRange
@@ -299,6 +299,7 @@ theorem prod_range_succ {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
((range n.succ).map f).prod = ((range n).map f).prod * f n := by
rw [range_succ, map_append, map_singleton, prod_append, prod_cons, prod_nil, mul_one]
#align list.prod_range_succ List.prod_range_succ
+#align list.sum_range_succ List.sum_range_succ
/-- A variant of `prod_range_succ` which pulls off the first
term in the product rather than the last.-/
@@ -309,6 +310,7 @@ theorem prod_range_succ' {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
Nat.recOn n (show 1 * f 0 = f 0 * 1 by rw [one_mul, mul_one]) fun _ hd => by
rw [List.prod_range_succ, hd, mul_assoc, ← List.prod_range_succ]
#align list.prod_range_succ' List.prod_range_succ'
+#align list.sum_range_succ' List.sum_range_succ'
@[simp]
theorem enum_from_map_fst : ∀ (n) (l : List α), map Prod.fst (enumFrom n l) = range' n l.length
@@ -136,7 +136,7 @@ theorem range_loop_range' : ∀ s n : ℕ, range.loop s (range' s n) = range' 0
| s + 1, n => by
rw [show n + (s + 1) = n + 1 + s from add_right_comm n s 1] ;
exact range_loop_range' s (n + 1)
-#align list.range_loop_range' List.range_loop_range'
+#align list.range_core_range' List.range_loop_range'
theorem range_eq_range' (n : ℕ) : range n = range' 0 n :=
(range_loop_range' n 0).trans <| by rw [zero_add]
by
line breaks (#1523)
During porting, I usually fix the desired format we seem to want for the line breaks around by
with
awk '{do {{if (match($0, "^ by$") && length(p) < 98) {p=p " by";} else {if (NR!=1) {print p}; p=$0}}} while (getline == 1) if (getline==0) print p}' Mathlib/File/Im/Working/On.lean
I noticed there are some more files that slipped through.
This pull request is the result of running this command:
grep -lr "^ by\$" Mathlib | xargs -n 1 awk -i inplace '{do {{if (match($0, "^ by$") && length(p) < 98 && not (match(p, "^[ \t]*--"))) {p=p " by";} else {if (NR!=1) {print p}; p=$0}}} while (getline == 1) if (getline==0) print p}'
Co-authored-by: Moritz Firsching <firsching@google.com>
@@ -207,8 +207,7 @@ theorem range_zero : range 0 = [] :=
#align list.range_zero List.range_zero
theorem chain'_range_succ (r : ℕ → ℕ → Prop) (n : ℕ) :
- Chain' r (range n.succ) ↔ ∀ m < n, r m m.succ :=
- by
+ Chain' r (range n.succ) ↔ ∀ m < n, r m m.succ := by
rw [range_succ]
induction' n with n hn
· simp
@@ -219,8 +218,7 @@ theorem chain'_range_succ (r : ℕ → ℕ → Prop) (n : ℕ) :
#align list.chain'_range_succ List.chain'_range_succ
theorem chain_range_succ (r : ℕ → ℕ → Prop) (n a : ℕ) :
- Chain r a (range n.succ) ↔ r a 0 ∧ ∀ m < n, r m m.succ :=
- by
+ Chain r a (range n.succ) ↔ r a 0 ∧ ∀ m < n, r m m.succ := by
rw [range_succ_eq_map, chain_cons, and_congr_right_iff, ← chain'_range_succ, range_succ_eq_map]
exact fun _ => Iff.rfl
#align list.chain_range_succ List.chain_range_succ
@@ -359,9 +359,11 @@ theorem get_finRange {n : ℕ} {i : ℕ} (h) :
(finRange n).get ⟨i, h⟩ = ⟨i, length_finRange n ▸ h⟩ := by
simp only [finRange, get_range, get_pmap]
---Porting note: new theorem
+--Porting note: new theorem, corresponding theorem used to be in Data.List.FinRange
+@[simp]
theorem finRange_map_get (l : List α) : (finRange l.length).map l.get = l :=
List.ext_get (by simp) (by simp)
+#align list.map_nth_le List.finRange_map_get
set_option linter.deprecated false in
@[simp]
@@ -359,6 +359,10 @@ theorem get_finRange {n : ℕ} {i : ℕ} (h) :
(finRange n).get ⟨i, h⟩ = ⟨i, length_finRange n ▸ h⟩ := by
simp only [finRange, get_range, get_pmap]
+--Porting note: new theorem
+theorem finRange_map_get (l : List α) : (finRange l.length).map l.get = l :=
+ List.ext_get (by simp) (by simp)
+
set_option linter.deprecated false in
@[simp]
theorem nthLe_finRange {n : ℕ} {i : ℕ} (h) :
@@ -2,76 +2,368 @@
Copyright (c) 2018 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau, Scott Morrison
+
+! This file was ported from Lean 3 source module data.list.range
+! leanprover-community/mathlib commit 7b78d1776212a91ecc94cf601f83bdcc46b04213
+! Please do not edit these lines, except to modify the commit id
+! if you have ported upstream changes.
-/
-import Mathlib.Data.Nat.Basic
-import Mathlib.Data.List.Nodup
-import Mathlib.Order.Basic
-import Mathlib.Data.Fin.Basic
import Mathlib.Data.List.Chain
+import Mathlib.Data.List.Zip
/-!
# Ranges of naturals as lists
-This file shows basic results about `List.iota`, `List.range`, `List.range'` (all defined in
-`Std.Data.List.Basic`) and defines `List.finRange`.
-`finRange n` is the list of elements of `Fin n`.
-`iota n = [1, ..., n]` and `range n = [0, ..., n - 1]` are basic list constructions used for
+This file shows basic results about `list.iota`, `list.range`, `list.range'` (all defined in
+`data.list.defs`) and defines `list.fin_range`.
+`fin_range n` is the list of elements of `fin n`.
+`iota n = [n, n - 1, ..., 1]` and `range n = [0, ..., n - 1]` are basic list constructions used for
tactics. `range' a b = [a, ..., a + b - 1]` is there to help prove properties about them.
-Actual maths should use `List.Ico` instead.
+Actual maths should use `list.Ico` instead.
-/
-namespace List
+
+universe u
open Nat
+namespace List
+
+variable {α : Type u}
+
+@[simp]
+theorem length_range' : ∀ s n : ℕ, length (range' s n) = n
+ | _, 0 => rfl
+ | _, _ + 1 => congr_arg succ (length_range' _ _)
+#align list.length_range' List.length_range'
+
+@[simp]
+theorem range'_eq_nil {s n : ℕ} : range' s n = [] ↔ n = 0 := by rw [← length_eq_zero, length_range']
+#align list.range'_eq_nil List.range'_eq_nil
+
@[simp]
theorem mem_range' {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧ m < s + n
- | s, 0 => by simp
- | s, succ n =>
- have : m = s → m < s + n + 1 := fun e ↦ e ▸ lt_succ_of_le (Nat.le_add_right _ _)
+ | s, 0 => by
+ simp only [range', find?, not_mem_nil, add_zero, false_iff, not_and, not_lt, imp_self]
+ | s, n + 1 =>
+ have : m = s → m < s + n + 1 := fun e => e ▸ lt_succ_of_le (Nat.le_add_right _ _)
have l : m = s ∨ s + 1 ≤ m ↔ s ≤ m := by
simpa only [eq_comm] using (@Decidable.le_iff_eq_or_lt _ _ _ s m).symm
mem_cons.trans <| by
- simp only [mem_range', or_and_left, or_iff_right_of_imp this, l, Nat.add_right_comm]; rfl
+ simp only [@mem_range' m (s + 1) n, or_and_left, or_iff_right_of_imp this, l,
+ add_right_comm, add_eq, add_zero, and_congr_right_iff, add_assoc, or_iff_right_iff_imp]
+ intro; exact this
+#align list.mem_range' List.mem_range'
-theorem range_loop_range' : ∀ s n : ℕ, range.loop s (range' s n) = range' 0 (n + s)
- | 0, n => rfl
- | s + 1, n => by
- rw [show n + (s + 1) = n + 1 + s from Nat.add_right_comm n s 1]
- exact range_loop_range' s (n + 1)
-
-theorem range_eq_range' (n : ℕ) : range n = range' 0 n :=
- (range_loop_range' n 0).trans <| by rw [Nat.zero_add]
+theorem map_add_range' (a) : ∀ s n : ℕ, map ((· + ·) a) (range' s n) = range' (a + s) n
+ | _, 0 => rfl
+ | s, n + 1 => congr_arg (cons _) (map_add_range' _ (s + 1) n)
+#align list.map_add_range' List.map_add_range'
-@[simp]
-theorem mem_range {m n : ℕ} : m ∈ range n ↔ m < n := by
- simp only [range_eq_range', mem_range', Nat.zero_le, true_and, Nat.zero_add]
+theorem map_sub_range' (a) :
+ ∀ (s n : ℕ) (_ : a ≤ s), map (fun x => x - a) (range' s n) = range' (s - a) n
+ | s, 0, _ => rfl
+ | s, n + 1, h => by
+ convert congr_arg (cons (s - a)) (map_sub_range' _ (s + 1) n (Nat.le_succ_of_le h))
+ rw [Nat.succ_sub h]
+ rfl
+#align list.map_sub_range' List.map_sub_range'
-theorem chain_succ_range' : ∀ s n : ℕ, Chain (fun a b ↦ b = succ a) s (range' (s + 1) n)
+theorem chain_succ_range' : ∀ s n : ℕ, Chain (fun a b => b = succ a) s (range' (s + 1) n)
| _, 0 => Chain.nil
| s, n + 1 => (chain_succ_range' (s + 1) n).cons rfl
+#align list.chain_succ_range' List.chain_succ_range'
theorem chain_lt_range' (s n : ℕ) : Chain (· < ·) s (range' (s + 1) n) :=
- (chain_succ_range' s n).imp fun _ _ e ↦ e.symm ▸ lt_succ_self _
+ (chain_succ_range' s n).imp fun _ _ e => e.symm ▸ lt_succ_self _
+#align list.chain_lt_range' List.chain_lt_range'
theorem pairwise_lt_range' : ∀ s n : ℕ, Pairwise (· < ·) (range' s n)
| _, 0 => Pairwise.nil
| s, n + 1 => chain_iff_pairwise.1 (chain_lt_range' s n)
+#align list.pairwise_lt_range' List.pairwise_lt_range'
theorem nodup_range' (s n : ℕ) : Nodup (range' s n) :=
- (pairwise_lt_range' s n).imp Nat.ne_of_lt
+ (pairwise_lt_range' s n).imp _root_.ne_of_lt
+#align list.nodup_range' List.nodup_range'
-theorem nodup_range (n : ℕ) : Nodup (range n) := by
- simp only [range_eq_range', nodup_range']
+@[simp]
+theorem range'_append : ∀ s m n : ℕ, range' s m ++ range' (s + m) n = range' s (n + m)
+ | s, 0, n => rfl
+ | s, m + 1, n =>
+ show s :: (range' (s + 1) m ++ range' (s + m + 1) n) = s :: range' (s + 1) (n + m) by
+ rw [add_right_comm, range'_append (s + 1) m n]
+#align list.range'_append List.range'_append
-/-- All elements of `Fin n`, from `0` to `n-1`. The corresponding finset is `Finset.univ`. -/
-def finRange (n : ℕ) : List (Fin n) := (range n).pmap Fin.mk fun _ ↦ mem_range.1
+theorem range'_sublist_right {s m n : ℕ} : range' s m <+ range' s n ↔ m ≤ n :=
+ ⟨fun h => by simpa only [length_range'] using h.length_le, fun h => by
+ rw [← tsub_add_cancel_of_le h, ← range'_append] ; apply sublist_append_left⟩
+#align list.range'_sublist_right List.range'_sublist_right
-@[simp] theorem fin_range_zero : finRange 0 = [] := rfl
+theorem range'_subset_right {s m n : ℕ} : range' s m ⊆ range' s n ↔ m ≤ n :=
+ ⟨fun h =>
+ le_of_not_lt fun hn =>
+ lt_irrefl (s + n) <|
+ (mem_range'.1 <| h <| mem_range'.2 ⟨Nat.le_add_right _ _, Nat.add_lt_add_left hn s⟩).2,
+ fun h => (range'_sublist_right.2 h).subset⟩
+#align list.range'_subset_right List.range'_subset_right
+
+theorem get?_range' : ∀ (s) {m n : ℕ}, m < n → get? (range' s n) m = some (s + m)
+ | s, 0, n + 1, _ => rfl
+ | s, m + 1, n + 1, h =>
+ (get?_range' (s + 1) (lt_of_add_lt_add_right h)).trans <| by rw [add_right_comm] ; rfl
+#align list.nth_range' List.get?_range'
+
+-- Porting note: new theorem
+@[simp]
+theorem get_range' {n m} (i) (H : i < (range' n m).length) : get (range' n m) ⟨i, H⟩ = n + i :=
+ Option.some.inj <| by rw [← get?_eq_get _, get?_range' _ (by simpa using H)]
+
+set_option linter.deprecated false in
+@[simp]
+theorem nth_le_range' {n m} (i) (H : i < (range' n m).length) : nthLe (range' n m) i H = n + i :=
+ get_range' i H
+#align list.nth_le_range' List.nth_le_range'
+
+theorem range'_concat (s n : ℕ) : range' s (n + 1) = range' s n ++ [s + n] := by
+ rw [add_comm n 1] ; exact (range'_append s n 1).symm
+#align list.range'_concat List.range'_concat
+
+#align list.range_core List.range.loop
+
+theorem range_loop_range' : ∀ s n : ℕ, range.loop s (range' s n) = range' 0 (n + s)
+ | 0, n => rfl
+ | s + 1, n => by
+ rw [show n + (s + 1) = n + 1 + s from add_right_comm n s 1] ;
+ exact range_loop_range' s (n + 1)
+#align list.range_loop_range' List.range_loop_range'
+
+theorem range_eq_range' (n : ℕ) : range n = range' 0 n :=
+ (range_loop_range' n 0).trans <| by rw [zero_add]
+#align list.range_eq_range' List.range_eq_range'
+
+theorem range_succ_eq_map (n : ℕ) : range (n + 1) = 0 :: map succ (range n) := by
+ rw [range_eq_range', range_eq_range', range', add_comm, ← map_add_range'] ; congr ;
+ exact funext one_add
+#align list.range_succ_eq_map List.range_succ_eq_map
+
+theorem range'_eq_map_range (s n : ℕ) : range' s n = map ((· + ·) s) (range n) := by
+ rw [range_eq_range', map_add_range'] ; rfl
+#align list.range'_eq_map_range List.range'_eq_map_range
+
+@[simp]
+theorem length_range (n : ℕ) : length (range n) = n := by simp only [range_eq_range', length_range']
+#align list.length_range List.length_range
+
+@[simp]
+theorem range_eq_nil {n : ℕ} : range n = [] ↔ n = 0 := by rw [← length_eq_zero, length_range]
+#align list.range_eq_nil List.range_eq_nil
+
+theorem pairwise_lt_range (n : ℕ) : Pairwise (· < ·) (range n) := by
+ simp only [range_eq_range', pairwise_lt_range']
+#align list.pairwise_lt_range List.pairwise_lt_range
+
+theorem pairwise_le_range (n : ℕ) : Pairwise (· ≤ ·) (range n) :=
+ Pairwise.imp (@le_of_lt ℕ _) (pairwise_lt_range _)
+#align list.pairwise_le_range List.pairwise_le_range
+
+theorem nodup_range (n : ℕ) : Nodup (range n) := by simp only [range_eq_range', nodup_range']
+#align list.nodup_range List.nodup_range
+
+theorem range_sublist {m n : ℕ} : range m <+ range n ↔ m ≤ n := by
+ simp only [range_eq_range', range'_sublist_right]
+#align list.range_sublist List.range_sublist
+
+theorem range_subset {m n : ℕ} : range m ⊆ range n ↔ m ≤ n := by
+ simp only [range_eq_range', range'_subset_right]
+#align list.range_subset List.range_subset
+
+@[simp]
+theorem mem_range {m n : ℕ} : m ∈ range n ↔ m < n := by
+ simp only [range_eq_range', mem_range', Nat.zero_le, true_and_iff, zero_add]
+#align list.mem_range List.mem_range
+
+-- @[simp] -- Porting note: simp can prove this
+theorem not_mem_range_self {n : ℕ} : n ∉ range n :=
+ mt mem_range.1 <| lt_irrefl _
+#align list.not_mem_range_self List.not_mem_range_self
+
+-- @[simp] -- Porting note: simp can prove this
+theorem self_mem_range_succ (n : ℕ) : n ∈ range (n + 1) := by
+ simp only [succ_pos', lt_add_iff_pos_right, mem_range]
+#align list.self_mem_range_succ List.self_mem_range_succ
+
+theorem nth_range {m n : ℕ} (h : m < n) : get? (range n) m = some m := by
+ simp only [range_eq_range', get?_range' _ h, zero_add]
+#align list.nth_range List.nth_range
+
+theorem range_succ (n : ℕ) : range (succ n) = range n ++ [n] := by
+ simp only [range_eq_range', range'_concat, zero_add]
+#align list.range_succ List.range_succ
+
+@[simp]
+theorem range_zero : range 0 = [] :=
+ rfl
+#align list.range_zero List.range_zero
+
+theorem chain'_range_succ (r : ℕ → ℕ → Prop) (n : ℕ) :
+ Chain' r (range n.succ) ↔ ∀ m < n, r m m.succ :=
+ by
+ rw [range_succ]
+ induction' n with n hn
+ · simp
+ · rw [range_succ]
+ simp only [append_assoc, singleton_append, chain'_append_cons_cons, chain'_singleton,
+ and_true_iff]
+ rw [hn, forall_lt_succ]
+#align list.chain'_range_succ List.chain'_range_succ
+
+theorem chain_range_succ (r : ℕ → ℕ → Prop) (n a : ℕ) :
+ Chain r a (range n.succ) ↔ r a 0 ∧ ∀ m < n, r m m.succ :=
+ by
+ rw [range_succ_eq_map, chain_cons, and_congr_right_iff, ← chain'_range_succ, range_succ_eq_map]
+ exact fun _ => Iff.rfl
+#align list.chain_range_succ List.chain_range_succ
+
+theorem range_add (a : ℕ) : ∀ b, range (a + b) = range a ++ (range b).map fun x => a + x
+ | 0 => by rw [add_zero, range_zero, map_nil, append_nil]
+ | b + 1 => by
+ rw [Nat.add_succ, range_succ, range_add a b, range_succ, map_append,
+ map_singleton, append_assoc]
+#align list.range_add List.range_add
+
+theorem iota_eq_reverse_range' : ∀ n : ℕ, iota n = reverse (range' 1 n)
+ | 0 => rfl
+ | n + 1 => by
+ simp only [iota, range'_concat, iota_eq_reverse_range' (n.add 0), reverse_append, add_comm]; rfl
+#align list.iota_eq_reverse_range' List.iota_eq_reverse_range'
+
+@[simp]
+theorem length_iota (n : ℕ) : length (iota n) = n := by
+ simp only [iota_eq_reverse_range', length_reverse, length_range']
+#align list.length_iota List.length_iota
+
+theorem pairwise_gt_iota (n : ℕ) : Pairwise (· > ·) (iota n) := by
+ simpa only [iota_eq_reverse_range', pairwise_reverse] using pairwise_lt_range' 1 n
+#align list.pairwise_gt_iota List.pairwise_gt_iota
+
+theorem nodup_iota (n : ℕ) : Nodup (iota n) :=
+ (pairwise_gt_iota n).imp _root_.ne_of_gt
+#align list.nodup_iota List.nodup_iota
+
+theorem mem_iota {m n : ℕ} : m ∈ iota n ↔ 1 ≤ m ∧ m ≤ n := by
+ simp only [iota_eq_reverse_range', mem_reverse, mem_range', add_comm, lt_succ_iff]
+#align list.mem_iota List.mem_iota
+
+theorem reverse_range' : ∀ s n : ℕ, reverse (range' s n) = map (fun i => s + n - 1 - i) (range n)
+ | s, 0 => rfl
+ | s, n + 1 => by
+ rw [range'_concat, reverse_append, range_succ_eq_map]
+ simp only [show s + (n + 1) - 1 = s + n from rfl, (· ∘ ·), fun a i =>
+ show a - 1 - i = a - succ i from pred_sub _ _, reverse_singleton, map_cons, tsub_zero,
+ cons_append, nil_append, eq_self_iff_true, true_and_iff, map_map, reverse_range' s n]
+#align list.reverse_range' List.reverse_range'
+
+/-- All elements of `fin n`, from `0` to `n-1`. The corresponding finset is `finset.univ`. -/
+def finRange (n : ℕ) : List (Fin n) :=
+ (range n).pmap Fin.mk fun _ => List.mem_range.1
+#align list.fin_range List.finRange
+
+@[simp]
+theorem finRange_zero : finRange 0 = [] :=
+ rfl
+#align list.fin_range_zero List.finRange_zero
+
+@[simp]
+theorem mem_finRange {n : ℕ} (a : Fin n) : a ∈ finRange n :=
+ mem_pmap.2
+ ⟨a.1, mem_range.2 a.2, by
+ cases a
+ rfl⟩
+#align list.mem_fin_range List.mem_finRange
+
+theorem nodup_finRange (n : ℕ) : (finRange n).Nodup :=
+ (Pairwise.pmap (nodup_range n) _) fun _ _ _ _ => @Fin.ne_of_vne _ ⟨_, _⟩ ⟨_, _⟩
+#align list.nodup_fin_range List.nodup_finRange
+
+@[simp]
+theorem length_finRange (n : ℕ) : (finRange n).length = n := by
+ rw [finRange, length_pmap, length_range]
+#align list.length_fin_range List.length_finRange
+
+@[simp]
+theorem finRange_eq_nil {n : ℕ} : finRange n = [] ↔ n = 0 := by
+ rw [← length_eq_zero, length_finRange]
+#align list.fin_range_eq_nil List.finRange_eq_nil
+
+@[to_additive]
+theorem prod_range_succ {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
+ ((range n.succ).map f).prod = ((range n).map f).prod * f n := by
+ rw [range_succ, map_append, map_singleton, prod_append, prod_cons, prod_nil, mul_one]
+#align list.prod_range_succ List.prod_range_succ
+
+/-- A variant of `prod_range_succ` which pulls off the first
+ term in the product rather than the last.-/
+@[to_additive
+ "A variant of `sum_range_succ` which pulls off the first term in the sum rather than the last."]
+theorem prod_range_succ' {α : Type u} [Monoid α] (f : ℕ → α) (n : ℕ) :
+ ((range n.succ).map f).prod = f 0 * ((range n).map fun i => f (succ i)).prod :=
+ Nat.recOn n (show 1 * f 0 = f 0 * 1 by rw [one_mul, mul_one]) fun _ hd => by
+ rw [List.prod_range_succ, hd, mul_assoc, ← List.prod_range_succ]
+#align list.prod_range_succ' List.prod_range_succ'
+
+@[simp]
+theorem enum_from_map_fst : ∀ (n) (l : List α), map Prod.fst (enumFrom n l) = range' n l.length
+ | _, [] => rfl
+ | _, _ :: _ => congr_arg (cons _) (enum_from_map_fst _ _)
+#align list.enum_from_map_fst List.enum_from_map_fst
+
+@[simp]
+theorem enum_map_fst (l : List α) : map Prod.fst (enum l) = range l.length := by
+ simp only [enum, enum_from_map_fst, range_eq_range']
+#align list.enum_map_fst List.enum_map_fst
+
+theorem enum_eq_zip_range (l : List α) : l.enum = (range l.length).zip l :=
+ zip_of_prod (enum_map_fst _) (enum_map_snd _)
+#align list.enum_eq_zip_range List.enum_eq_zip_range
+
+@[simp]
+theorem unzip_enum_eq_prod (l : List α) : l.enum.unzip = (range l.length, l) := by
+ simp only [enum_eq_zip_range, unzip_zip, length_range]
+#align list.unzip_enum_eq_prod List.unzip_enum_eq_prod
+
+theorem enum_from_eq_zip_range' (l : List α) {n : ℕ} : l.enumFrom n = (range' n l.length).zip l :=
+ zip_of_prod (enum_from_map_fst _ _) (enumFrom_map_snd _ _)
+#align list.enum_from_eq_zip_range' List.enum_from_eq_zip_range'
+
+@[simp]
+theorem unzip_enum_from_eq_prod (l : List α) {n : ℕ} :
+ (l.enumFrom n).unzip = (range' n l.length, l) := by
+ simp only [enum_from_eq_zip_range', unzip_zip, length_range']
+#align list.unzip_enum_from_eq_prod List.unzip_enum_from_eq_prod
+
+-- Porting note: new theorem
+@[simp]
+theorem get_range {n} (i) (H : i < (range n).length) : get (range n) ⟨i, H⟩ = i :=
+ Option.some.inj <| by rw [← get?_eq_get _, nth_range (by simpa using H)]
+
+set_option linter.deprecated false in
+@[simp]
+theorem nthLe_range {n} (i) (H : i < (range n).length) : nthLe (range n) i H = i :=
+ get_range i H
+#align list.nth_le_range List.nthLe_range
+
+-- Porting note: new theorem
+@[simp]
+theorem get_finRange {n : ℕ} {i : ℕ} (h) :
+ (finRange n).get ⟨i, h⟩ = ⟨i, length_finRange n ▸ h⟩ := by
+ simp only [finRange, get_range, get_pmap]
+set_option linter.deprecated false in
@[simp]
-theorem mem_fin_range {n : ℕ} (a : Fin n) : a ∈ finRange n :=
- mem_pmap.2 ⟨a.1, mem_range.2 a.2, Fin.eta _ _⟩
+theorem nthLe_finRange {n : ℕ} {i : ℕ} (h) :
+ (finRange n).nthLe i h = ⟨i, length_finRange n ▸ h⟩ :=
+ get_finRange h
+#align list.nth_le_fin_range List.nthLe_finRange
-theorem nodup_fin_range (n : ℕ) : (finRange n).Nodup :=
- (nodup_range _).pmap fun _ _ _ _ ↦ Fin.val_eq_of_eq
+end List
The unported dependencies are