Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Swift, outwards pingpong sequence?

Tags:

ios

swift5

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)
    }
}
like image 458
Fattie Avatar asked Dec 04 '25 03:12

Fattie


1 Answers

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) ),
  []
)

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!