Have language features changed the way we work for the better?

Craig Murphy dropped a little coding challenge on his blog the other day. This prompted me to write the responses as below. I’ve tried to target each one towards using a particular technology as the framework has developed.

Have a look and tell me which is your preferred answer, or propose a new one (but again try to target a language feature). I’d love to know who you why you choose that language feature over another.

Option 1. With Linq

private const string alphabet = "abcdefghijklmnopqrstuvwxyz";
 
static void Main(string[] args)
{
    char c = Console.ReadKey().KeyChar;
 
    var myChars = from character in alphabet
                  where character <= c
                  select character;
 
    var fullRow = myChars.Skip(1).Reverse().Concat(myChars);
 
    var myRows = (from character in myChars
                  select ConvertToSpaces(character, fullRow));
 
    var reverseRows = myRows.Reverse().Skip(1);
    myRows = myRows.Concat(reverseRows);
 
    Console.WriteLine(Environment.NewLine);//Skip the ReadKey line
    foreach (string line in myRows)
        Console.WriteLine(line);
 
    Console.ReadKey();
}
 
private static string ConvertToSpaces(char wanted, IEnumerable<char> characters)
{
    return new string(
    (from character in characters
     select character == wanted ? character : ' ').ToArray());
}

Option 2. With Generics

 
class Program
  {
      private const string alphabet = "abcdefghijklmnopqrstuvwxyz";
 
      static void Main(string[] args)
      {
          char c = Console.ReadKey().KeyChar;
 
          List<char> myChars = new List<char>();
          foreach (char character in alphabet)
          {
              if (character <= c)
                  myChars.Add(character);
          }
 
          List<char> temp = new List<char>(Reverse<char>(AllButFirst<char>(myChars)));
          temp.AddRange(myChars);
          string fullRow = new string(temp.ToArray());
 
          List<string> myRows = new List<string>();
          foreach (char character in myChars)
          {
              myRows.Add(ConvertToSpaces(character, fullRow));
          }
 
          IEnumerable<string> reverseRows = AllButFirst<string>(Reverse<string>(myRows));
          myRows.AddRange(reverseRows);
 
          Console.WriteLine(Environment.NewLine);//Skip the ReadKey line
          foreach (string line in myRows)
              Console.WriteLine(line);
 
          Console.ReadKey();
      }
 
      private static IEnumerable<T> Reverse<T>(IEnumerable<T> myChars)
      {
          Stack<T> reverse = new Stack<T>();
          foreach (T character in myChars)
          {
              reverse.Push(character);
          }
          while (reverse.Count > 0)
          {
              yield return reverse.Pop();
          }
      }
 
      private static IEnumerable<T> AllButFirst<T>(IEnumerable<T> myChars)
      {
           bool first = true;
          foreach (T character in myChars)
          {
              if (first)
                  first = false;
              else
                  yield return character;
          }
      }
      
 
      private static string ConvertToSpaces(char wanted, IEnumerable<char> characters)
      {
          StringBuilder result = new StringBuilder();
          foreach (char character in characters)
          {
              result.Append(character == wanted ? character : ' ');
          }
          return result.ToString();
      }
  }

Option 3. Using IEnumerable

 

class ProgramDNv2
{
    private const string alphabet = "abcdefghijklmnopqrstuvwxyz";
        
    static void Main(string[] args)
    {
        DiamondChars diamond = new DiamondChars();
        diamond.chars = GetChars(     Console.ReadKey().KeyChar);
        foreach (string line in diamond)
        {
            Console.WriteLine(line);
        }
        Console.ReadKey();
    }
 
        private static string GetChars(char MidChar)
        {
            string chars = alphabet.Substring(0, alphabet.IndexOf(MidChar) + 1);
            return chars;
        }
 
    private class DiamondChars : IEnumerable<String>
    {
        public string chars;
 
        #region IEnumerable<string> Members
 
        public IEnumerator<string> GetEnumerator()
        {
            int index = 0;
            foreach (char character in chars)
            {
                yield return MakeLine(character, index);
                index++;
            }
            
            index--;
            foreach (char character in chars.Reverse())
            {
                if (index < chars.Length - 1)
                {
                    yield return MakeLine(character, index);
                }
                index--;
            }
        }
 
        #endregion
 
        private string MakeLine(char character, int index)
        {
            string line = new string(chars[index], 1).PadLeft(chars.Length - index);
 
            if (index > 0)
                 return line + new string(chars[index], 1).PadLeft(index * 2);
            else
                 return line;
        }
 
        #region IEnumerable Members
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
 
        #endregion
    }
 
}

Option 4. Simple recursion

 
    class ProgramDNv1
    {
        static void Main(string[] args)
        {
            string input = "abcde";
            StringBuilder result = new StringBuilder();
            BuildDiamond(0, input, result);
            Console.WriteLine(result);
        }
 
 
 
        private static void BuildDiamond(int index, string input, StringBuilder result)
        {
            string line = new string(input[index], 1).PadLeft(input.Length - index);
            string line2 = new string(input[index], 1).PadLeft(index * 2);
            result.Append(line);
            if (index > 0)
                result.Append(line2);
            result.Append(Environment.NewLine);
            if (index < input.Length - 1)
            {
                BuildDiamond(index + 1, input, result);
                result.Append(line);
                if (index > 0)
                    result.Append(line2);
                result.Append(Environment.NewLine);
            }
        }
    }

Now add a quick comment below telling you preferred implementation and briefly why. Thanks.

Advertisement