Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e7e85af
Updates
linesthatinterlace Nov 6, 2025
cc57a71
Add lemmas + constructs
linesthatinterlace Nov 7, 2025
7d48957
Fix lint
linesthatinterlace Nov 7, 2025
d62488a
Small improvements
linesthatinterlace Nov 10, 2025
7add6c7
Small update
linesthatinterlace Nov 10, 2025
6b78148
Add in start type
linesthatinterlace Nov 10, 2025
4335bb1
Remove count changes
linesthatinterlace Nov 10, 2025
e3dc7ad
Act on feedback
linesthatinterlace Nov 10, 2025
2d221bf
Golf
linesthatinterlace Nov 10, 2025
5812382
Add const lemma
linesthatinterlace Nov 10, 2025
e3be298
Add unzip lemma
linesthatinterlace Nov 10, 2025
5408ec9
Remove variable
linesthatinterlace Nov 10, 2025
656398e
Fiddle with imports
linesthatinterlace Nov 10, 2025
69c3254
Change name
linesthatinterlace Nov 10, 2025
5a3766c
Merge branch 'main' into idxsOf
linesthatinterlace Nov 10, 2025
99ac39e
Fix merge error
linesthatinterlace Nov 10, 2025
c8c0c18
Merge branch 'main' into idxsOf
fgdorais Nov 11, 2025
4c094e6
Fix build
linesthatinterlace Nov 11, 2025
5443aa8
Change
linesthatinterlace Nov 12, 2025
41ebe33
Merge branch 'main' into idxsOf
linesthatinterlace Nov 17, 2025
b68a38a
Redefine foldrIdxTR
linesthatinterlace Nov 17, 2025
89492e6
Add filterMap lemmas
linesthatinterlace Nov 17, 2025
dfa249f
Merge branch 'main' into idxsOf
linesthatinterlace Nov 18, 2025
95b4919
Merge branch 'main' into idxsOf
linesthatinterlace Nov 19, 2025
afb58e2
Merge branch 'main' into idxsOf
linesthatinterlace Nov 24, 2025
aa0d0bc
Make changes
linesthatinterlace Nov 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 37 additions & 18 deletions Batteries/Data/List/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Authors: Leonardo de Moura
-/

module
import Batteries.Tactic.Alias
public import Batteries.Tactic.Alias

@[expose] public section

Expand Down Expand Up @@ -219,43 +219,62 @@ def scanr (f : α → β → β) (b : β) (l : List α) : List β :=

/--
Fold a list from left to right as with `foldl`, but the combining function
also receives each element's index.
also receives each element's index added to an optional parameter `start`
(i.e. the numbers that `f` takes as its first argument will be greater than or equal to `start` and
less than `start + l.length`).
-/
@[simp, specialize] def foldlIdx (f : Nat → α → β → α) (init : α) : List β → (start : _ := 0) → α
@[specialize] def foldlIdx (f : Nat → α → β → α) (init : α) : List β → (start : Nat := 0) → α
| [], _ => init
| b :: l, i => foldlIdx f (f i init b) l (i+1)
| b :: l, s => foldlIdx f (f s init b) l (s + 1)

/--
Fold a list from right to left as with `foldr`, but the combining function
also receives each element's index.
also receives each element's index added to an optional parameter `start`
(i.e. the numbers that `f` takes as its first argument will be greater than or equal to `start` and
less than `start + l.length`).
-/
-- TODO(Mario): tail recursive / array-based implementation
@[simp, specialize] def foldrIdx (f : Nat → α → β → β) (init : β) :
(l : List α) → (start : _ := 0) → β
def foldrIdx {α : Type u} {β : Type v} (f : Nat → α → β → β) (init : β) :
(l : List α) → (start : Nat := 0) → β
| [], _ => init
| a :: l, i => f i a (foldrIdx f init l (i+1))
| a :: l, s => f s a (foldrIdx f init l (s + 1))

/-- `findIdxs p l` is the list of indexes of elements of `l` that satisfy `p`. -/
@[inline] def findIdxs (p : α → Bool) (l : List α) : List Nat :=
foldrIdx (fun i a is => if p a then i :: is else is) [] l
/-- A tail-recursive version of `foldrIdx`. -/
@[inline] def foldrIdxTR (f : Nat → α → β → β) (init : β) (l : List α) (start : Nat := 0) : β :=
l.foldr (fun a (acc, n) => (f (n - 1) a acc, n - 1)) (init, start + l.length) |>.1

@[csimp] theorem foldrIdx_eq_foldrIdxTR : @foldrIdx = @foldrIdxTR := by
funext _ _ f
have go i xs s : xs.foldr (fun a xa => (f (xa.2 - 1) a xa.1, xa.2 - 1)) (i, s + xs.length) =
(foldrIdx f i xs s, s) := by induction xs generalizing s <;> grind [foldrIdx]
grind [foldrIdxTR]

/-- `findIdxs p l` is the list of indexes of elements of `l` that satisfy `p`, added to an
optional parameter `start` (so that the members of `findIdxs p l` will be greater than or
equal to `start` and less than `l.length + start`). -/
@[inline] def findIdxs (p : α → Bool) (l : List α) (start : Nat := 0) : List Nat :=
foldrIdx (fun i a is => bif p a then i :: is else is) [] l start

/--
Returns the elements of `l` that satisfy `p` together with their indexes in
`l`. The returned list is ordered by index.
`l` added to an optional parameter `start`. The returned list is ordered by index.
We have `l.findIdxsValues p s = (l.findIdxs p s).zip (l.filter p)`.
-/
@[inline] def findIdxsValues (p : α → Bool) (l : List α) : List (Nat × α) :=
foldrIdx (fun i a l => if p a then (i, a) :: l else l) [] l
@[inline] def findIdxsValues (p : α → Bool) (l : List α) (start : Nat := 0) : List (Nat × α) :=
foldrIdx (fun i a l => if p a then (i, a) :: l else l) [] l start

@[deprecated (since := "2025-11-06")]
alias indexsValues := findIdxsValues

/--
`idxsOf a l` is the list of all indexes of `a` in `l`. For example:
`idxsOf a l` is the list of all indexes of `a` in `l`, added to an
optional parameter `start`. For example:
```
idxsOf a [a, b, a, a] = [0, 2, 3]
idxsOf b [a, b, a, a] = [1]
idxsOf a [a, b, a, a] 5 = [5, 7, 8]
```
-/
@[inline] def idxsOf [BEq α] (a : α) : List α → List Nat := findIdxs (· == a)
@[inline] def idxsOf [BEq α] (a : α) (xs : List α) (start : Nat := 0) : List Nat :=
xs.findIdxs (· == a) start

@[deprecated (since := "2025-11-06")]
alias indexesOf := idxsOf
Expand Down
Loading
Loading