Enhancing a Voting System with C# for Robust Functionality

Introduction

Welcome back to another exciting session where we learn about enhancing existing functionality without causing regressions. Today, our scenario 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 C# with a set of basic functionalities:

  • bool RegisterCandidate(string candidateId): This method is used to add new candidates to our system.
  • bool Vote(long timestamp, string voterId, string candidateId): This method facilitates users casting their votes. Each vote is given a timestamp.
  • int? GetVotes(string candidateId): This method retrieves the total number of votes for a given candidate.
  • List<string> TopNCandidates(int n): We also want to add a leaderboard functionality to our system. This method returns the top n candidates sorted by the number of votes.

Initial Solution Development

Let's jump into the C# code and begin the implementation of our starter task. Here, we use C#'s built-in Dictionary and List 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.

using System;
using System.Collections.Generic;
using System.Linq;

public class VotingSystem {
    private Dictionary<string, int> candidates;  // Stores candidate_id as key and votes as value
    private Dictionary<string, VotingHistory> voters;  // Tracks each voter's voting history

    public VotingSystem() {
        this.candidates = new Dictionary<string, int>();  // Initialize candidates dictionary
        this.voters = new Dictionary<string, VotingHistory>();  // Initialize voters dictionary
    }

    public bool RegisterCandidate(string candidateId) {
        if (candidates.ContainsKey(candidateId)) {
            return false;  // Candidate is already registered
        }
        candidates[candidateId] = 0;  // Initialize candidates with 0 votes
        return true;
    }

    public bool Vote(long timestamp, string voterId, string candidateId) {
        if (!candidates.ContainsKey(candidateId)) {
            return false;  // Return false if candidate is not registered
        }
        if (!voters.TryGetValue(voterId, out var voterHistory)) {
            voterHistory = new VotingHistory();
            voters[voterId] = voterHistory;
        }
        voterHistory.Votes.Add(candidateId);  // Record the vote
        voterHistory.Timestamps.Add(timestamp);  // Record the time of the vote
        candidates[candidateId]++;  // Increment vote count for the candidate
        return true;
    }

    public int? GetVotes(string candidateId) {
        return candidates.ContainsKey(candidateId) ? candidates[candidateId] : (int?)null;  // Retrieve vote count for a candidate or null if not found
    }

    public List<string> TopNCandidates(int n) {
        return candidates.OrderByDescending(entry => entry.Value)
                         .Take(n)
                         .Select(entry => entry.Key)
                         .ToList();  // Return top n candidates based on votes
    }

    private class VotingHistory {
        public List<string> Votes { get; }
        public List<long> Timestamps { get; }

        public VotingHistory() {
            this.Votes = new List<string>();
            this.Timestamps = new List<long>();
        }
    }
}
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