| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | ! Copyright (C) 2007 Alex Chapman | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  | USING: accessors arrays assocs combinators | 
					
						
							| 
									
										
										
										
											2017-01-25 13:26:22 -05:00
										 |  |  | combinators.short-circuit deques dlists kernel locals make math | 
					
						
							|  |  |  | math.order namespaces parser prettyprint.custom random sequences | 
					
						
							|  |  |  | vectors ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | IN: trees | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 14:21:11 -04:00
										 |  |  | TUPLE: tree root { count integer } ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-04 19:10:34 -04:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | : new-tree ( class -- tree )
 | 
					
						
							|  |  |  |     new
 | 
					
						
							|  |  |  |         f >>root | 
					
						
							|  |  |  |         0 >>count ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-04 19:10:34 -04:00
										 |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | : <tree> ( -- tree )
 | 
					
						
							|  |  |  |     tree new-tree ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | INSTANCE: tree assoc | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-04 19:10:34 -04:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | TUPLE: node key value left right ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : new-node ( key value class -- node )
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  |     new
 | 
					
						
							|  |  |  |         swap >>value | 
					
						
							| 
									
										
										
										
											2010-10-09 14:21:11 -04:00
										 |  |  |         swap >>key ; inline
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : <node> ( key value -- node )
 | 
					
						
							|  |  |  |     node new-node ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: current-side | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | CONSTANT: left -1
 | 
					
						
							|  |  |  | CONSTANT: right 1
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : key-side ( k1 k2 -- n )
 | 
					
						
							|  |  |  |     <=> { | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  |         { +lt+ [ left ] } | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |         { +eq+ [ 0 ] } | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  |         { +gt+ [ right ] } | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     } case ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : go-left? ( -- ? ) current-side get left eq? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-13 20:21:44 -04:00
										 |  |  | : inc-count ( tree -- ) [ 1 + ] change-count drop ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-13 20:21:44 -04:00
										 |  |  | : dec-count ( tree -- ) [ 1 - ] change-count drop ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : node-link@ ( node ? -- node )
 | 
					
						
							|  |  |  |     go-left? xor [ left>> ] [ right>> ] if ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  | : set-node-link@ ( left parent ? -- )
 | 
					
						
							| 
									
										
										
										
											2010-05-05 16:52:54 -04:00
										 |  |  |     go-left? xor [ left<< ] [ right<< ] if ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : node-link ( node -- child ) f node-link@  ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | : set-node-link ( child node -- ) f set-node-link@ ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | : node+link ( node -- child ) t node-link@ ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | : set-node+link ( child node -- ) t set-node-link@ ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | : with-side ( side quot -- )
 | 
					
						
							| 
									
										
										
										
											2010-05-04 19:10:34 -04:00
										 |  |  |     [ current-side ] dip with-variable ; inline
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | : with-other-side ( quot -- )
 | 
					
						
							|  |  |  |     current-side get neg swap with-side ; inline
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | : go-left ( quot -- ) left swap with-side ; inline
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | : go-right ( quot -- ) right swap with-side ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : leaf? ( node -- ? )
 | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  |     { [ left>> not ] [ right>> not ] } 1&& ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | : random-side ( -- side )
 | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  |     2 random 0 eq? left right ? ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : choose-branch ( key node -- key node-left/right )
 | 
					
						
							|  |  |  |     2dup key>> key-side [ node-link ] with-side ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : node-at* ( key node -- value ? )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         2dup key>> = [ | 
					
						
							|  |  |  |             nip value>> t
 | 
					
						
							|  |  |  |         ] [ | 
					
						
							|  |  |  |             choose-branch node-at* | 
					
						
							|  |  |  |         ] if
 | 
					
						
							|  |  |  |     ] [ drop f f ] if* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  | M: tree at* | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     root>> node-at* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-06 10:40:47 -05:00
										 |  |  | : node-set ( value key node -- node new? )
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     2dup key>> key-side dup 0 eq? [ | 
					
						
							| 
									
										
										
										
											2017-01-06 10:40:47 -05:00
										 |  |  |         drop nip swap >>value f
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     ] [ | 
					
						
							|  |  |  |         [ | 
					
						
							| 
									
										
										
										
											2017-01-06 10:40:47 -05:00
										 |  |  |             [ node-link [ node-set ] [ swap <node> t ] if* ] keep
 | 
					
						
							|  |  |  |             swap [ [ set-node-link ] keep ] dip
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |         ] with-side | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  | M: tree set-at | 
					
						
							| 
									
										
										
										
											2017-01-06 10:40:47 -05:00
										 |  |  |     [ [ node-set ] [ swap <node> t ] if* swap ] change-root | 
					
						
							|  |  |  |     swap [ dup inc-count ] when drop ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : valid-node? ( node -- ? )
 | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  |         { | 
					
						
							|  |  |  |             [ dup left>> [ key>> swap key>> before? ] when* ] | 
					
						
							|  |  |  |             [ dup right>> [ key>> swap key>> after? ] when* ] | 
					
						
							|  |  |  |             [ left>> valid-node? ] | 
					
						
							|  |  |  |             [ right>> valid-node? ] | 
					
						
							|  |  |  |         } 1&& | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     ] [ t ] if* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : valid-tree? ( tree -- ? ) root>> valid-node? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 13:26:22 -05:00
										 |  |  | : node>entry ( node -- entry ) [ key>> ] [ value>> ] bi 2array ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : entry, ( node -- ) node>entry , ;
 | 
					
						
							| 
									
										
										
										
											2017-01-24 08:30:05 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | : (node>alist) ( node -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ left>> (node>alist) ] | 
					
						
							| 
									
										
										
										
											2017-01-25 13:26:22 -05:00
										 |  |  |         [ entry, ] | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |         [ right>> (node>alist) ] | 
					
						
							|  |  |  |         tri
 | 
					
						
							|  |  |  |     ] when* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  | M: tree >alist | 
					
						
							|  |  |  |     [ root>> (node>alist) ] { } make ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 08:30:05 -05:00
										 |  |  | :: (node>subalist-right) ( to-key node end-comparator: ( key1 key2 -- ? ) -- )
 | 
					
						
							|  |  |  |     node [ | 
					
						
							|  |  |  |         node key>> to-key end-comparator call :> node-left? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node left>> node-left? [ (node>alist) ] [ | 
					
						
							|  |  |  |             [ to-key ] dip end-comparator (node>subalist-right) | 
					
						
							|  |  |  |         ] if
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node-left? [ | 
					
						
							| 
									
										
										
										
											2017-01-25 13:26:22 -05:00
										 |  |  |             node [ entry, ] [ | 
					
						
							| 
									
										
										
										
											2017-01-24 08:30:05 -05:00
										 |  |  |                 right>> [ to-key ] dip
 | 
					
						
							|  |  |  |                 end-comparator (node>subalist-right) | 
					
						
							|  |  |  |             ] bi
 | 
					
						
							|  |  |  |         ] when
 | 
					
						
							|  |  |  |     ] when ; inline recursive
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :: (node>subalist-left) ( from-key node start-comparator: ( key1 key2 -- ? ) -- )
 | 
					
						
							|  |  |  |     node [ | 
					
						
							|  |  |  |         node key>> from-key start-comparator call :> node-right? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node-right? [ | 
					
						
							|  |  |  |             node [ | 
					
						
							|  |  |  |                 left>> [ from-key ] dip
 | 
					
						
							|  |  |  |                 start-comparator (node>subalist-left) | 
					
						
							| 
									
										
										
										
											2017-01-25 13:26:22 -05:00
										 |  |  |             ] [ entry, ] bi
 | 
					
						
							| 
									
										
										
										
											2017-01-24 08:30:05 -05:00
										 |  |  |         ] when
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node right>> node-right? [ (node>alist) ] [ | 
					
						
							|  |  |  |             [ from-key ] dip start-comparator (node>subalist-left) | 
					
						
							|  |  |  |         ] if
 | 
					
						
							|  |  |  |     ] when ; inline recursive
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :: (node>subalist) ( from-key to-key node start-comparator: ( key1 key2 -- ? ) end-comparator: ( key1 key2 -- ? ) -- )
 | 
					
						
							|  |  |  |     node [ | 
					
						
							|  |  |  |         node key>> from-key start-comparator call :> node-right? | 
					
						
							|  |  |  |         node key>> to-key end-comparator call :> node-left? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node-right? [ | 
					
						
							|  |  |  |             from-key node left>> node-left? | 
					
						
							|  |  |  |             [ start-comparator (node>subalist-left) ] | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 [ to-key ] dip start-comparator | 
					
						
							|  |  |  |                 end-comparator (node>subalist) | 
					
						
							|  |  |  |             ] if
 | 
					
						
							|  |  |  |         ] when
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 13:26:22 -05:00
										 |  |  |         node-right? node-left? and [ node entry, ] when
 | 
					
						
							| 
									
										
										
										
											2017-01-24 08:30:05 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         node-left? [ | 
					
						
							|  |  |  |             to-key node right>> node-right? | 
					
						
							|  |  |  |             [ end-comparator (node>subalist-right) ] | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                  [ from-key ] 2dip start-comparator | 
					
						
							|  |  |  |                  end-comparator (node>subalist) | 
					
						
							|  |  |  |             ] if
 | 
					
						
							|  |  |  |         ] when
 | 
					
						
							|  |  |  |     ] when ; inline recursive
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : subtree>alist[) ( from-key to-key tree -- alist )
 | 
					
						
							|  |  |  |     [ root>> [ after=? ] [ before? ] (node>subalist) ] { } make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : subtree>alist(] ( from-key to-key tree -- alist )
 | 
					
						
							|  |  |  |     [ root>> [ after? ] [ before=? ] (node>subalist) ] { } make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : subtree>alist[] ( from-key to-key tree -- alist )
 | 
					
						
							|  |  |  |     [ root>> [ after=? ] [ before=? ] (node>subalist) ] { } make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : subtree>alist() ( from-key to-key tree -- alist )
 | 
					
						
							|  |  |  |     [ root>> [ after? ] [ before? ] (node>subalist) ] { } make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : headtree>alist[) ( to-key tree -- alist )
 | 
					
						
							|  |  |  |     [ root>> [ before? ] (node>subalist-right) ] { } make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : headtree>alist[] ( to-key tree -- alist )
 | 
					
						
							|  |  |  |     [ root>> [ before=? ] (node>subalist-right) ] { } make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : tailtree>alist[] ( from-key tree -- alist )
 | 
					
						
							|  |  |  |     [ root>> [ after=? ] (node>subalist-left) ] { } make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : tailtree>alist(] ( from-key tree -- alist )
 | 
					
						
							|  |  |  |     [ root>> [ after? ] (node>subalist-left) ] { } make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 08:30:22 -05:00
										 |  |  | : (nodepath-at) ( key node -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         dup , | 
					
						
							|  |  |  |         2dup key>> = [ | 
					
						
							|  |  |  |             2drop
 | 
					
						
							|  |  |  |         ] [ | 
					
						
							|  |  |  |             choose-branch (nodepath-at) | 
					
						
							|  |  |  |         ] if
 | 
					
						
							|  |  |  |     ] [ drop ] if* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : nodepath-at ( key tree -- path )
 | 
					
						
							|  |  |  |     [ root>> (nodepath-at) ] { } make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : right-extremity ( node -- node' )
 | 
					
						
							|  |  |  |     [ dup right>> dup ] [ nip ] while drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : left-extremity ( node -- node' )
 | 
					
						
							|  |  |  |     [ dup left>> dup ] [ nip ] while drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : lower-node-in-child? ( key node -- ? )
 | 
					
						
							|  |  |  |     [ nip left>> ] [ key>> = ] 2bi and ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : higher-node-in-child? ( key node -- ? )
 | 
					
						
							|  |  |  |     [ nip right>> ] [ key>> = ] 2bi and ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : lower-node ( key tree -- node )
 | 
					
						
							|  |  |  |     dupd nodepath-at | 
					
						
							|  |  |  |     [ drop f ] [ | 
					
						
							|  |  |  |         reverse 2dup first lower-node-in-child? | 
					
						
							|  |  |  |         [ nip first left>> right-extremity ] | 
					
						
							|  |  |  |         [ [ key>> after? ] with find nip ] if
 | 
					
						
							|  |  |  |     ] if-empty ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : higher-node ( key tree -- node )
 | 
					
						
							|  |  |  |     dupd nodepath-at | 
					
						
							|  |  |  |     [ drop f ] [ | 
					
						
							|  |  |  |         reverse 2dup first higher-node-in-child? | 
					
						
							|  |  |  |         [ nip first right>> left-extremity ] | 
					
						
							|  |  |  |         [ [ key>> before? ] with find nip ] if
 | 
					
						
							|  |  |  |     ] if-empty ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : floor-node ( key tree -- node )
 | 
					
						
							|  |  |  |     dupd nodepath-at [ drop f ] [ | 
					
						
							|  |  |  |         reverse [ key>> after=? ] with find nip
 | 
					
						
							|  |  |  |     ] if-empty ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : ceiling-node ( key tree -- node )
 | 
					
						
							|  |  |  |     dupd nodepath-at [ drop f ] [ | 
					
						
							|  |  |  |         reverse [ key>> before=? ] with find nip
 | 
					
						
							|  |  |  |     ] if-empty ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : first-node ( tree -- node ) root>> dup [ left-extremity ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : last-node ( tree -- node ) root>> dup [ right-extremity ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : lower-entry ( key tree -- pair/f ) lower-node dup [ node>entry ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : higher-entry ( key tree -- pair/f ) higher-node dup [ node>entry ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : floor-entry ( key tree -- pair/f ) floor-node dup [ node>entry ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : ceiling-entry ( key tree -- pair/f ) ceiling-node dup [ node>entry ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : first-entry ( tree -- pair/f ) first-node dup [ node>entry ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : last-entry ( tree -- pair/f ) last-node dup [ node>entry ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : lower-key ( key tree -- key/f ) lower-node dup [ key>> ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : higher-key ( key tree -- key/f ) higher-node dup [ key>> ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : floor-key ( key tree -- key/f ) floor-node dup [ key>> ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : ceiling-key ( key tree -- key/f ) ceiling-node dup [ key>> ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : first-key ( tree -- key/f ) first-node dup [ key>> ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : last-key ( tree -- key/f ) last-node dup [ key>> ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | M: tree clear-assoc | 
					
						
							|  |  |  |     0 >>count | 
					
						
							|  |  |  |     f >>root drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : copy-node-contents ( new old -- new )
 | 
					
						
							|  |  |  |     [ key>> >>key ] | 
					
						
							|  |  |  |     [ value>> >>value ] bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Deletion | 
					
						
							|  |  |  | DEFER: delete-node | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (prune-extremity) ( parent node -- new-extremity )
 | 
					
						
							|  |  |  |     dup node-link [ | 
					
						
							| 
									
										
										
										
											2010-05-04 19:10:34 -04:00
										 |  |  |         [ nip ] dip (prune-extremity) | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2017-01-09 11:22:20 -05:00
										 |  |  |         [ delete-node swap set-node-link ] keep
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     ] if* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : prune-extremity ( node -- new-extremity )
 | 
					
						
							| 
									
										
										
										
											2015-09-08 19:15:10 -04:00
										 |  |  |     ! remove and return the leftmost or rightmost child of this node. | 
					
						
							|  |  |  |     ! assumes at least one child | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     dup node-link (prune-extremity) ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : replace-with-child ( node -- node )
 | 
					
						
							|  |  |  |     dup node-link copy-node-contents dup node-link delete-node over set-node-link ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : replace-with-extremity ( node -- node )
 | 
					
						
							|  |  |  |     dup node-link dup node+link [ | 
					
						
							|  |  |  |         ! predecessor/successor is not the immediate child | 
					
						
							|  |  |  |         [ prune-extremity ] with-other-side copy-node-contents | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         ! node-link is the predecessor/successor | 
					
						
							|  |  |  |         drop replace-with-child | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : delete-node-with-two-children ( node -- node )
 | 
					
						
							| 
									
										
										
										
											2015-09-08 19:15:10 -04:00
										 |  |  |     ! randomised to minimise tree unbalancing | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     random-side [ replace-with-extremity ] with-side ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : delete-node ( node -- node )
 | 
					
						
							| 
									
										
										
										
											2015-09-08 19:15:10 -04:00
										 |  |  |     ! delete this node, returning its replacement | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  |     dup [ right>> ] [ left>> ] bi [ | 
					
						
							|  |  |  |         swap [ | 
					
						
							|  |  |  |             drop delete-node-with-two-children | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |         ] [ | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  |             nip ! left but no right | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |         ] if
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  |         nip ! right but no left, or no children | 
					
						
							|  |  |  |     ] if* ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-06 10:40:47 -05:00
										 |  |  | : delete-bst-node ( key node -- node deleted? )
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     2dup key>> key-side dup 0 eq? [ | 
					
						
							| 
									
										
										
										
											2017-01-06 10:40:47 -05:00
										 |  |  |         drop nip delete-node t
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2010-05-04 19:10:34 -04:00
										 |  |  |         [ | 
					
						
							|  |  |  |             [ node-link delete-bst-node ] | 
					
						
							| 
									
										
										
										
											2017-01-06 10:40:47 -05:00
										 |  |  |             [ swap [ set-node-link ] dip ] | 
					
						
							|  |  |  |             [ swap ] tri
 | 
					
						
							| 
									
										
										
										
											2010-05-04 19:10:34 -04:00
										 |  |  |         ] with-side | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: tree delete-at | 
					
						
							| 
									
										
										
										
											2017-01-06 10:40:47 -05:00
										 |  |  |     [ delete-bst-node swap ] change-root | 
					
						
							|  |  |  |     swap [ dup dec-count ] when drop ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: tree new-assoc | 
					
						
							|  |  |  |     2drop <tree> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-06 09:20:06 -05:00
										 |  |  | : clone-nodes ( node -- node' )
 | 
					
						
							|  |  |  |     dup [ | 
					
						
							|  |  |  |         clone
 | 
					
						
							|  |  |  |         [ clone-nodes ] change-left | 
					
						
							|  |  |  |         [ clone-nodes ] change-right | 
					
						
							|  |  |  |     ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: tree clone (clone) [ clone-nodes ] change-root ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 13:26:22 -05:00
										 |  |  | : ?push-children ( node queue -- )
 | 
					
						
							|  |  |  |     [ [ left>> ] [ right>> ] bi ] | 
					
						
							|  |  |  |     [ [ over [ push-front ] [ 2drop ] if ] curry bi@ ] bi* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : each-bfs-node ( tree quot: ( ... entry -- ... ) -- ... )
 | 
					
						
							|  |  |  |     [ root>> <dlist> [ push-front ] keep dup ] dip
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ drop node>entry ] prepose
 | 
					
						
							|  |  |  |         [ ?push-children ] 2bi
 | 
					
						
							|  |  |  |     ] 2curry slurp-deque ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : >bfs-alist ( tree -- alist )
 | 
					
						
							|  |  |  |     dup assoc-size <vector> [ | 
					
						
							|  |  |  |         [ push ] curry each-bfs-node | 
					
						
							|  |  |  |     ] keep ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: tree assoc-clone-like | 
					
						
							|  |  |  |     [ dup tree? [ >bfs-alist ] when ] dip call-next-method ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 14:03:47 -05:00
										 |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | : >tree ( assoc -- tree )
 | 
					
						
							|  |  |  |     T{ tree f f 0 } assoc-clone-like ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-21 02:27:50 -04:00
										 |  |  | SYNTAX: TREE{ | 
					
						
							|  |  |  |     \ } [ >tree ] parse-literal ;
 | 
					
						
							| 
									
										
										
										
											2014-12-11 23:33:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 14:03:47 -05:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: tree assoc-like drop dup tree? [ >tree ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:02:21 -05:00
										 |  |  | M: tree assoc-size count>> ;
 | 
					
						
							| 
									
										
										
										
											2009-03-04 17:14:16 -05:00
										 |  |  | M: tree pprint-delims drop \ TREE{ \ } ;
 | 
					
						
							|  |  |  | M: tree >pprint-sequence >alist ;
 | 
					
						
							|  |  |  | M: tree pprint-narrow? drop t ;
 | 
					
						
							| 
									
										
										
										
											2017-01-06 09:28:24 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : node-height ( node -- n )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ left>> ] [ right>> ] bi
 | 
					
						
							|  |  |  |         [ node-height ] bi@ max 1 +
 | 
					
						
							|  |  |  |     ] [ 0 ] if* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : height ( tree -- n )
 | 
					
						
							|  |  |  |     root>> node-height ;
 | 
					
						
							| 
									
										
										
										
											2017-01-24 13:59:27 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 09:25:56 -05:00
										 |  |  | : pop-tree-extremity ( tree node/f -- node/f )
 | 
					
						
							|  |  |  |     dup [ | 
					
						
							|  |  |  |         [ key>> swap delete-at ] keep node>entry | 
					
						
							| 
									
										
										
										
											2017-01-24 13:59:27 -05:00
										 |  |  |     ] [ nip ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 09:25:56 -05:00
										 |  |  | :: slurp-tree ( tree quot: ( ... entry -- ... ) getter: ( tree -- node ) -- ... )
 | 
					
						
							|  |  |  |     [ tree count>> 0 = ] | 
					
						
							|  |  |  |     [ tree getter call quot call ] until ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 13:59:27 -05:00
										 |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 09:25:56 -05:00
										 |  |  | : pop-tree-left ( tree -- node/f )
 | 
					
						
							|  |  |  |     dup first-node pop-tree-extremity ;
 | 
					
						
							| 
									
										
										
										
											2017-01-24 13:59:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 09:25:56 -05:00
										 |  |  | : pop-tree-right ( tree -- node/f )
 | 
					
						
							|  |  |  |     dup last-node pop-tree-extremity ;
 | 
					
						
							| 
									
										
										
										
											2017-01-24 13:59:27 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : slurp-tree-left ( tree quot: ( ... entry -- ... ) -- ... )
 | 
					
						
							| 
									
										
										
										
											2017-01-25 09:25:56 -05:00
										 |  |  |     [ pop-tree-left ] slurp-tree ; inline
 | 
					
						
							| 
									
										
										
										
											2017-01-24 13:59:27 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : slurp-tree-right ( tree quot: ( ... entry -- ... ) -- ... )
 | 
					
						
							| 
									
										
										
										
											2017-01-25 09:25:56 -05:00
										 |  |  |     [ pop-tree-right ] slurp-tree ; inline
 |