From e95721ad084c0d7db9356aa779405ea214e10d1f Mon Sep 17 00:00:00 2001 From: Dan Ehrenberg Date: Fri, 11 Jul 2008 09:42:16 -0700 Subject: [PATCH] Persistent heaps --- extra/persistent-heaps/authors.txt | 1 + .../persistent-heaps-tests.factor | 11 ++ .../persistent-heaps/persistent-heaps.factor | 102 ++++++++++++++++++ extra/persistent-heaps/summary.txt | 1 + extra/persistent-heaps/tags.txt | 1 + 5 files changed, 116 insertions(+) create mode 100644 extra/persistent-heaps/authors.txt create mode 100644 extra/persistent-heaps/persistent-heaps-tests.factor create mode 100644 extra/persistent-heaps/persistent-heaps.factor create mode 100644 extra/persistent-heaps/summary.txt create mode 100644 extra/persistent-heaps/tags.txt diff --git a/extra/persistent-heaps/authors.txt b/extra/persistent-heaps/authors.txt new file mode 100644 index 0000000000..f990dd0ed2 --- /dev/null +++ b/extra/persistent-heaps/authors.txt @@ -0,0 +1 @@ +Daniel Ehrenberg diff --git a/extra/persistent-heaps/persistent-heaps-tests.factor b/extra/persistent-heaps/persistent-heaps-tests.factor new file mode 100644 index 0000000000..6e559971a0 --- /dev/null +++ b/extra/persistent-heaps/persistent-heaps-tests.factor @@ -0,0 +1,11 @@ +USING: persistent-heaps tools.test ; +IN: persistent-heaps.tests + +: test-input + { { "hello" 3 } { "goodbye" 2 } { "whatever" 5 } + { "foo" 1 } { "bar" -1 } { "baz" -7 } { "bing" 0 } } ; + +[ + { { "baz" -7 } { "bar" -1 } { "bing" 0 } { "foo" 1 } + { "goodbye" 2 } { "hello" 3 } { "whatever" 5 } } +] [ test-input assoc>pheap pheap>alist ] unit-test diff --git a/extra/persistent-heaps/persistent-heaps.factor b/extra/persistent-heaps/persistent-heaps.factor new file mode 100644 index 0000000000..5b57898da0 --- /dev/null +++ b/extra/persistent-heaps/persistent-heaps.factor @@ -0,0 +1,102 @@ +USING: kernel accessors multi-methods locals combinators math arrays +assocs namespaces sequences ; +IN: persistent-heaps +! These are minheaps + +> ] [ right>> ] bi [ empty-heap? ] both? ; + +C: branch +: >branch< ( branch -- value prio left right ) + { [ value>> ] [ prio>> ] [ left>> ] [ right>> ] } cleave ; +PRIVATE> + +: ( -- heap ) T{ empty-heap } ; + +: ( value prio -- heap ) + ; + +: pheap-empty? ( heap -- ? ) empty-heap? ; + +: empty-pheap ( -- * ) + "Attempt to delete from an empty heap" throw ; + +> ] [ right>> ] bi [ pheap-empty? ] both? + [ [ value>> ] [ prio>> ] bi ] + [ >branch< swap remove-left -rot [ ] 2dip rot ] if ; + +: both-with? ( obj a b quot -- ? ) + swap >r with r> swap both? ; inline + +GENERIC: sift-down ( value prio left right -- heap ) + +METHOD: sift-down { empty-heap empty-heap } ; + +METHOD: sift-down { singleton-heap empty-heap } + 3dup drop prio>> <= [ ] [ + drop -rot [ [ value>> ] [ prio>> ] bi ] 2dip + + ] if ; + +:: reroot-left ( value prio left right -- heap ) + left value>> left prio>> + value prio left left>> left right>> sift-down + right ; + +:: reroot-right ( value prio left right -- heap ) + right value>> right prio>> left + value prio right left>> right right>> sift-down + ; + +METHOD: sift-down { branch branch } + 3dup [ prio>> <= ] both-with? [ ] [ + 2dup [ prio>> ] bi@ <= [ reroot-left ] [ reroot-right ] if + ] if ; +PRIVATE> + +GENERIC: pheap-peek ( heap -- value prio ) +M: empty-heap pheap-peek empty-pheap ; +M: branch pheap-peek [ value>> ] [ prio>> ] bi ; + +GENERIC: pheap-push ( value prio heap -- newheap ) + +M: empty-heap pheap-push + drop ; + +> ] [ prio>> ] [ right>> ] tri pheap-push ] + [ left>> ] bi ; + +: push-in ( value prio heap -- newheap ) + [ 2nip [ value>> ] [ prio>> ] bi ] + [ right>> pheap-push ] + [ 2nip left>> ] 3tri ; +PRIVATE> + +M: branch pheap-push + 2dup prio>> <= [ push-top ] [ push-in ] if ; + +: pheap-pop* ( heap -- newheap ) + dup pheap-empty? [ empty-pheap ] [ + dup left>> pheap-empty? + [ drop ] + [ [ left>> remove-left ] keep right>> swap sift-down ] if + ] if ; + +: pheap-pop ( heap -- newheap value prio ) + [ pheap-pop* ] [ pheap-peek ] bi ; + +: assoc>pheap ( assoc -- heap ) ! Assoc is value => prio + swap [ rot pheap-push ] assoc-each ; + +: pheap>alist ( heap -- alist ) + [ dup pheap-empty? not ] [ pheap-pop 2array ] [ ] produce nip ; + +: pheap>values ( heap -- seq ) pheap>alist keys ; diff --git a/extra/persistent-heaps/summary.txt b/extra/persistent-heaps/summary.txt new file mode 100644 index 0000000000..1451439c65 --- /dev/null +++ b/extra/persistent-heaps/summary.txt @@ -0,0 +1 @@ +Datastructure for functional peristent heaps, from ML for the Working Programmer diff --git a/extra/persistent-heaps/tags.txt b/extra/persistent-heaps/tags.txt new file mode 100644 index 0000000000..42d711b32b --- /dev/null +++ b/extra/persistent-heaps/tags.txt @@ -0,0 +1 @@ +collections