Code iteration time out

var x = readLine()!.characters.split { $0 == " " }.map { Int(String($0))! }
var y = readLine()!.characters.split { $0 == " " }.map { Int(String($0))! }
var n = x[0]
var k = x[1]
var q = x[2]
for _ in 0..<k {
y.insert(y[n-1], at: y.startIndex) 
y.removeLast() } 

for _ in 0..<q {
var i = Int(readLine()!)!
print(y[i]) }


currently stuck on hackerrank where it gives you three Ints (n, k, q) as a string and then another line of n Ints as a string. It wants you to rotate the array right (remove the last index and put it at the start) k number of times and then it provides q number of queries about what element is at the index queried.


the above code works (the compiler must be Swift 2.0 because I can't use .components and have to use .split.) However, it times out on the larger ones, say 100000 100000 500 (array of 100000 Ints, rotate 100000 times and then query 500 times the different index and elements). I know in release build this would be fine but anyone know of a way to optimise this code in Swift to prevent time out in hackerrank a Swift compiler?


Thank you

You might have received replies sooner if you had made clear that this is for a HackerRank practice problem and not a competition.


I'll leave the implementation to you because you'll benefit from the practice, but my tip is to not actually rotate the array contents. For a given query index, calculate the corresponding original index and use that to retrieve the value from the original array.


(I don't understand why you say "the compiler must be Swift 2.0 because I can't use .components and have to use .split." HackerRank currently has a Swift 3.0.1 compiler and if your code imports Foundation (which is supported on HackerRank) then String will have the components(separatedBy:) method.)

Thank you for your time in assisting.


From your message I can understand that the given query index needs to have the rotation required minused from it in order to query the correct index. However, I get stuck on reiterating over the arry when I get 0 - k (rotation required) because the value comes out of index scope. Also, I thougth about deducting and then using abs().


Thank you for the hint and guidance - Also, RE: the compiler, I have only been doing Swift for 1+ month so excuse my naivity ...

Is reiterating over an array once you have come to the start index even possible - to get back to the end if there is overflow...


Thank you goldsdad

The modulo operator '%' can be employed to keep indices in the valid range 0 <= i < endIndex.


let endIndex = array.endIndex
let rotatedFirstIndex = endIndex - numberOfRightRotations % endIndex
let index = (rotatedFirstIndex + queryIndex) % endIndex

Thanks for the guidance but I have been stuck on this for a while... I even looked at the editorial which explains the route to the answer, but there is no Swift code or guidance. The expanation wasn't straight forward (for me anyway).


I implemented your code above into Playground and it works fine with the small case array - after that it runTime errors and fails on anything large (100000 72456 500). I have spent 6 hours today on it lol so I think I need to get some sleep and take a break...below is what I input:


var x = readLine()!.characters.split { $0 == " " }.map { Int(String($0))! }
var y = readLine()!.characters.split { $0 == " " }.map { Int(String($0))! }
var t = [Int]()


var n = x[0]
var k = x[1]
var q = x[2]

//appending the lines of queries to t based on q number of queries
while q != 0 {
    t.append(Int(readLine()!)!)
    q = q - 1
}


let endIndex = y.endIndex
let rotatedFirstIndex = endIndex - k % endIndex

//t is array of queries
for i in t {
    var index = (rotatedFirstIndex + t[i]) % endIndex
    print(y[index])
}
Accepted Answer

I entered the following solution at Hackerrank and it passed all tests:


import Foundation

let readLineOfInts = { readLine()!.components(separatedBy: " ").map{ Int($0)! } }

let parameters =  readLineOfInts()
let numberOfRightRotations = parameters[1]
let numberOfQueries = parameters[2]
let array = readLineOfInts()

let endIndex = array.endIndex
let rotatedFirstIndex = endIndex - numberOfRightRotations % endIndex

(0 ..< numberOfQueries)
  .lazy
  .map { _ in Int(readLine()!)! }
  .map { array[(rotatedFirstIndex + $0) % endIndex] }
  .forEach { print($0) }

Wow! Safe to say, I do not feel to bad about 'giving in' this time around as there is plenty in that code that I am yet to understand. Thank you for taking the time to assist. I have written out how I think that works below:


create a closure function with readLineOfInts

parameters are the first three Ints with the numberOfRR and numberOfQ being the para[1] and para[2].

Then recall the closure to get the array


End index = last index + 1

rotateIndex = endIndex - para[1](rightRotates) % modulo by endIndex (which is also count of array)


How does the last section work?

There is nothing calling (0..< numberOfQ) to start it and also the four following methods are out of any brackets?

.lazy = don't intiliase until called right?

.map I understand, take the next readLine and map it to an Int

.map within the array rotatedFirstIndex + the default value within the array modulo by endIndex

.forEach I have never seen either.


Thank you - I am certainly going to sit and study this answer to fully understand it - then rewrite ad understand.

(0 ..< numberOfQueries)
  .lazy
  .map { _ in Int(readLine()!)! }
  .map { array[(rotatedFirstIndex + $0) % endIndex] }
  .forEach { print($0) }


0 ..< numberOfQueries is a CountableRange: a struct which you can think of as similar to an array of consecutive values, but for which there's no actual storage of these values. Its lazy property didn't need to be used, but I wanted to prevent an array being stored by each of the maps chained after it. You'll find information about lazy and forEach in the Swift Standard Library reference. The omission of parentheses around the closures provided to the map and forEach calls is known as trailing closure syntax, which is explained in The Swift Programming Language guide, and I strongly recommend you read that guide.


The code could have been written as follows, but I wanted a little practice at writing in a more functional style.


for _ in 0 ..< numberOfQueries {
    let queryIndex = Int(readLine()!)!
    let value = array[(rotatedFirstIndex + queryIndex) % endIndex]
    print(value)
}
var x = readLine()!.characters.split { $0 == " " }.map { Int(String($0))! }.sorted(by: { $0 < $1 } )


var sum1: Int64 = 0
var sum2: Int64 = 0


(x.startIndex...x.index( 3, offsetBy: 0))
    .forEach( { sum1 += x[$0] } )


(x.index(0, offsetBy: 1)...x.index( 4, offsetBy: 0))
    .forEach( { sum2 += x[$0] } )


print(sum1, sum2)



I must thank you for these countable ranges! and the .forEach - they are revolutionary. Just cracked a case in a more effeicient way!


I have been reading the documentation as part of the free iTunes Ulearn Stanford course but I learn but quicker when I see it in practice after reading.


How long have you been working with Swift?


Thanks again for your help

Your new example can be written more concisely and clearly, which I'll demonstrate in several steps.


You've written:

var sum1: Int64 = 0
(x.startIndex...x.index( 3, offsetBy: 0))
    .forEach( { sum1 += x[$0] } )


x is an Array, so x.startIndex must be 0, and an index offset by 0 is the same index:

var sum1: Int64 = 0
(0 ... 3).forEach { sum1 += x[$0] }


We can iterate over a slice of an array:

var sum1: Int64 = 0
x[0 ... 3].forEach { sum1 += $0 }


We can use a slice's reduce method to sum its values:

let sum1: Int64 = x[0 ... 3].reduce(0, +)


In my opinion, 0 ..< n is clearer than 0 ... (n-1) when specifying the first n indices:

let sum1: Int64 = x[0 ..< 4].reduce(0, +)



> How long have you been working with Swift?

I've been playing with Swift for about 6 months, and largely learning by trying to solve problems posted in this forum.


Addendum:

.sorted(by: { $0 < $1 })
can be written as
.sorted(by: <)
, which can be even more concisely replaced with
.sorted()
.

Thank you for the assistance - what you have explicitly demonstrated there has signifgantly helped me. I am bookmarking these posts. I need to get more comfortable with the existing methods available to me, and then truncating my code.

I have been going for 1 month on Swift but never programmed before (dabbled in HTML5 and CSS) but WAY prefer programming, specificallly Swift.

Were you programming using a different language before (i.e. python?) and any tips to help me improve mine? Other than reading the Swift documentation regularly (which I am doing as part of my reading assignments and have even hand written almost all of it -_- lol).

Thanks again


EDIT: reason I ask about previous programming experience is because you seem very comfortable with code for only 6 months.

Decades ago, I learned BASIC, 6502 Assembler, Pascal, C and COBOL then stopped programming shortly before OOP exploded in popularity. I've occasionally written a little JavaScript, VBScript and VBA over the years. My recommendation for you at this early stage is to seek out a well-recommended course on core programming concepts, regardless of the language(s) used in the course; you'll soon become proficient at translating to Swift.

Sure, I will check some out and please, if you can recommend any yourself it would be greatly appreciated.


Thank you for your guidance and for taking so much time in repsonding to my posts!

Code iteration time out
 
 
Q