/// <summary> /// Custom Input Action for the 'Breaker of Chains' problem /// </summary> /// <param name="input">The user input which triggered the custom action</param> /// <param name="southeros"></param> /// <returns></returns> /// <remarks>We don't particularly require the input data in this function but we keep it anyway to match the function signature</remarks> public string CustomInputAction(string input, ISoutheros southeros) { // Once a ruler has been found, we no longer need to hold a ballot if (southeros.RulingKingdom != null) { return(string.Format(Utility.RulerCrownedMessage, southeros.RulingKingdom.Name)); } // Declare local variables var output = string.Empty; var noOfCompetitors = 0; var maxBallotRounds = 1000; var messagesToChoose = 6; // Read the list of competitors from the user var possibleCandidates = console.ReadLine().Trim().Replace(',', ' ').Split(" ", StringSplitOptions.RemoveEmptyEntries); // Try parsing the user input into valid kingdoms foreach (var candidate in possibleCandidates) { if (!string.IsNullOrWhiteSpace(candidate) && Enum.TryParse(candidate, true, out Kingdoms competingKingdom)) { southeros.AllKingdoms[competingKingdom].IsCompeting = true; noOfCompetitors++; } else { output += string.Format(Utility.InvalidKingdomMessage, candidate); } } // We need atleast two kingdoms competing for the crown if (noOfCompetitors < 2) { output += Utility.NoCompetingKingdomsMessage; } // and atmost one less than all of them else if (noOfCompetitors < Enum.GetValues(typeof(Kingdoms)).Length) { // Summon high priest var highPriest = new HighPriest(messagesToChoose, maxBallotRounds, console); // FindRulerByBallot return false if we don't have a ruler after maxBallotRounds if (!highPriest.HoldBallot(southeros)) { output += Utility.BallotTookTooLongMessage; } } // If all the kingdoms compete, we can't proceed else { output += Utility.TooManyKingdomsMessage; } return(output); }
// Custom Input Action for the 'A Golden Crown' problem public string CustomInputAction(string input, ISoutheros southeros) { // Declare local variables var output = string.Empty; // The only competing kingdom as per the problem is the SpaceKingdom (this can // be changed here any time) var competingKingdom = Kingdoms.Space; // Required right to rule is the number of kingdoms the competingKingdom kingdom // needs to be allied with in order to be crowned as the ruler var reqRightToRule = 3; // Give the gorilla king of the Space kingdom a name southeros.AllKingdoms[Kingdoms.Space].King = "King Shan"; // Try parsing the input into target kingdom and message var index = input.IndexOf('"'); var recipient = input.Substring(0, index).Trim(new char[] { ' ', ',' }); var messageText = input.Substring(index + 1, input.LastIndexOf('"') - index - 1); // Try parsing the target kingdom to verify target is valid if (Enum.TryParse(recipient, true, out Kingdoms recipientKingdom)) { // Create message object var message = new Message(competingKingdom, recipientKingdom, messageText); // Send out message southeros.AllKingdoms[competingKingdom].SendMessage(southeros.AllKingdoms[recipientKingdom], message); // Check if the competeing kingdom now has the required number of allies if (southeros.AllKingdoms[competingKingdom].Allies.Count >= reqRightToRule) { // If so, set the value for the ruling kingdom southeros.RulingKingdom = southeros.AllKingdoms[competingKingdom]; } } // If target is invalid, return appropriate error message else { output = string.Format(Utility.InvalidKingdomMessage, recipient); } return(output); }
/// <summary> /// Finds the ruler of Southeros using a ballot system /// </summary> /// <param name="southeros">Reference to a ISoutheros implemented class object</param> /// <returns>Returns a boolean denoting whether a king was crowned or not</returns> public bool HoldBallot(ISoutheros southeros) { // Randomizer to choose message to write var rnd = new Random(); //Ballot round int round = 0; // The drawing from the ballot goes on until a winner is decided or we reach maxRounds while (southeros.RulingKingdom == null && ++round <= maxRounds) { // Get a new ballot box var ballotBox = new BallotBox(); // Round up all kingdoms competing for the throne var competingKingdoms = southeros.AllKingdoms.Where(kv => kv.Value.IsCompeting).Select(kv => kv.Key).ToList(); // Each competing kingdom composes messages... foreach (var competitor in competingKingdoms) { // ...for all the other kingdoms foreach (var reciver in southeros.AllKingdoms.Keys) { // ...except itself ofcourse ¯\_(ツ)_/¯ if (reciver == competitor) { continue; } var newRequest = new Message(competitor, reciver, Utility.listOfMessages[rnd.Next(Utility.listOfMessages.Count)]); ballotBox.DropMessage(newRequest); } } // The High Priest of Southeros chooses the messages to send out var choosenMessages = PickRandomMessages(ballotBox); // Hand over the messages foreach (var message in choosenMessages) { southeros.AllKingdoms[message.Sender].SendMessage(southeros.AllKingdoms[message.Recipient], message); } // Declare results console.WriteLine($"{Environment.NewLine}Results after round {Utility.IntegerToWritten(round)} ballot count"); // Variable to store max allies by any kingdom var maxAllies = 0; foreach (var competitor in competingKingdoms) { var allyCount = southeros.AllKingdoms[competitor].Allies.Count; console.WriteLine($"Allies for {competitor} : {allyCount}"); maxAllies = allyCount > maxAllies ? allyCount : maxAllies; } // Find the kingdom(s) with the most allies var leadingKingdoms = southeros.AllKingdoms.Where(kv => kv.Value.IsCompeting && kv.Value.Allies.Count == maxAllies); // If there is a tie if (leadingKingdoms.Count() > 1) { // Clear the list of old competitors competingKingdoms.Clear(); // Create a new list comprising of the kingdoms there was a tie between competingKingdoms.AddRange(leadingKingdoms.Select(kv => kv.Key)); // Break all alliances foreach (var kingdom in southeros.AllKingdoms.Values) { kingdom.BreakAlliances(); } } // If not... else { // ...we declare the winner southeros.RulingKingdom = leadingKingdoms.FirstOrDefault().Value; } } return(southeros.RulingKingdom != null); }