{ import: Object } { import: TestCase } "Range represents a range between two integers (or two comarable object maybe). It is almost same as Ingerval in Smalltalk except step. TODO: Equal test. " Range : SequenceableCollection (first last) Range from: firstValue to: lastValue [ self := self new. first := firstValue. last := lastValue. ] Range at: offset [ ^first + offset ] Range first [ ^first ] Range last [ ^last ] Range size [ ^last - first ] Range copy [ ^Range from: first to: last ] Range + aNumber [ ^ first + aNumber to: last + aNumber ] Number to: aNumber [ ^ Range from: self to: aNumber ] Number size: aNumber [ ^ Range from: self to: self + aNumber ] Range sorted [ ^ first < last ifTrue: [ self ] ifFalse: [ last to: first ] ] Range union: aRange [ "Answer the smallest Range that contains both the receiver and aRange." ^self from: (first min: aRange first) to: (last max: aRange last) ] Range intersect: aRange [ "Answer common area of two ranges, answer minus size range if it does not intersect" ^(self first max: aRange first) to: (self last min: aRange last) ] Range printOn: aStream [ aStream nextPutAll: '('. first printOn: aStream. aStream nextPutAll: ' to: '. last printOn: aStream. aStream nextPutAll: ')'. ] Range do: aBlock [ first to: last do: aBlock ] "about to merge to SequenceableCollection >> findBinary:ifNone:" Range largestSatisfied: aBlock [ "Search for the largest element which satisfies the condition" | index low high test item | self size = 0 ifTrue: [ ^ first ]. (aBlock value: first) ifFalse: [ ^ first ]. low := 0. high := self size. [index := high + low // 2. low > high] whileFalse:[ test := aBlock value: (item := self at: index). test ifTrue:[low := index + 1] ifFalse:[high := index - 1]]. ^ self at: high ] RangeTest : TestCase () RangeTest testRange [ | result | self assert: (5 to: 10) size equals: 5. self assert: (10 to: 5) size equals: -5. result := OrderedCollection new. (5 to: 10) do: [:i | result add: i]. self assert: result asArray equals: #(5 6 7 8 9 10). result := OrderedCollection new. (10 to: 5) do: [:i | result add: i]. self assert: result asArray equals: #(). result := OrderedCollection new. (5 to: 5) do: [:i | result add: i]. self assert: result asArray equals: #(5). "todo: it seems to be strange" result := OrderedCollection new. (5 size: 5) do: [:i | result add: i]. self assert: result asArray equals: #(5 6 7 8 9 10). self assert: ((5 to: 10) intersect: (6 to: 9)) equals: (6 to: 9). self assert: ((5 to: 10) intersect: (0 to: 9)) equals: (5 to: 9). self assert: ((5 to: 10) intersect: (6 to: 15)) equals: (6 to: 10). self assert: ((5 to: 10) intersect: (10 to: 15)) size equals: 0. self assert: ((5 to: 10) intersect: (15 to: 20)) size < 0 equals: true. self assert: ((5 to: 10) intersect: (0 to: 4)) size < 0 equals: true. ]