2
\$\begingroup\$

I solve this problem in Swift. Looking for feedback on my code or a better solution:

enter image description here

import Foundation

// parses line to return array of numbers in string format
func readIntegers() -> [String] {
    return readLine()!.componentsSeparatedByString(" ").map { $0 }
}

// left rotates the array by a given input
func leftRotation() -> String {
    let input = readIntegers()
    let array = readIntegers()
    var newArray = [String](count: Int(input[0])!, repeatedValue: "")
    let (count, rotations) = (Int(input[0])!, Int(input[1])!)

    for index in 0..<count {
        // newIndex after rotation
        let newIndex = index + rotations
        if newIndex < count  { // up until count
            newArray[index] = array[newIndex]
        } else { // loops back to beginning index of array
            newArray[index] = array[newIndex - count]
        }
    }
    // joins the array
    return newArray.joinWithSeparator(" ")
}

print(leftRotation())
\$\endgroup\$

4 Answers 4

2
\$\begingroup\$

I am not a swift programmer so i will not be able to give you exact advice on how to improve the quality of your code but rather the algorithm you used to solve this challenge and nitpicks i have with your solution.

Firstly lets look at the question itself.

It asks you to print out the new array. why are you creating it and turning it back into a string?

That considered, you can simply perform 2 for loops

1 for loop up until the "break" where the array has overflown, and a second for loop for the rest of the untouched array.

like that

therfor we can simply print out the elements at location

d to n

and then the elements from

0 to d

This will shorten your code considerably and make it run a whole lot faster because no extra variables are needed and you arent doing array manipilation, its just a way to iterate over an array

\$\endgroup\$
1
\$\begingroup\$

First, whenever you see a phrase like "given x, perform y" you should think of the 'x' as inputs into a function that returns the result of 'y'.

So you should have something like func rotate(array array: [Int], left distance: Int) -> [Int] somewhere in your code. Getting the data from the user and displaying it should be separate from the function that does the work.

Second, the problem is underspecified. What if the distance to shift left is negative? Your solution will crash in the middle of the algorithm. It would be better to use the precondition function to make it explicit that this algorithm won't work with a negative count.

Lastly, Swift's array class has methods to make this much more elegant. You should be able to implement this without a loop & without any vars. (Read up on the functions dropFirst and dropLast.)

\$\endgroup\$
0
\$\begingroup\$

This is what I did but still looking for any better answer available for this solution:

import Foundation

extension Array {
    func shiftedLeft(by rawOffset: Int = 1) -> Array {
        let rotation_amount = rawOffset % count
        let offset = rotation_amount < 0 ? count + rotation_amount : rotation_amount
        return Array(self[offset ..< count] + self[0 ..< offset])
    }

    mutating func shiftLeft(by rawOffset: Int = 1) {
        self = self.shiftedLeft(by: rawOffset)
    }
}

class ArrayRotation {

    func readIntegers() -> [String] {
        return (readLine()?.components(separatedBy: " "))!
    }

    func rotateArray(){

        let componentsMutableArray = readIntegers()
        let array = readIntegers()
        let number_of_rotation = Int(componentsMutableArray[1])
        print(array.shiftedLeft(by: number_of_rotation!).joined(separator: " "))

    }

}

Looking for suggestions to improve, please share your thoughts too. Thanks

\$\endgroup\$
0
\$\begingroup\$

I've tried several variations and appart for a minor improvement on the offset calculation (to allow negatives to rotate to the right), I couldn't find anything meaningful to add:

  public func shiftedLeft(by rotation:Int) -> [Element]
  {  
     guard count > 1 else { return self}

     let offset = ( count - rotation%count ) % count
     return Array(self[offset..<count] + self[0..<offset]) 
  } 
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.