stack.monkey2 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. Namespace std.collections
  2. #rem monkeydoc Convenience type alias for Stack\<Int\>.
  3. #end
  4. Alias IntStack:Stack<Int>
  5. #rem monkeydoc Convenience type alias for Stack\<Float\>.
  6. #end
  7. Alias FloatStack:Stack<Float>
  8. #rem monkeydoc Convenience type alias for Stack\<String\>.
  9. #end
  10. Alias StringStack:Stack<String>
  11. #rem monkeydoc The Stack class provides suport for dynamic arrays.
  12. A stack is an 'array like' container that grows dynamically as necessary.
  13. It is very cheap to add values to the end of a stack, but insertion or removal of values requires higher indexed values to be
  14. 'shifted down'.
  15. Stacks implement the [[IContainer]] interface so can be used with [[Eachin]] loops.
  16. Note that you should NOT modify a stack while iterating through it with an eachin loop. Doing so while cause a 'concurrent stack
  17. modification' runtime error in debug mode. Please see [[IContainer]] for more information.
  18. #end
  19. Class Stack<T> Implements IContainer<T>
  20. #rem monkeydoc The Stack.Iterator struct.
  21. #end
  22. Struct Iterator 'Implements IIterator<T>
  23. Private
  24. Field _stack:Stack
  25. Field _index:Int
  26. Field _seq:Int
  27. Method AssertSeq()
  28. DebugAssert( _seq=_stack._seq,"Concurrent list modification" )
  29. End
  30. Method AssertCurrent()
  31. DebugAssert( Not AtEnd,"Invalid list iterator" )
  32. End
  33. Method New( stack:Stack,index:Int )
  34. _stack=stack
  35. _index=index
  36. _seq=stack._seq
  37. End
  38. Public
  39. #rem monkeydoc Checks if the iterator has reached the end of the stack.
  40. #end
  41. Property AtEnd:Bool()
  42. AssertSeq()
  43. Return _index=_stack._length
  44. End
  45. #rem monkeydoc The value currently pointed to by the iterator.
  46. #end
  47. Property Current:T()
  48. AssertCurrent()
  49. Return _stack._data[_index]
  50. Setter( current:T )
  51. AssertCurrent()
  52. _stack._data[_index]=current
  53. End
  54. #rem monkeydoc Bumps the iterator so it points to the next value in the stack.
  55. #end
  56. Method Bump()
  57. AssertCurrent()
  58. _index+=1
  59. End
  60. #rem monkeydoc Safely erases the value pointed to by the iterator.
  61. After calling this method, the iterator will point to the value after the removed value.
  62. Therefore, if you are manually iterating through a stack you should not call [[Bump]] after calling this method or you
  63. will end up skipping a value.
  64. #end
  65. Method Erase()
  66. AssertSeq()
  67. _stack.Erase( _index )
  68. _seq=_stack._seq
  69. End
  70. #rem monkeydoc Safely inserts a value before the value pointed to by the iterator.
  71. After calling this method, the iterator will point to the newly added value.
  72. #end
  73. Method Insert( value:T )
  74. AssertSeq()
  75. _stack.Insert( _index,value )
  76. _seq=_stack._seq
  77. End
  78. End
  79. #rem monkeydoc The Stack.BackwardsIterator struct.
  80. #end
  81. Struct BackwardsIterator 'Implements IIterator<T>
  82. Private
  83. Field _stack:Stack
  84. Field _index:Int
  85. Field _seq:Int
  86. Method AssertSeq()
  87. DebugAssert( _seq=_stack._seq,"Concurrent list modification" )
  88. End
  89. Method AssertCurrent()
  90. DebugAssert( Not AtEnd,"Invalid list iterator" )
  91. End
  92. Method New( stack:Stack,index:Int )
  93. _stack=stack
  94. _index=index
  95. _seq=stack._seq
  96. End
  97. Public
  98. #rem monkeydoc Checks if the iterator has reached the end of the stack.
  99. #end
  100. Property AtEnd:Bool()
  101. AssertSeq()
  102. Return _index=-1
  103. End
  104. #rem monkeydoc The value currently pointed to by the iterator.
  105. #end
  106. Property Current:T()
  107. AssertCurrent()
  108. Return _stack._data[_index]
  109. Setter( current:T )
  110. AssertCurrent()
  111. _stack._data[_index]=current
  112. End
  113. #rem monkeydoc Bumps the iterator so it points to the next value in the stack.
  114. #end
  115. Method Bump()
  116. AssertCurrent()
  117. _index-=1
  118. End
  119. #rem monkeydoc Safely erases the value pointed to by the iterator.
  120. After calling this method, the iterator will point to the value after the removed value.
  121. Therefore, if you are manually iterating through a stack you should not call [[Bump]] after calling this method or you
  122. will end up skipping a value.
  123. #end
  124. Method Erase()
  125. AssertCurrent()
  126. _index-=1
  127. _stack.Erase( _index+1 )
  128. _seq=_stack._seq
  129. End
  130. #rem monkeydoc Safely inserts a value before the value pointed to by the iterator.
  131. After calling this method, the iterator will point to the newly added value.
  132. #end
  133. Method Insert( value:T )
  134. AssertSeq()
  135. _index+=1
  136. _stack.Insert( _index,value )
  137. _seq=_stack._seq
  138. End
  139. End
  140. Private
  141. Field _data:T[]
  142. Field _length:Int
  143. Field _seq:Int
  144. Public
  145. #rem monkeydoc Creates a new stack.
  146. New() creates an empty stack.
  147. New( length:Int ) creates a stack that initially contains `length` null values.
  148. New( values:T[] ) creates a stack with the contents of an array.
  149. New( values:List<T> ) creates a stack with the contents of a list.
  150. New( values:Stack<T> ) create a stack with the contents of another stack.
  151. @param length The length of the stack.
  152. @param values An array, list or stack.
  153. #end
  154. Method New()
  155. _data=New T[10]
  156. End
  157. Method New( length:Int )
  158. _length=length
  159. _data=New T[_length]
  160. End
  161. Method New( values:T[] )
  162. AddAll( values )
  163. End
  164. Method New( values:Stack<T> )
  165. _length=values.Length
  166. _data=New T[_length]
  167. values.Data.CopyTo( _data,0,0,_length )
  168. End
  169. Method New( values:List<T> )
  170. AddAll( values )
  171. End
  172. #rem monkeydoc Checks if the stack is empty.
  173. @return True if the stack is empty.
  174. #end
  175. Property Empty:Bool()
  176. Return _length=0
  177. End
  178. #rem monkeydoc Gets an iterator for visiting stack values.
  179. Returns an iterator suitable for use with [[Eachin]], or for manual iteration.
  180. @return A stack iterator.
  181. #end
  182. Method All:Iterator()
  183. Return New Iterator( Self,0 )
  184. End
  185. #rem monkeydoc Gets an iterator for visiting stack values in reverse order.
  186. Returns an iterator suitable for use with [[Eachin]], or for manual iteration.
  187. @return A backwards stack iterator.
  188. #end
  189. Method Backwards:BackwardsIterator()
  190. Return New BackwardsIterator( Self,_length-1 )
  191. End
  192. #rem monkeydoc Converts the stack to an array.
  193. @return An array containing each element of the stack.
  194. #end
  195. Method ToArray:T[]()
  196. Return _data.Slice( 0,_length )
  197. End
  198. #rem monkeydoc Gets the underlying array used by the stack.
  199. Note that the returned array may be longer than the stack length.
  200. @return The array used internally by the stack.
  201. #end
  202. Property Data:T[]()
  203. Return _data
  204. End
  205. #rem monkeydoc Gets the number of values in the stack.
  206. @return The number of values in the stack.
  207. #end
  208. Property Length:Int()
  209. Return _length
  210. End
  211. #rem monkeydoc Gets the storage capacity of the stack.
  212. The capacity of a stack is the number of values it can contain before memory needs to be reallocated to store more values.
  213. If a stack's length equals its capacity, then the next Add or Insert operation will need to allocate more memory to 'grow' the stack.
  214. You don't normally need to worry about stack capacity, but it can be useful to use [[Reserve]] to preallocate stack storage if you know in advance
  215. how many values a stack is likely to contain, in order to prevent the overhead of excessive memory allocation.
  216. @return The current stack capacity.
  217. #end
  218. Property Capacity:Int()
  219. Return _data.Length
  220. End
  221. #rem monkeydoc Resizes the stack.
  222. If `length` is greater than the current stack length, any extra elements are initialized to null.
  223. If `length` is less than the current stack length, the stack is truncated.
  224. @param length The new length of the stack.
  225. #end
  226. Method Resize( length:Int )
  227. DebugAssert( length>=0 )
  228. For Local i:=length Until _length
  229. _data[i]=Null
  230. Next
  231. Reserve( length )
  232. _length=length
  233. _seq+=1
  234. End
  235. #rem monkeydoc Reserves stack storage capacity.
  236. The capacity of a stack is the number of values it can contain before memory needs to be reallocated to store more values.
  237. If a stack's length equals its capacity, then the next Add, Insert or Push operation will need to allocate more memory to 'grow' the stack.
  238. You don't normally need to worry about stack capacity, but it can be useful to use [[Reserve]] to preallocate stack storage if you know in advance
  239. how many values a stack is likely to contain, in order to prevent the overhead of excessive memory allocation.
  240. @param capacity The new capacity.
  241. #end
  242. Method Reserve( capacity:Int )
  243. DebugAssert( capacity>=0 )
  244. If _data.Length>=capacity Return
  245. capacity=Max( _length*2+_length,capacity )
  246. Local data:=New T[capacity]
  247. _data.CopyTo( data,0,0,_length )
  248. _data=data
  249. End
  250. #rem monkeydoc Clears the stack.
  251. #end
  252. Method Clear()
  253. Resize( 0 )
  254. End
  255. #rem monkeydoc Erases an element at an index in the stack.
  256. In debug builds, a runtime error will occur if `index` is less than 0 or greater than the stack length.
  257. if `index` is equal to the stack length, the operation has no effect.
  258. @param index The index of the element to erase.
  259. #end
  260. Method Erase( index:Int )
  261. DebugAssert( index>=0 And index<=_length )
  262. If index=_length Return
  263. _data.CopyTo( _data,index+1,index,_length-index-1 )
  264. Resize( _length-1 )
  265. End
  266. #rem monkeydoc Erases a range of elements in the stack.
  267. If debug builds, a runtime error will occur if either index is less than 0 or greater than the stack length, or if index2 is less than index1.
  268. The number of elements actually erased is `index2`-`index1`.
  269. @param index1 The index of the first element to erase.
  270. @param index2 The index of the last+1 element to erase.
  271. #end
  272. Method Erase( index1:Int,index2:Int )
  273. DebugAssert( index1>=0 And index1<=_length And index2>=0 And index2<=_length And index1<=index2 )
  274. If index1=_length Return
  275. _data.CopyTo( _data,index2,index1,_length-index2 )
  276. Resize( _length-index2+index1 )
  277. End
  278. #rem monkeydoc Inserts a value at an index in the stack.
  279. In debug builds, a runtime error will occur if `index` is less than 0 or greater than the stack length.
  280. If `index` is equal to the stack length, the value is added to the end of the stack.
  281. @param index The index of the value to insert.
  282. @param value The value to insert.
  283. #end
  284. Method Insert( index:Int,value:T )
  285. DebugAssert( index>=0 And index<=_length )
  286. Reserve( _length+1 )
  287. _data.CopyTo( _data,index,index+1,_length-index )
  288. _data[index]=value
  289. _length+=1
  290. _seq+=1
  291. End
  292. #rem monkeydoc Gets the value of a stack element.
  293. In debug builds, a runtime error will occur if `index` is less than 0, or greater than or equal to the length of the stack.
  294. @param index The index of the element to get.
  295. #end
  296. Method Get:T( index:Int )
  297. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  298. Return _data[index]
  299. End
  300. #rem monkeydoc Sets the value of a stack element.
  301. In debug builds, a runtime error will occur if `index` is less than 0, or greater than or equal to the length of the stack.
  302. @param index The index of the element to set.
  303. @param value The value to set.
  304. #end
  305. Method Set( index:Int,value:T )
  306. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  307. _data[index]=value
  308. End
  309. #rem monkeydoc Gets the value of a stack element.
  310. In debug builds, a runtime error will occur if `index` is less than 0, or greater than or equal to the length of the stack.
  311. @param index The index of the element to get.
  312. #end
  313. Operator []:T( index:Int )
  314. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  315. Return _data[index]
  316. End
  317. #rem monkeydoc Sets the value of a stack element.
  318. In debug builds, a runtime error will occur if `index` is less than 0, or greater than or equal to the length of the stack.
  319. @param index The index of the element to set.
  320. @param value The value to set.
  321. #end
  322. Operator []=( index:Int,value:T )
  323. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  324. _data[index]=value
  325. End
  326. #rem monkeydoc Adds a value to the end of the stack.
  327. This method behaves identically to Push( value:T ).
  328. @param value The value to add.
  329. #end
  330. Method Add( value:T )
  331. Reserve( _length+1 )
  332. _data[_length]=value
  333. _length+=1
  334. _seq+=1
  335. End
  336. #rem monkeydoc Adds the values in an array to the end of the stack.
  337. @param values The values to add.
  338. #end
  339. Method AddAll( values:T[] )
  340. Reserve( _length+values.Length )
  341. values.CopyTo( _data,0,_length,values.Length )
  342. Resize( _length+values.Length )
  343. End
  344. #rem monkeydoc Adds the values in a container to the end of the stack.
  345. @param values The values to add.
  346. #end
  347. Method AddAll<C>( values:C ) Where C Implements IContainer<T>
  348. For Local value:=Eachin values
  349. Add( value )
  350. Next
  351. End
  352. 'TODO: KILLME! DON'T USE THIS!
  353. Method Append<C>( values:C ) Where C Implements IContainer<T>
  354. For Local value:=Eachin values
  355. Add( value )
  356. Next
  357. End
  358. #rem monkeydoc Finds the index of the first matching value in the stack.
  359. In debug builds, a runtime error will occur if `start` is less than 0 or greater than the length of the stack.
  360. @param value The value to find.
  361. @param start The starting index for the search.
  362. @return The index of the value in the stack, or -1 if the value was not found.
  363. #end
  364. Method FindIndex:Int( value:T,start:Int=0 )
  365. DebugAssert( start>=0 And start<=_length )
  366. Local i:=start
  367. While i<_length
  368. If _data[i]=value Return i
  369. i+=1
  370. Wend
  371. Return -1
  372. End
  373. #rem monkeydoc Finds the index of the last matching value in the stack.
  374. In debug builds, a runtime error will occur if `start` is less than 0 or greater than the length of the stack.
  375. @param value The value to find.
  376. @param start The starting index for the search.
  377. @return The index of the value in the stack, or -1 if the value was not found.
  378. #end
  379. Method FindLastIndex:Int( value:T,start:Int=0 )
  380. DebugAssert( start>=0 And start<=_length )
  381. Local i:=_length
  382. While i>start
  383. i-=1
  384. If _data[i]=value Return i
  385. Wend
  386. Return -1
  387. End
  388. #rem monkeydoc Checks if the stack contains a value.
  389. @param value The value to check for.
  390. @return True if the stack contains the value, else false.
  391. #end
  392. Method Contains:Bool( value:T )
  393. Return FindIndex( value )<>-1
  394. End
  395. #rem monkeydoc Finds and removes the first matching value from the stack.
  396. @param start The starting index for the search.
  397. @param value The value to remove.
  398. @return True if the value was removed.
  399. #end
  400. Method Remove:Bool( value:T,start:Int=0 )
  401. Local i:=FindIndex( value,start )
  402. If i=-1 Return False
  403. Erase( i )
  404. Return True
  405. End
  406. #rem monkeydoc Finds and removes the last matching value from the stack.
  407. @param start The starting index for the search.
  408. @param value The value to remove.
  409. @return True if the value was removed.
  410. #end
  411. Method RemoveLast:Bool( value:T,start:Int=0 )
  412. Local i:=FindLastIndex( value,start )
  413. If i=-1 Return False
  414. Erase( i )
  415. Return True
  416. End
  417. #rem monkeydoc Finds and removes each matching value from the stack.
  418. @param value The value to remove.
  419. @return The number of values removed.
  420. #end
  421. Method RemoveEach:Int( value:T )
  422. Local put:=0,n:=0
  423. For Local get:=0 Until _length
  424. If _data[get]=value
  425. n+=1
  426. Continue
  427. Endif
  428. _data[put]=_data[get]
  429. put+=1
  430. Next
  431. Resize( put )
  432. Return n
  433. End
  434. #rem monkeydoc Returns a range of elements from the stack
  435. Returns a slice of the stack consisting of all elements from `index` to the end of the stack.
  436. If `index` is negative, then it represents an offset from the end of the stack.
  437. 'index' is clamped to the length of the stack, so Slice will never cause a runtime error.
  438. @param index1 the index of the first element.
  439. @return A new stack.
  440. #end
  441. Method Slice:Stack( index:Int )
  442. Return Slice( index,_length )
  443. End
  444. #rem monkeydoc Returns a range of elements from the stack.
  445. Returns a slice of the stack consisting of all elements from `index1` up to but not including `index2`.
  446. If either index is negative, then it represents an offset from the end of the stack.
  447. 'index' and `index2` are clamped to the length of the stack, so Slice will never cause a runtime error.
  448. @param index1 The index of the first element.
  449. @param index2 The index of the last+1 element.
  450. @return A new stack.
  451. #end
  452. Method Slice:Stack( index1:Int,index2:Int )
  453. If index1<0
  454. index1=Max( index1+_length,0 )
  455. Else If index1>_length
  456. index1=_length
  457. Endif
  458. If index2<0
  459. index2=Max( index2+_length,index1 )
  460. Else If index2>_length
  461. index2=_length
  462. Else If index2<index1
  463. index2=index1
  464. Endif
  465. Return New Stack( _data.Slice( index1,index2 ) )
  466. End
  467. #rem monkeydoc Swaps 2 elements in the stack.
  468. In debug builds, a runtime error will occur if `index1` or `index2` is out of range.
  469. @param index1 The index of the first element.
  470. @param index2 The index of the second element.
  471. #end
  472. Method Swap( index1:Int,index2:Int )
  473. DebugAssert( index1>=0 And index1<_length And index2>=0 And index2<_length,"Stack index out of range" )
  474. Local t:=_data[index1]
  475. _data[index1]=_data[index2]
  476. _data[index2]=t
  477. End
  478. #rem monkeydoc Sorts the stack.
  479. @param ascending True to sort the stack in ascending order, false to sort in descending order.
  480. @param compareFunc Function to be used to compare values when sorting.
  481. @param lo Index of first value to sort.
  482. @param hi Index of last value to sort.
  483. #end
  484. Method Sort( ascending:Int=True )
  485. If ascending
  486. Sort( Lambda:Int( x:T,y:T )
  487. Return x<=>y
  488. End )
  489. Else
  490. Sort( Lambda:Int( x:T,y:T )
  491. Return y<=>x
  492. End )
  493. Endif
  494. End
  495. Method Sort( compareFunc:Int( x:T,y:T ) )
  496. Sort( compareFunc,0,_length-1 )
  497. End
  498. Method Sort( compareFunc:Int( x:T,y:T ),lo:Int,hi:int )
  499. If hi<=lo Return
  500. If lo+1=hi
  501. If compareFunc( _data[hi],_data[lo] )<0 Swap( hi,lo )
  502. Return
  503. Endif
  504. Local i:=(lo+hi)/2
  505. If compareFunc( _data[i],_data[lo] )<0 Swap( i,lo )
  506. If compareFunc( _data[hi],_data[i] )<0
  507. Swap( hi,i )
  508. If compareFunc( _data[i],_data[lo] )<0 Swap( i,lo )
  509. Endif
  510. Local x:=lo+1
  511. Local y:=hi-1
  512. Repeat
  513. Local p:=_data[i]
  514. While compareFunc( _data[x],p )<0
  515. x+=1
  516. Wend
  517. While compareFunc( p,_data[y] )<0
  518. y-=1
  519. Wend
  520. If x>y Exit
  521. If x<y
  522. Swap( x,y )
  523. If i=x i=y Else If i=y i=x
  524. Endif
  525. x+=1
  526. y-=1
  527. Until x>y
  528. Sort( compareFunc,lo,y )
  529. Sort( compareFunc,x,hi )
  530. End
  531. #rem monkeydoc Gets the top element of the stack
  532. In debug builds, a runtime error will occur if the stack is empty.
  533. @return The top element of the stack.
  534. #end
  535. Property Top:T()
  536. DebugAssert( _length,"Stack is empty" )
  537. Return _data[_length-1]
  538. End
  539. #rem monkeydoc Pops the top element off the stack and returns it.
  540. In debug builds, a runtime error will occur if the stack is empty.
  541. @return The top element of the stack before it was popped.
  542. #end
  543. Method Pop:T()
  544. DebugAssert( _length,"Stack is empty" )
  545. _length-=1
  546. _seq+=1
  547. Local value:=_data[_length]
  548. _data[_length]=Null
  549. Return value
  550. End
  551. #rem monkeydoc Pushes a value on the stack.
  552. This method behaves identically to Add( value:T ).
  553. @param value The value to push.
  554. #end
  555. Method Push( value:T )
  556. Add( value )
  557. End
  558. #rem monkeydoc Joins the values in the string list.
  559. @param sepeator The separator to be used when joining values.
  560. @return The joined values.
  561. #end
  562. Method Join:String( separator:String ) Where T=String
  563. Return separator.Join( ToArray() )
  564. End
  565. End