Enhancing a Voting System in Kotlin: Implementing New Functionalities and Ensuring Compatibility

Introduction

Welcome back to another exciting session where we learn about enhancing existing functionality without causing regressions. Our scenario today involves designing a voting system. We'll start with the basic implementation of the voting system and gradually introduce additional elements of complexity.

Starter Task Review

In our initial task, we created a simple voting system in Kotlin with a set of basic functionalities:

  • fun registerCandidate(candidateId: String): Boolean: This function is used for adding new candidates to our system.
  • fun vote(timestamp: Long, voterId: String, candidateId: String): Boolean: This function facilitates users casting their votes. Each vote is given a timestamp.
  • fun getVotes(candidateId: String): Int?: This function retrieves the total number of votes for a given candidate.
  • fun topNCandidates(n: Int): List<String>: We also want to add a leaderboard functionality to our system. This function returns the top n candidates sorted by the number of votes.

Initial Solution Development

Let's jump into the Kotlin code and begin the implementation of our starter task. Here, we use Kotlin's mutableMapOf() and mutableListOf() as the core of our design. These collections allow us to have dynamic lists keyed based on candidate IDs and voter IDs, which will greatly simplify our design.

class VotingSystem {
    private val candidates: MutableMap<String, Int> = mutableMapOf()  // Stores candidate_id as key and votes as value
    private val voters: MutableMap<String, VotingHistory> = mutableMapOf()  // Tracks each voter's voting history

    fun registerCandidate(candidateId: String): Boolean {
        if (candidates.containsKey(candidateId)) {
            return false  // Candidate is already registered
        }
        candidates[candidateId] = 0  // Initialize candidates with 0 votes
        return true
    }

    fun vote(timestamp: Long, voterId: String, candidateId: String): Boolean {
        if (!candidates.containsKey(candidateId)) {
            return false  // Return false if candidate is not registered
        }
        val voterHistory = voters.computeIfAbsent(voterId) { VotingHistory() }
        voterHistory.votes.add(candidateId)  // Record the vote
        voterHistory.timestamps.add(timestamp)  // Record the time of the vote
        candidates[candidateId] = candidates[candidateId]!! + 1  // Increment vote count for the candidate
        return true
    }

    fun getVotes(candidateId: String): Int? {
        return candidates[candidateId]  // Retrieve vote count for a candidate or null if not found
    }

    fun topNCandidates(n: Int): List<String> {
        return candidates.entries
            .sortedByDescending { it.value }
            .take(n)
            .map { it.key }  // Return top n candidates based on votes
    }

    private class VotingHistory {
        val votes: MutableList<String> = mutableListOf()
        val timestamps: MutableList<Long> = mutableListOf()
    }
}
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal