stack.monkey2 19 KB

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