feat(library/init/data/persistentarray/basic): PersistentArray.pop
This commit is contained in:
parent
4181f35546
commit
4bd347de3a
2 changed files with 66 additions and 1 deletions
|
|
@ -131,6 +131,49 @@ if r.tail.size < branching.toNat || t.size >= tooBig then
|
||||||
else
|
else
|
||||||
mkNewTail r
|
mkNewTail r
|
||||||
|
|
||||||
|
private def emptyArray {α : Type u} : Array (PersistentArrayNode α) :=
|
||||||
|
Array.mkEmpty PersistentArray.branching.toNat
|
||||||
|
|
||||||
|
partial def popLeaf : PersistentArrayNode α → Option (Array α) × Array (PersistentArrayNode α)
|
||||||
|
| n@(node cs) :=
|
||||||
|
if h : cs.size ≠ 0 then
|
||||||
|
let idx : Fin cs.size := ⟨cs.size - 1, Nat.predLt h⟩;
|
||||||
|
let last := cs.fget idx;
|
||||||
|
match popLeaf last with
|
||||||
|
| (none, _) => (none, emptyArray)
|
||||||
|
| (some l, newLast) =>
|
||||||
|
if newLast.size == 0 then
|
||||||
|
let cs := cs.pop;
|
||||||
|
if cs.isEmpty then (some l, emptyArray) else (some l, cs)
|
||||||
|
else
|
||||||
|
(some l, cs.fset idx (node newLast))
|
||||||
|
else
|
||||||
|
(none, emptyArray)
|
||||||
|
| (leaf vs) := (some vs, emptyArray)
|
||||||
|
|
||||||
|
def pop (t : PersistentArray α) : PersistentArray α :=
|
||||||
|
if t.tail.size > 0 then
|
||||||
|
{ tail := t.tail.pop, size := t.size - 1, .. t }
|
||||||
|
else
|
||||||
|
match popLeaf t.root with
|
||||||
|
| (none, _) => t
|
||||||
|
| (some last, newRoots) =>
|
||||||
|
let last := last.pop;
|
||||||
|
let newSize := t.size - 1;
|
||||||
|
let newTailOff := newSize - last.size;
|
||||||
|
if newRoots.size == 1 then
|
||||||
|
{ root := newRoots.get 0,
|
||||||
|
shift := t.shift - initShift,
|
||||||
|
size := newSize,
|
||||||
|
tail := last,
|
||||||
|
tailOff := newTailOff }
|
||||||
|
else
|
||||||
|
{ root := node newRoots,
|
||||||
|
size := newSize,
|
||||||
|
tail := last,
|
||||||
|
tailOff := newTailOff,
|
||||||
|
.. t }
|
||||||
|
|
||||||
section
|
section
|
||||||
variables {m : Type u → Type v} [Monad m]
|
variables {m : Type u → Type v} [Monad m]
|
||||||
variable {β: Type u}
|
variable {β: Type u}
|
||||||
|
|
@ -183,7 +226,7 @@ def stats (r : PersistentArray α) : Stats :=
|
||||||
collectStats r.root { numNodes := 0, depth := 0, tailSize := r.tail.size } 0
|
collectStats r.root { numNodes := 0, depth := 0, tailSize := r.tail.size } 0
|
||||||
|
|
||||||
def Stats.toString (s : Stats) : String :=
|
def Stats.toString (s : Stats) : String :=
|
||||||
toString [s.numNodes, s.depth, s.tailSize]
|
"{nodes := " ++ toString s.numNodes ++ ", depth := " ++ toString s.depth ++ ", tail size := " ++ toString s.tailSize ++ "}"
|
||||||
|
|
||||||
instance : HasToString Stats := ⟨Stats.toString⟩
|
instance : HasToString Stats := ⟨Stats.toString⟩
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,17 @@ n.fold (λ i s => s.set i (s.get i + 1)) s
|
||||||
def checkId (n : Nat) (s : MyArray) : IO Unit :=
|
def checkId (n : Nat) (s : MyArray) : IO Unit :=
|
||||||
check n (fun a b => a == b) s
|
check n (fun a b => a == b) s
|
||||||
|
|
||||||
|
def popTest (n : Nat) (p : Nat → Nat → Bool) (s : MyArray) : IO MyArray :=
|
||||||
|
n.mfold (λ i s => do
|
||||||
|
-- IO.println i;
|
||||||
|
check (n - i) p s;
|
||||||
|
let s := s.pop;
|
||||||
|
-- IO.println s.stats;
|
||||||
|
-- IO.println ("size: " ++ toString s.size ++ ", tailOff " ++ toString s.tailOff ++ ", shift: " ++ toString s.shift);
|
||||||
|
-- IO.println s.tail;
|
||||||
|
pure s)
|
||||||
|
s
|
||||||
|
|
||||||
def main (xs : List String) : IO Unit :=
|
def main (xs : List String) : IO Unit :=
|
||||||
do
|
do
|
||||||
let n := xs.head.toNat;
|
let n := xs.head.toNat;
|
||||||
|
|
@ -25,4 +36,15 @@ let t := inc1 n t;
|
||||||
check n (λ i v => v == i + 1) t;
|
check n (λ i v => v == i + 1) t;
|
||||||
IO.println t.size;
|
IO.println t.size;
|
||||||
IO.println t.stats;
|
IO.println t.stats;
|
||||||
|
IO.println "popping...";
|
||||||
|
t ← popTest (n - 33) (λ i v => v == i + 1) t;
|
||||||
|
IO.println t.size;
|
||||||
|
check 33 (λ i v => v == i + 1) t;
|
||||||
|
let t : MyArray := (1000 : Nat).fold (fun i s => s.push i) t;
|
||||||
|
check t.size (λ i v => if i < 33 then v == i + 1 else v == i - 33) t;
|
||||||
|
IO.println t.size;
|
||||||
|
IO.println t.stats;
|
||||||
|
t ← popTest t.size (λ i v => if i < 33 then v == i + 1 else v == i - 33) t;
|
||||||
|
IO.println t.size;
|
||||||
|
IO.println t.stats;
|
||||||
pure ()
|
pure ()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue