diff --git a/csharp-scrabble-challenge.Main/Program.cs b/csharp-scrabble-challenge.Main/Program.cs index 3751555..aa523cc 100644 --- a/csharp-scrabble-challenge.Main/Program.cs +++ b/csharp-scrabble-challenge.Main/Program.cs @@ -1,2 +1,4 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); +using csharp_scrabble_challenge.Main; + +Scrabble s = new Scrabble("[{h}ous{e}]"); +Console.WriteLine(s.score()); // Output the score to the console \ No newline at end of file diff --git a/csharp-scrabble-challenge.Main/Scrabble.cs b/csharp-scrabble-challenge.Main/Scrabble.cs index c1ea013..0b25547 100644 --- a/csharp-scrabble-challenge.Main/Scrabble.cs +++ b/csharp-scrabble-challenge.Main/Scrabble.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.Metrics; using System.Linq; using System.Reflection.Metadata.Ecma335; using System.Text; @@ -9,15 +10,132 @@ namespace csharp_scrabble_challenge.Main { public class Scrabble { + private string _word; + private readonly Dictionary _letterValues = new Dictionary + { + {'A', 1}, {'B', 3}, {'C', 3}, {'D', 2}, {'E', 1}, + {'F', 4}, {'G', 2}, {'H', 4}, {'I', 1}, {'J', 8}, + {'K', 5}, {'L', 1}, {'M', 3}, {'N', 1}, {'O', 1}, + {'P', 3}, {'Q', 10}, {'R', 1}, {'S', 1}, {'T', 1}, + {'U', 1}, {'V', 4}, {'W', 4}, {'X', 8}, {'Y', 4}, + {'Z', 10} + }; + private List _validBrackets = new List { '{', '}', '[', ']' }; + private Stack _bracketStack = new Stack(); + public Scrabble(string word) - { - //TODO: do something with the word variable + { + _word = word; } public int score() { - //TODO: score calculation code goes here - throw new NotImplementedException(); //TODO: Remove this line when the code has been written + int totalScore = 0; + int index = 0; + + // check if word is valid + if (!IsValidWord(_word)) + { + return 0; // Invalid word, return 0 as total score + } + + while (index < _word.Length) + { + char currentChar = _word[index]; + + if (currentChar == '{') + { + + int multiplier = 2; // this is potentially a double score word + index++; // Move past the curly bracket to the letter inside the brackets + + // check that the character after the letter inside brackets is the correct closing bracket + if ((index + 1 < _word.Length) && (_word[index + 1] == '}')) + { + // retrieve the letter inside and its base value score + char letter = Char.ToUpper(_word[index]); + if (_letterValues.TryGetValue(letter, out int baseValue)) + { + totalScore += (baseValue * multiplier); + } + index += 2; // move past the letter and the closing brace or bracket + } + + continue; // move to next iteration since no closing bracket was found + } + + else if (currentChar == '[') + { + int multiplier = 3; // this is potentially a triple score word + index++; // Move to the letter inside the brackets + + // check that the character after the letter inside brackets is also the right closing bracket + if ((index + 1 < _word.Length) && (_word[index + 1] == ']')) + { + // retrieve the letter inside and its base value score + char letter = Char.ToUpper(_word[index]); + if (_letterValues.TryGetValue(letter, out int baseValue)) + { + totalScore += baseValue * multiplier; + } + + index += 2; // move past the letter and the closing brace or bracket + } + + continue; // move to next iteration since no closing bracket was found + } + + else + { + char letter = Char.ToUpper(_word[index]); + if (_letterValues.TryGetValue(letter, out int value)) + { + totalScore += value; + } + + index++; // Move to the next character in the word + } + } + return totalScore; + } + + private bool IsValidWord(string word) + { + Stack bracketStack = new Stack(); + + // base check: if a character is not present in dictionary or a valid bracket, we return 0 + foreach (char c in word) + { + if (!char.IsLetter(c) && !_validBrackets.Contains(c)) + { + return false; // Invalid character found + } + } + + // check for balanced brackets + foreach (char c in word) + { + if (c == '{' || c == '[') + { + bracketStack.Push(c); + } + else if (c == '}' || c == ']') + { + if (bracketStack.Count == 0) + { + return false; + } + char openingBracket = bracketStack.Pop(); + if ((c == '}' && openingBracket != '{') || + (c == ']' && openingBracket != '[')) + { + return false; + } + } + } + + // If stack is empty, all brackets are balanced + return bracketStack.Count == 0; } } -} +} \ No newline at end of file diff --git a/csharp-scrabble-challenge.Test/ExtensionTests.cs b/csharp-scrabble-challenge.Test/ExtensionTests.cs index 8eb37dc..6d11bda 100644 --- a/csharp-scrabble-challenge.Test/ExtensionTests.cs +++ b/csharp-scrabble-challenge.Test/ExtensionTests.cs @@ -12,15 +12,24 @@ namespace csharp_scrabble_challenge.Test public class ExtensionTests { - [TestCase("{street}", 12)] //extension double word - [TestCase("[street]", 18)] //extension triple word - [TestCase("{quirky}", 44)] //extension double word - [TestCase("[quirky]", 66)] //extension triple word - [TestCase("{OXyPHEnBUTaZoNE}", 82)] - [TestCase("[OXyPHEnBUTaZoNE]", 123)] - public void ExtendedCriteriaTests(string word, int targetScore) + [TestCase("[{h}o1s{e}]", 0)] // error case (zero for errors) + [TestCase("{h}ous{e}", 13)] + [TestCase("[{h}ous{e}]", 39)] + [TestCase("[h}ous{e}]", 0)] //Error case (zero for errors) + [TestCase("", 0)] + [TestCase(" ", 0)] + [TestCase(" \t\n", 0)] + [TestCase("\n\r\t\b\f", 0)] + [TestCase("a", 1)] + [TestCase("f", 4)] + [TestCase("OXyPHEnBUTaZoNE", 41)] + [TestCase("quirky", 22)] + [TestCase("street", 6)] + public void WordScoreTests(string word, int targetScore) { - Assert.AreEqual(this.GetWordScore(word), targetScore); + Scrabble scrabble = new Scrabble(word); + + Assert.That(scrabble.score(), Is.EqualTo(targetScore)); } private int GetWordScore(string word) => new Scrabble(word).score();