DEV Community

James Robb
James Robb

Posted on • Edited on

Duplicate Encoder

Task description

The goal of this exercise is to convert a string to a new string where each character in the new string is "(" if that character appears only once in the original string, or ")" if that character appears more than once in the original string. Ignore capitalization when determining if a character is a duplicate.

Examples:
"din" => "((("
"recede" => "()()()"
"Success" => ")())())"
"(( @" => "))(("

Task solution

Tests

As I will be using the C# language for this implementation, we will use the Microsoft.VisualStudio.TestTools.UnitTesting namespace which will provide testing utilities to us out of the box. For the tests we will use the examples provided in the task description above like so:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Kata;

namespace KataTests.UnitTests 
{
    [TestClass]
    public class DuplicateEncoderTests
    {
        [TestMethod]
        public void TaskExamplesPassAsExpected()
        {
            var encoder = new DuplicateEncoder();
            Assert.AreEqual("(((", encoder.Encode("din"));
            Assert.AreEqual("()()()", encoder.Encode("recede"));
            Assert.AreEqual(")())())", encoder.Encode("Success"));
            Assert.AreEqual("))((", encoder.Encode("(( @"));
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Implementation

using System;
using System.Collections.Generic;

namespace Kata {
   public class DuplicateEncoder {
    private Dictionary<char, int> CharCounts(string text) {
      var letters = text.ToCharArray(); 
      var charCounts = new Dictionary<char, int>();

      foreach(char letter in text) {
         var lower_letter = Char.ToLower(letter);
         if (charCounts.ContainsKey(lower_letter)) charCounts[lower_letter]++;
         else charCounts.Add(lower_letter, 1);
      }

      return charCounts;
    }

    private string EncodeWordBasedOnCharCount(
      Dictionary<char, int> charCounts, 
      string text
    ) {
      var return_string = "";

      foreach(char letter in text) {
         var lower_letter = Char.ToLower(letter);
         if(charCounts[lower_letter] == 1) return_string += "(";
         else return_string += ")";
      }

      return return_string;
    }

    public string Encode(string text) {
      var charCounts = this.CharCounts(text);
      return this.EncodeWordBasedOnCharCount(charCounts, text);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The DuplicateEncoder class in the Kata namespace exposes 1 function publicly, that being the Encode function. This function will take in the word to encode and return the encoded string in response. Further to this, there are 2 private functions:

  1. CharCounts takes the word to encode and generates a Dictionary<char, int> of its characters
  2. EncodeWordBasedOnCharCount takes the character counts from CharCounts and the word to encode and return the encoded string

When we run the Encode function we will first generate a Dictionary<char, int> to represent the count of each character by calling the CharCounts function. From there we generate the encoded string based on the character counts and the word we wish to encode by calling the EncodeWordBasedOnCharCount function, for example we can express this with the following overview of that process:

var encoder = new DuplicateEncoder();
encoder.Encode("test")
  -> `CharCounts("test")` -> `{t: 2, e: 1, s: 1 }`
  -> `EncodeWordBasedOnCharCount({t: 2, e: 1, s: 1 }, "test")` -> ")(()"
Enter fullscreen mode Exit fullscreen mode

That's all we need to encode any string based on the task description. ๐Ÿ˜„

Conclusions

I am getting back into C# lately and really like how simple its gotten since I last used it over 6 ish years back ๐Ÿ˜…. I would like to potentially refactor the solution at some point but for now I am quite happy with the tests and implementation. Let me know if you have any suggestions on improvements since I am looking to brush up my C# skills further anyway, otherwise, see you in the next one!

Top comments (0)