Say you have
for i in 0 ... 10 {
print(i)
}
of course it will print 0,1,2,3,4,5,6,7,8,9,10
for i in 0 ..< 5 {
that's 0,1,2,3,4.
I want to start at a certain integer and pingpong outwards over the count of numbers
So,
for i in function or something (10, 3)
that's 3 4 2 5 1 6 0 7 8 9
for i in function or something (10, 8) {
would be 8 9 7 6 5 4 3 2 1 0
for i in function or something (10, 2) {
would be 2 3 1 4 0 5 6 7 8 9
So it's just an outwards pingpong.
What should I type where I have written function or something (10, 2)?
There might be some really cool syntax possible, along the lines 0 # 7 # 10.
What about something like (0..<10).outPong(3)?
How to formulate such a sequence?
Here's a naive example of how you'd do an outwards pingpong, at the call level.
Call exampleLoad for each of the items in RA, outwards pingpoing:
func loadItemsPongwise(startWith: Int) {
// RA = ... this is your array of some type
exampleLoad(startWith)
let k = RA.count
var howManyDone: Int = 0
var distance: Int = 1
while howManyDone < ( k - 1 ) {
let tryRight = alreadyLoaded + distance
if tryRight < k {
howManyDone = howManyDone + 1
exampleLoad(RA[tryRight])
}
let tryLeft = alreadyLoaded - distance
if tryLeft >= 0 {
howManyDone = howManyDone + 1
exampleLoad(RA[tryLeft])
}
distance = distance + 1
}
}
Of course, something like this wouild be much nicer:
func loadItemsPongwise(startWith: Int) {
for i in ???? {
exampleLoad(i)
}
}
public extension ClosedRange where Bound: AdditiveArithmetic {
func 🏓(
by contiguousAdvancement: Bound,
startingAt start: Bound
) -> AnySequence<Bound> {
guard contains(start)
else { return .init( EmptyCollection() ) }
var advancement = contiguousAdvancement
typealias Operate = (Bound, Bound) -> Bound
var pingPong: Operate = (+)
var contiguouslyAdvance: Operate = (-)
return .init(
sequence(first: start) { previous in
pingPongIterate: do {
defer { advancement += contiguousAdvancement }
let pingPonged = pingPong(previous, advancement)
guard self.contains(pingPonged)
else { break pingPongIterate }
(pingPong, contiguouslyAdvance) = (contiguouslyAdvance, pingPong)
return pingPonged
}
let contiguouslyAdvanced = contiguouslyAdvance(previous, contiguousAdvancement)
return self.contains(contiguouslyAdvanced)
? contiguouslyAdvanced
: nil
}
)
}
}
public extension ClosedRange where Bound: AdditiveArithmetic & ExpressibleByIntegerLiteral {
func 🏓(startingAt start: Bound) -> AnySequence<Bound> {
🏓(by: 1, startingAt: start)
}
}
public extension ClosedRange where Bound: BinaryInteger {
func 🏓(by contiguousAdvancement: Bound = 1) -> AnySequence<Bound> {
🏓(by: contiguousAdvancement, startingAt: (upperBound + lowerBound) / 2)
}
}
public extension ClosedRange where Bound: FloatingPoint {
func 🏓(by contiguousAdvancement: Bound = 1) -> AnySequence<Bound> {
🏓(by: contiguousAdvancement, startingAt: (upperBound + lowerBound) / 2)
}
}
XCTAssertEqual(
Array( (2...10).🏓() ),
[6, 7, 5, 8, 4, 9, 3, 10, 2]
)
XCTAssertEqual(
Array( (2...10).🏓(startingAt: 7) ),
[7, 8, 6, 9, 5, 10, 4, 3, 2]
)
XCTAssertEqual(
Array( (-1.5...7.5).🏓(by: 1.5) ),
[3, 4.5, 1.5, 6, 0, 7.5, -1.5]
)
XCTAssertEqual(
Array( (0...6).🏓(by: -1) ),
[3, 2, 4, 1, 5, 0, 6]
)
XCTAssertEqual(
Array( (0...3).🏓(startingAt: 4) ),
[]
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With