Cleanest way to wrap array index? - ios

Say I have an array of 5 Ints. What would be the most efficient way to wrap the index of the array if the index were incremented or decremented (for example) the following occurs?
where n = 0: arr[n-1] // -> arr[4] (wraps from 0 back to the end of the array)
where n = 2: arr[n+1] // -> arr[3] (behaves as normal)
where n = 4: arr[n+1] // -> arr[0] (wraps to 0 from the end of the array)

You can use the mod operation which will get you to a range of -count to count, then add count back in and mod again:
let foo = [0, 1, 2, 3, 4, 5]
for i in -6...7 {
print(i, foo[(i % foo.count + foo.count) % foo.count])
}
// -6 0
// -5 1
// -4 2
// -3 3
// -2 4
// -1 5
// 0 0
// 1 1
// 2 2
// 3 3
// 4 4
// 5 5
// 6 0
This works for both directions.

A bit late to the party, but if you're facing the same issue and have a lot of use cases for wrap-around array indices, you could also put the %-solution from the accepted answer in a simple subscript extension of Array, like so:
extension Array {
subscript (wrapping index: Int) -> Element {
return self[(index % self.count + self.count) % self.count]
}
}
Example Usage:
let array = ["a","b","c"]
print( array[wrapping: 0] ) // a
print( array[wrapping: 4] ) // b
print( array[wrapping: -1] ) // c

Cleanest I can do for only positive integers is this
extension Array{
subscript(wrapAround index: Int) -> Element {
return self[index % self.count]
}
}

Related

In Swift, outwards pingpong sequence?

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) ),
[]
)
So I went the route of taking the analogy of ping-pong seriously. I left some comments for clarity.
It simulates an actual ping pong ball bouncing (starting from the net, oddly), back and forth on a ping pong table that has a net that might not be centered. If it's about to go off the edge on one side, then it just goes to the other side and I like to imagine it does smaller and smaller bounces until it rolls off the table.
Here's the code with comments and a test:
// It's supposed to be a ping pong table 🤷‍♂️
struct 🟦: IteratorProtocol, Sequence {
typealias Element = Int
// The table *is* the iterator
typealias Iterator = 🟦
let leftEdgePosition: Int
/// The starting point for the ball
let netPosition: Int
let rightEdgePosition: Int
/// For convenience in checking whether different ball positions are on the table.
private let tableBounds: ClosedRange<Int>
init(leftEdgePosition: Int, netPosition: Int, rightEdgePosition: Int) {
self.leftEdgePosition = leftEdgePosition
self.netPosition = netPosition
self.rightEdgePosition = rightEdgePosition
self.tableBounds = leftEdgePosition...rightEdgePosition
}
private var distanceFromNet = 0
/// The side of the table the ping pong ball is headed toward
private var ballDirection: PingPongBallDirection = .towardLeftEdge
func makeIterator() -> 🟦 {
return self
}
/// This gets called for each iteration in the for loop. Once the ball goes beyond the table, we should return nil to stop the for loop.
mutating public func next() -> Int? {
// the ball position we will return if this position is on the table
let ballPosition = ballDirection.locationCalculator(netPosition, distanceFromNet)
// the ball position we will return if the first ball position is not on the table
let redirectedPosition = (!ballDirection).locationCalculator(netPosition, distanceFromNet)
// determine which ball position to return and set up our state for the next call to next()
var ballPositionToReturn: Int?
if tableBounds.contains(ballPosition) {
ballPositionToReturn = ballPosition
let ballMirrorPosition = (!ballDirection).locationCalculator(netPosition, distanceFromNet)
let ballIsTrailingOff = !tableBounds.contains(ballMirrorPosition)
if !ballIsTrailingOff {
// switch the direction because the ball hit the table
ballDirection = !ballDirection
}
// If we're heading to the right, i.e 3 -> 4 in the case of 0 << 3 >> 10, then increase
// the distance from the net.
// If we're trailing off and not ping-ponging any more, then we need to add distance.
if ballDirection == .towardRightEdge || ballIsTrailingOff {
distanceFromNet += 1
}
} else if tableBounds.contains(redirectedPosition) {
ballPositionToReturn = redirectedPosition
// reflect the redirection
ballDirection = !ballDirection
// add distance when we redirect
distanceFromNet += 1
}
return ballPositionToReturn
}
}
enum PingPongBallDirection {
case towardLeftEdge
case towardRightEdge
/// Returns the oppposite direction
static prefix func !(direction: PingPongBallDirection) -> PingPongBallDirection {
switch direction {
case towardLeftEdge: return towardRightEdge
case towardRightEdge: return towardLeftEdge
}
}
// In our world, right is greater and left is lesser.
var locationCalculator: (Int, Int) -> Int {
switch self {
case .towardLeftEdge: return (-)
case .towardRightEdge: return (+)
}
}
}
// Make the syntax work
precedencegroup PingPongPrecedenceGroup {
associativity: left
// this makes sure the ping pong operator gets evaluated before the assignment operator
higherThan: AssignmentPrecedence
}
infix operator ...: PingPongPrecedenceGroup
func ... (lhs: ClosedRange<Int>, rhs: Int) -> 🟦 {
return 🟦(leftEdgePosition: lhs.lowerBound, netPosition: lhs.upperBound, rightEdgePosition: rhs)
}
for i in 0...10 {
for j in 0...i...10 {
print(j, terminator: " ")
}
print()
}
// OUTPUT:
// 0 1 2 3 4 5 6 7 8 9 10
// 1 2 0 3 4 5 6 7 8 9 10
// 2 3 1 4 0 5 6 7 8 9 10
// 3 4 2 5 1 6 0 7 8 9 10
// 4 5 3 6 2 7 1 8 0 9 10
// 5 6 4 7 3 8 2 9 1 10 0
// 6 7 5 8 4 9 3 10 2 1 0
// 7 8 6 9 5 10 4 3 2 1 0
// 8 9 7 10 6 5 4 3 2 1 0
// 9 10 8 7 6 5 4 3 2 1 0
// 10 9 8 7 6 5 4 3 2 1 0
stateless
Just for anyone working on the syntax.
I wasted an hour of my life figuring out a stateless conversion.
(I couldn't make it simple or elegant - maybe someone else can!)
var plaground = "directly convert a single ping pong index to a plain index"
let L: Int = 10
let S: Int = 7
func ppiToIndex(_ ppi: Int) -> Int {
let inner = S+1 < (L-S) ? (S+1) : (L-S)
let pp = (ppi+1) / ( (ppi % 2 == 1) ? 2 : -2 )
let way = (S < L/2) ? -(inner-ppi-1) : (inner-ppi-1)
return (ppi < inner*2-1) ? S+pp : S+way
}
for i in 0..<L {
print(" \(i) \(ppiToIndex(i)) ")
}
inner is how many from the start inclusive to the nearer end inclusive.
pp is a full-on endless ping pong.
way is the correct direction +/- to add once you pass the inner area.
Think of how you'd do this with a deck of cards, or a set of matchsticks. Just split the series into two at the point where you want to start, reverse the order of one of the resulting series, and alternate pulling values off the two series.
Here's a utility that alternates between two series until both are exhausted:
func alternateUntilBothAreExhausted<T> (arr1:Array<T>, arr2:Array<T>)
-> Array<T> {
var result = Array<T>()
var arr1 = arr1; var arr2 = arr2
while true {
if let last1 = arr1.popLast() {
result.append(last1)
}
if let last2 = arr2.popLast() {
result.append(last2)
}
if arr1.isEmpty && arr2.isEmpty {
return result
}
}
}
So we start with one series, split it, reverse one, and alternate:
func pingPong<T>(array:Array<T>, startingAtIndex ix:Int) -> Array<T> {
let arr1 = array[..<ix]
let arr2 = array[ix...]
return alternateUntilBothAreExhausted(
arr1: Array(arr1), arr2: Array(arr2.reversed()))
}
Example:
let ping = pingPong(array: Array(0..<10), startingAtIndex:4)
// [3, 4, 2, 5, 1, 6, 0, 7, 8, 9]
Wrapping that up in your desired syntax is trivial and is left as an exercise for the reader.

why my code is slow when finding Fibonacci sum?

I'm writing answers for project Euler Questions in this repo
but having some performance issues in my solution
Question 2:
Each new term in the Fibonacci sequence is generated by adding the previous two terms.
By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
My Solution is
func solution2()
{
func fibonacci(number: Int) -> (Int)
{
if number <= 1
{
return number
}
else
{
return fibonacci(number - 1) + fibonacci(number - 2)
}
}
var sum = 0
print("calculating...")
for index in 2..<50
{
print (index)
if (fibonacci(index) % 2 == 0)
{
sum += fibonacci(index)
}
}
print(sum)
}
My Question is, why it gets super slow after iteration 42, i want to do it for 4000000 as the question says, any help?
solution 2
func solution2_fast()
{
var phiOne : Double = (1.0 + sqrt(5.0)) / 2.0
var phiTwo : Double = (1.0 - sqrt(5.0)) / 2.0
func findFibonacciNumber (nthNumber : Double) -> Int64
{
let nthNumber : Double = (pow(phiOne, nthNumber) - (pow(phiTwo, nthNumber))) / sqrt(5.0)
return Int64(nthNumber)
}
var sum : Int64 = 0
print("calculating...")
for index in 2..<4000000
{
print (index)
let f = findFibonacciNumber(Double(index))
if (f % 2 == 0)
{
sum += f
}
}
print(sum)
}
The most important thing about PE questions is to think about what it is asking.
This is not asking you to produce all Fibonacci numbers F(n) less than 4000000. It is asking for the sum of all even F(n) less than 4000000.
Think about the sum of all F(n) where F(n) < 10.
1 + 2 + 3 + 5 + 8
I could do this by calculating F(1), then F(2), then F(3), and so on... and then checking they are less than 10 before adding them up.
Or I could store two variables...
F1 = 1
F2 = 2
And a total...
Total = 3
Now I can turn this into a while loop and lose the recursion altogether. In fact, the most complex thing I'm doing is adding two numbers together...
I came up with this...
func sumEvenFibonacci(lessThan limit: Int) -> Int {
// store the first two Fibonacci numbers
var n1 = 1
var n2 = 2
// and a cumulative total
var total = 0
// repeat until you hit the limit
while n2 < limit {
// if the current Fibonacci is even then add to total
if n2 % 2 == 0 {
total += n2
}
// move the stored Fibonacci numbers up by one.
let temp = n2
n2 = n2 + n1
n1 = temp
}
return total
}
It runs in a fraction of a second.
sumEvenFibonacci(lessThan: 4000000)
Finds the correct answer.
In fact this... sumEvenFibonacci(lessThan: 1000000000000000000) runs in about half a second.
The second solution seems to be fast(er) although an Int64 will not be sufficient to store the result. The sum of Fibonacci numbers from 2..91 is 7,527,100,471,027,205,936 but the largest number you can store in an Int64 is 9,223,372,036,854,775,807. For this you need to use some other types like BigInteger
Because you use the recursive, and it cache in the memory.If you iteration 42, it maybe has so many fibonacci function in your memory, and recursive.So it isn't suitable for recursive, and you can store the result in the array, not the reason of the swift.
this is the answer in two different ways
func solution2_recursive()
{
func fibonacci(number: Int) -> (Int)
{
if number <= 1
{
return number
}
else
{
return fibonacci(number - 1) + fibonacci(number - 2)
}
}
var sum = 0
print("calculating...")
for index in 2..<50
{
print (index)
let f = fibonacci(index)
if( f < 4000000)
{
if (f % 2 == 0)
{
sum += f
}
}
else
{
print(sum)
return
}
}
}
solution 2
func solution2()
{
var phiOne : Double = (1.0 + sqrt(5.0)) / 2.0
var phiTwo : Double = (1.0 - sqrt(5.0)) / 2.0
func findFibonacciNumber (nthNumber : Double) -> Int64
{
let nthNumber : Double = (pow(phiOne, nthNumber) - (pow(phiTwo, nthNumber))) / sqrt(5.0)
return Int64(nthNumber)
}
var sum : Int64 = 0
print("calculating...")
for index in 2..<50
{
let f = findFibonacciNumber(Double(index))
if(f < 4000000)
{
if (f % 2 == 0)
{
sum += f
}
}
else
{
print(sum)
return
}
}
}

Generate a random number NOT divisible by x?

I'm using rand(1..10) * 3 to generate a random number divisible by three.
Is there a simple way to generate a random number that's NOT divisible by three (or any other number) without having to sample from an array?
k = rand(0..1000)
out = k + k/2 + 1 # The '/' here is integer division.
0 -> 1
1 -> 2
2 -> 4
3 -> 5
4 -> 7
5 -> 8
6 -> 10
...
int getNumberNotDivisibleBy9()
{
srand(time(NULL));
int randm;
randm = rand();
while (randm % 9 == 0)
randm = rand();
return randm;
}
Something like this maybe?
y = 3
x = nil
loop { break if (x=rand(1..10))%y !=0 }

Swift convert decimal String to UInt8-Array

I have a very long String (600+ characters) holding a big decimal value (yes I know - sounds like a BigInteger) and need the byte representation of this value.
Is there any easy way to archive this with swift?
static func decimalStringToUInt8Array(decimalString:String) -> [UInt8] {
...
}
Edit: Updated for Swift 5
I wrote you a function to convert your number string. This is written in Swift 5 (originally Swift 1.2).
func decimalStringToUInt8Array(_ decimalString: String) -> [UInt8] {
// Convert input string into array of Int digits
let digits = Array(decimalString).compactMap { Int(String($0)) }
// Nothing to process? Return an empty array.
guard digits.count > 0 else { return [] }
let numdigits = digits.count
// Array to hold the result, in reverse order
var bytes = [UInt8]()
// Convert array of digits into array of Int values each
// representing 6 digits of the original number. Six digits
// was chosen to work on 32-bit and 64-bit systems.
// Compute length of first number. It will be less than 6 if
// there isn't a multiple of 6 digits in the number.
var ints = Array(repeating: 0, count: (numdigits + 5)/6)
var rem = numdigits % 6
if rem == 0 {
rem = 6
}
var index = 0
var accum = 0
for digit in digits {
accum = accum * 10 + digit
rem -= 1
if rem == 0 {
rem = 6
ints[index] = accum
index += 1
accum = 0
}
}
// Repeatedly divide value by 256, accumulating the remainders.
// Repeat until original number is zero
while ints.count > 0 {
var carry = 0
for (index, value) in ints.enumerated() {
var total = carry * 1000000 + value
carry = total % 256
total /= 256
ints[index] = total
}
bytes.append(UInt8(truncatingIfNeeded: carry))
// Remove leading Ints that have become zero.
while ints.count > 0 && ints[0] == 0 {
ints.remove(at: 0)
}
}
// Reverse the array and return it
return bytes.reversed()
}
print(decimalStringToUInt8Array("0")) // prints "[0]"
print(decimalStringToUInt8Array("255")) // prints "[255]"
print(decimalStringToUInt8Array("256")) // prints "[1,0]"
print(decimalStringToUInt8Array("1024")) // prints "[4,0]"
print(decimalStringToUInt8Array("16777216")) // prints "[1,0,0,0]"
Here's the reverse function. You'll notice it is very similar:
func uInt8ArrayToDecimalString(_ uint8array: [UInt8]) -> String {
// Nothing to process? Return an empty string.
guard uint8array.count > 0 else { return "" }
// For efficiency in calculation, combine 3 bytes into one Int.
let numvalues = uint8array.count
var ints = Array(repeating: 0, count: (numvalues + 2)/3)
var rem = numvalues % 3
if rem == 0 {
rem = 3
}
var index = 0
var accum = 0
for value in uint8array {
accum = accum * 256 + Int(value)
rem -= 1
if rem == 0 {
rem = 3
ints[index] = accum
index += 1
accum = 0
}
}
// Array to hold the result, in reverse order
var digits = [Int]()
// Repeatedly divide value by 10, accumulating the remainders.
// Repeat until original number is zero
while ints.count > 0 {
var carry = 0
for (index, value) in ints.enumerated() {
var total = carry * 256 * 256 * 256 + value
carry = total % 10
total /= 10
ints[index] = total
}
digits.append(carry)
// Remove leading Ints that have become zero.
while ints.count > 0 && ints[0] == 0 {
ints.remove(at: 0)
}
}
// Reverse the digits array, convert them to String, and join them
return digits.reversed().map(String.init).joined()
}
Doing a round trip test to make sure we get back to where we started:
let a = "1234567890987654321333555777999888666444222000111"
let b = decimalStringToUInt8Array(a)
let c = uInt8ArrayToDecimalString(b)
if a == c {
print("success")
} else {
print("failure")
}
success
Check that eight 255 bytes is the same as UInt64.max:
print(uInt8ArrayToDecimalString([255, 255, 255, 255, 255, 255, 255, 255]))
print(UInt64.max)
18446744073709551615
18446744073709551615
You can use the NSData(int: Int, size: Int) method to get an Int to NSData, and then get the bytes from NSData to an array: [UInt8].
Once you know that, the only thing is to know the size of your array. Darwin comes in handy there with the powfunction. Here is a working example:
func stringToUInt8(string: String) -> [UInt8] {
if let int = string.toInt() {
let power: Float = 1.0 / 16
let size = Int(floor(powf(Float(int), power)) + 1)
let data = NSData(bytes: &int, length: size)
var b = [UInt8](count: size, repeatedValue: 0)
return data.getBytes(&b, length: size)
}
}
You can always do:
let bytes = [UInt8](decimalString.utf8)
If you want the UTF-8 bytes.
Provided you had division implemented on your decimal string you could divide by 256 repeatedly. The reminder of the first division is the your least significant byte.
Here's an example of division by a scalar in C (assumed the length of the number is stored in A[0] and writes the result in the same array):
void div(int A[], int B)
{
int i, t = 0;
for (i = A[0]; i > 0; i--, t %= B)
A[i] = (t = t * 10 + A[i]) / B;
for (; A[0] > 1 && !A[A[0]]; A[0]--);
}

Check if an integer is divisible by another integer (Swift)

I need to check if an integer is divisible by another integer exactly.
If not I would like to round it up to the closest multiple of the number.
Example:
var numberOne = 3
var numberTwo = 5
numberTwo is not a multiple of numberOne therefore I would like it to round numberTwo up to 6.
How would I do this?
Thank you
1) If you want to check or an integer is divided by another integer:
Swift 5
if numberOne.isMultiple(of: numberTwo) { ... }
Swift 4 or less
if numberOne % numberTwo == 0 { ... }
2) Function to round to the closest multiple value:
func roundToClosestMultipleNumber(_ numberOne: Int, _ numberTwo: Int) -> Int {
var result: Int = numberOne
if numberOne % numberTwo != 0 {
if numberOne < numberTwo {
result = numberTwo
} else {
result = (numberOne / numberTwo + 1) * numberTwo
}
}
return result
}
You can use the modulo operator %:
numberTwo % numberOne == 0
The modulo finds the remainder of an integer division between 2 numbers, so for example:
20 / 3 = 6
20 % 3 = 20 - 6 * 3 = 2
The result of 20/3 is 6.666667 - the dividend (20) minus the integer part of that division multiplied by the divisor (3 * 6) is the modulo (20 - 6 * 3) , equal to 2 in this case.
If the modulo is zero, then the dividend is a multiple of the divisor
More info about the modulo at this wikipedia page.
Swift 5
isMultiple(of:)
Returns true if this value is a multiple of the given
value, and false otherwise.
func isMultiple(of other: Int) -> Bool
let rowNumber = 4
if rowNumber.isMultiple(of: 2) {
print("Even")
} else {
print("Odd")
}
You can use truncatingRemainder. E.g.,
if number.truncatingRemainder(dividingBy: 10) == 0 {
print("number is divisible by 10")
}

Resources