Skip to main content

Coding Exercise

Coding Exercise

In this excercise we asked two developers to create solution for the very same problem.

There is an input array of number of votes (eg. [3, 5, 6, 2, 0]) and they need to provide a whole(!) percentages of each vote considering the total number of votes (eg. [Int]), the sum of the percentages (obviously) need to to 100 at the end of the day – which requires them to cheat mathematics a bit, as rounding the percetages to whole number may have a loss or an overflow.

We got two Swift developers from different levels and experience to complete the task on their own chosen way.

Here are the results, which you can run in Playgound in Xcode, anytime (copy paste).

Developer #1

func responsePercentages1(fromVotes votes: [Int]) -> [Int] {

    let totalResponseCount = votes.reduce(0, +)

    var percentages = [Double]()

    for vote in votes {
        if totalResponseCount == 0 {
            percentages.append(0.0)
        } else {
            percentages.append(Double(vote) / Double(totalResponseCount))
        }
    }

    let realPercentages = percentages.map { $0 * 100 }
    let flooredPercentages = realPercentages.map { floor($0) }
    let summedPercentages = flooredPercentages.reduce(0, +)
    let difference: Int = 100 - Int(summedPercentages)

    var newPercentages = [Int]()
    for (index, percentage) in realPercentages.enumerated() {
        if index < difference {
            newPercentages.append(Int(percentage) + 1)
        } else {
            newPercentages.append(Int(percentage))
        }
    }
    return newPercentages
}

responsePercentages1(fromVotes: [3, 5, 6, 2, 0])

Developer #2

func responsePercentages2(fromVotes votes: [Int]) -> [Int] {

    let counts = votes
    let sum = counts.reduce(0, +)

    guard sum > 0 else { return counts.map { _ in 0 } }
    var candy = counts.map { Int(100.0 * Double($0) / Double(sum)) }
    let difference = candy.reduce(-100, +)

    guard
        difference != 0,
        let max = candy.max(),
        let index = candy.firstIndex(of: max)
    else { return candy }

    candy.replaceSubrange((index...index), with: [max-difference])
    return candy
}

responsePercentages2(fromVotes: [3, 5, 6, 2, 0])

Summary 

I will let you to be the judge of which one seems to be a better, cleaner, more understandble solution to this particular problem. Both solutions try to cover the edge cases on their own way, but the output seems slighlty different because of the different choice of cheating the calculation to get 100 as a sum.

Do you think these are good solutions? Or do you have a better algorithm?

Comments