Add permutations and LazyList.length to Util

This commit is contained in:
Nathan McCarty 2025-01-28 09:48:11 -05:00
parent c632ab023d
commit ac93582e96

View file

@ -10,6 +10,7 @@ import Data.SortedSet
import Data.String import Data.String
import Data.List.Lazy import Data.List.Lazy
import Data.List1 import Data.List1
import Data.Vect
%default total %default total
``` ```
@ -88,6 +89,54 @@ rotations xs = rotations' (length xs) xs []
in rotations' k next (next :: acc) in rotations' k next (next :: acc)
``` ```
### permutations
Lazily generate all of the permutations of a list
```idris
export
permutations : List a -> LazyList (List a)
permutations [] = pure []
permutations xs = do
(head, tail) <- select xs
tail <- permutations (assert_smaller xs tail)
pure $ head :: tail
where
consSnd : a -> (a, List a) -> (a, List a)
consSnd x (y, xs) = (y, x :: xs)
select : List a -> LazyList (a, List a)
select [] = []
select (x :: xs) = (x, xs) :: map (consSnd x) (select xs)
```
## Vect
```idris hide
namespace Vect
```
### permutations
Lazily generate all the permutations of a Vect
```idris
export
permutations : Vect n a -> LazyList (Vect n a)
permutations [] = []
permutations [x] = [[x]]
permutations (x :: xs) = do
(head, tail) <- select (x :: xs)
tail <- permutations tail
pure $ head :: tail
where
consSnd : a -> (a, Vect m a) -> (a, Vect (S m) a)
consSnd x (y, xs) = (y, x :: xs)
select : Vect (S m) a -> LazyList (a, Vect m a)
select [y] = [(y, [])]
select (y :: (z :: ys)) =
(y, z :: ys) :: map (consSnd y) (select (z :: ys))
```
## Vectors ## Vectors
Define some operations for pairs of numbers, treating them roughly like vectors Define some operations for pairs of numbers, treating them roughly like vectors
@ -166,6 +215,10 @@ off of the string at a time, checking if the needle is a prefix at each step.
### Cartesian product ### Cartesian product
```idris hide
namespace LazyList
```
Lazily take the cartesian product of two foldables Lazily take the cartesian product of two foldables
```idris ```idris
@ -203,10 +256,25 @@ lazyGroup : Eq a => LazyList a -> LazyList (List1 a)
lazyGroup [] = [] lazyGroup [] = []
lazyGroup (x :: xs) = lazyGroup' xs x (x ::: []) lazyGroup (x :: xs) = lazyGroup' xs x (x ::: [])
where where
lazyGroup' : LazyList a -> (current : a) -> (acc : List1 a) -> LazyList (List1 a) lazyGroup' : LazyList a -> (current : a) -> (acc : List1 a)
-> LazyList (List1 a)
lazyGroup' [] current acc = [acc] lazyGroup' [] current acc = [acc]
lazyGroup' (y :: ys) current acc@(head ::: tail) = lazyGroup' (y :: ys) current acc@(head ::: tail) =
if y == current if y == current
then lazyGroup' ys current (head ::: (y :: tail)) then lazyGroup' ys current (head ::: (y :: tail))
else acc :: lazyGroup (y :: ys) else acc :: lazyGroup (y :: ys)
``` ```
### length
Calculate the length of a LazyList
```idris
export
length : LazyList a -> Nat
length = length' 0
where
length' : Nat -> LazyList a -> Nat
length' k [] = k
length' k (x :: xs) = length' (S k) xs
```