Hello i practice on hackerRank using swift and now i have a problem. My code works great in swift playground, and return the expected result, but in HackerRank i have runtime error ~ no response on stdout ~ I've tried to reset code and refresh page. What could be the problem?
func diagonalDifference(arr: [[Int]]) -> Int {
// Write your code here
let rowNumber = arr[0][0]
var leftD = 0
var rightD = 0
for i in 1...rowNumber {
leftD += arr[i][i - 1]
}
var increasedNum = 0
for i in (1...rowNumber).reversed() {
rightD += arr[i][increasedNum]
increasedNum += 1
}
var absoluteDifference = leftD - rightD
if absoluteDifference < 0 {
absoluteDifference = absoluteDifference * -1
}
return absoluteDifference
}
Here is the challenge page:
https://www.hackerrank.com/challenges/diagonal-difference/problem
Your problem is a misunderstanding of what is passed to your diagonalDifference() function. The code which calls that function uses the first line of input to correctly size the array, but that value is not passed to your function in arr[0][0]. Instead, you should use arr.count to determine the dimensions of the array, then you should be indexing the array as 0..<arr.count.
To fix your code
change:
let rowNumber = arr[0][0]
to:
let rowNumber = arr.count
change:
leftD += arr[i][i - 1]
to:
leftD += arr[i][i]
And change both instances of
1...rowNumber
to:
0..<rowNumber
func diagonalDifference(arr: [[Int]]) -> Int {
var difference = 0
for i in 0..<arr.count {
difference += (arr[i][i] - arr[i][arr.count-1-i])
}
return Int(abs(difference))
}
Related
If I want to evaluate time performance of a few algos using Date() or Dispatch() how can I create a function that does this?
For example this binary search algo. How can I pass it as a closure parameter and have the closure do all of the time performance measuring using any of the Swift time keeping methods below? Please answer with an example of a closure. Thanks.
let startingPoint = Date()
let startingPoint = Dispatch().now
func binarySearchForValue(searchValue: Int, array: [Int]) -> Bool {
var leftIndex = 0
var rightIndex = array.count - 1
while leftIndex <= rightIndex {
let middleIndex = (leftIndex + rightIndex) / 2
let middleValue = array[middleIndex]
if middleValue == searchValue {
return true
}
if searchValue < middleValue {
rightIndex = middleIndex - 1
}
if searchValue > middleValue {
leftIndex = middleIndex + 1
}
}
return false
}
Since you may want to measure different functions, it probably makes sense to capture the arguments for the function in the closure instead of including their types in the signature. But I did use a generic type for the return value. I hope that this is what you're after:
func measure<R>(_ label: String, operation: () -> R) -> R {
let start = DispatchTime.now()
let result = operation()
let end = DispatchTime.now()
let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
let timeInterval = Double(nanoTime) / 1_000_000_000
print(String(format: "%#: %.9f s", label, timeInterval))
return result
}
Here's how you use it:
let result = measure("search") { binarySearchForValue(searchValue: 3, array: [1, 3, 8]) }
print(result) // that's the result of the function that was measured, not the measurement
measure("some function") { functionWithoutReturnValue() }
If the function has no return value, R will be (), so that should work too. Just don't assign the result to anything (see the example above). If you want to do something with the measurement other than printing it to the console, you can do that, too. But you didn't specify that in your question, so I went with print.
Not sure what exactly you are after here and this solution below will only fit one specific function signature to test
func testBench(search: Int, array: [Int], testCase test: (Int, [Int]) -> Bool) {
let start = DispatchTime.now()
test(search, array)
let end = DispatchTime.now()
print("\(start) - \(end)")
}
called like this
testBench(search: 3, array: [6,7,5,3]) {binarySearchForValue(searchValue: $0, array: $1)}
You should use XCTest to measure the performance ... It gives you proper stats for your method in terms of performance
i.e.
func testMyCodesPerformance() {
measureBlock {
someClass.doSomethingFancy()
}
}
You can do lot more using XCTest measureBlock for performance testing
I faced situation, which is
let IntA = IntB - IntC
let usingInt = IntA <= 0 ? 0 : IntA
But, Just not smart I felt.
Is there some cool methods??
You can use the max function for this:
let IntA = IntB - IntC
let usingInt = max(IntA, 0)
How about using the setter methods to do the same thing suggested in the other answer?
var result: Int = 0 {
didSet {
result = max(0, result)
}
}
Use this variable to store your calculation result.
result = 4 - 5
print(result) //0
I'm trying to write a function that has arrayOne, arrayTwo, and arrayThree as inputs. If arrayTwo has any 0s as its last elements, the function is supposed to remove these elements from the array, as well as the same elements from arrayOne. When I run the code and try to test it, I get the error: "Terminated by signal 4".
What could the problem be?
var arrayOneNew = arrayOne
var arrayTwoNew = arrayTwo
var arrayThreeNew = arrayThree
var endElement = arrayTwoNew.last
if endElement == 0 {
var counter = arrayTwoNew.count
while arrayTwoNew[counter] == 0 {
var elementToBeRemoved = arrayTwoNew.remove(at: counter - 1)
var 2ndElementToBeRemoved = arrayOneNew.remove(at: counter - 1)
}
}
Your main problem is that you are setting counter to arrayTwoNew.count which is 1 bigger than the last valid index in arrayTwoNew, so while arrayTwoNew[counter] == 0 crashes with index out of range.
Also:
var elementToBeRemoved = arrayTwoNew.remove(at: counter - 1)
is probably meant to remove the last item from arrayTwoNew, but that is more easily accomplished with:
arrayTwoNew.removeLast()
especially since you're not using elementToBeRemoved.
I think you're trying to do this:
while arrayTwoNew.last == 0 {
arrayTwoNew.removeLast()
arrayOneNew.removeLast()
arrayThreeNew.removeLast()
}
You are creating a new array "arrayTwoNew" which is mixed up with the original one at
var arrayTwoNew = arrayTwoNew.remove(at: counter - 1)
Now I'm also struggling with your .remove - this returns an element so won't work. I'd usually use a filter here but I'm not sure what you are doing!
//code with remove taken out (replace with filter?) to get you started:
let arrayOne = [1,2,3]
let arrayTwo = [2,3,4]
let arrayThree = [5,6,7]
var arrayOneNew = arrayOne
var arrayTwoNew = arrayTwo
var arrayThreeNew = arrayThree
var endIndex = arrayTwoNew.last
if endIndex == 0 {
let counter = arrayTwoNew.count
// arrayTwoNew = arrayTwoNew.remove(at: counter - 1)
while arrayTwoNew[counter] == 0 {
// arrayOneNew = arrayOneNew.remove(at: counter - 1)
}
}
I have update Xcode to 7.3 and now I have a warning to the function that I use to create random strings.
I have tried to change the for statement with for (i in 0 ..< len){...} however, the warning became an error.
How can I remove the warning?
static func randomStringWithLength (len : Int) -> NSString {
let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomString : NSMutableString = NSMutableString(capacity: len)
for (var i=0; i < len; i += 1){ // warning
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
}
return randomString
}
C-style for loop has been deprecated in Swift 3. You can continue using it for a while, but they will certainly disappear in the future.
You can rewrite your loop to Swift's style:
for i in 0..<len {
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
}
Since you don't use i at all in the loop's body, you can replace it with:
for _ in 0..<len {
// do stuffs
}
This BLOG saved my life.
INCREMENTING
for i in 0 ..< len {
}
DECREMENTING
for i in (0 ..< len).reverse() {
}
NON-SEQUENTIAL INDEXING
Using where
for i in (0 ..< len) where i % 2 == 0 {
}
Using striding to or through
for i in 0.stride(to: len, by: 2) {
}
in Swift 3 it's been an error
some general replacement was posted and just add
For Swift 3 and need to change the "index"
for var index in stride(from: 0, to: 10, by: 1){}
I've had success with the following. You can use the for loop as follows - note that the for loop is inclusive so you may need to check that len is actually greater than 0:
for i in 0...len - 1 {
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
}
Or you can use this:
for i in 0 ..< len {
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
}
BTW it appears XCode 7.x does help you to get there but it's a two step process. First you have to change your increment operator from (say) i++ to i += 1 and then XCode warning helps you modify the loop.
I've write a simple code:
extension String {
func trailingSpaces (width: Int) -> String {
var s = "\(self)"
for i in count(s)..<width {
s = s + " "
}
return s
}
func leadingSpaces (width: Int) -> String {
var s = "\(self)"
for i in count(s)..<width {
s = " " + s
}
return s
}
}
class ViewController: UIViewController {
var users = ["Marco", "Gianni", "Antonio", "Giulio", "Franco"]
var ages = [29, 45, 17, 33, 37]
override func viewDidLoad() {
super.viewDidLoad()
var merged = [String: Int] ()
var totalAge = 0.0
for var i = 0; i < ages.count; i++ {
merged[users[i]] = ages[i]
}
for user in sorted(merged.keys) {
let age = merged[user]
totalAge += Double(age!)
let paddedUser = user.trailingSpaces(10)
let paddedAge = "\(age)".leadingSpaces(3)
println("\(paddedUser) \(age!)")
}
println("\n\(merged.count) users")
println("average age: \(totalAge / Double(merged.count))")
}
}
but I can't make it work the leadingSpaces function and I can't understand the reason, it's quite identical to the other extension func that works.
It give the error
fatal error: Can't form Range with end < start
on runtime
in case you run into this kind of problem, always do a println() of the variable you are using
println("\(age)") right before let paddedAge = "\(age!)".leadingSpaces(3)
reveals the problem
age is an optional, meaning that you are trying to do the padding on a String which has this value "Optional(17)"
Thus, your count(s) is higher than 3, and you have an invalid range
Your variable age is not an Int - it's an optional - Int?. You know this already as you are unwrapping it in the lines totalAge += Double(age!) and println("\(paddedUser) \(age!)") - but you are not unwrapping it in the failing line let paddedAge = "\(age)".leadingSpaces(3). The string being passed to leadingSpaces is not "17", it's "Optional(17)", which is why your padding function is failing, as the length is greater than the requested width.
Having said that, as the commentator #milo256 points out, Swift can only iterate upwards, and so unless you put a check on width >= .count in your padding functions they will crash at some point.