A friend of mine and sharpfellow John Rayner posted a coding Kata to a c# group I subscribe to on Friday. We have a lot of these posted in the group and its a great way to see how different people attack the problem. Fridays Kata was described as follows.
Today’s problem is to create an LCD for displaying numbers. You are given two integers s and n, where n is the number to be displayed and s is the size, You need to use | and _ characters to construct a display. Each digit occupies exactly s+2 columns and 2s+3 rows. There has to be exactly one column of blanks between digits.
After thinking about this problem for a little while, I came to conclusion that each digit in the display has some fairly simple structure and that structure is common across all digits. I set out some core rules that would help me break down this problem. I have listed these out.
- Each Digit has two box sections. And upper and lower box.
- Each Digit has a top, middle & bottom which must be formed of dashes.
- Excluding the top, middle and bottom dash sections, you must assume that the gaps must be bars ( “|”)
- In the “bars” sections a digit can be formed of 3 types of bar. Left, Right and Both.
With these rules in place I set about tacking the problem. I went through a few iterations to reach the version below and I am sure I could go through a few more to make it cleaner and more efficient. This version does pretty well though by generating the number 1234567890 with 5 chars per segment in 4 ms.
private static StringBuilder Draw(int b, int n) { var format = string.Join("|", n.ToString().ToCharArray()); var buffer = new StringBuilder(); var line = new StringBuilder(); var lineCount = 2 + (b * 2); var dash = string.Format(" {0} ", string.Concat(Enumerable.Repeat("-", b))); var blank = string.Format(" {0} ", string.Concat(Enumerable.Repeat(" ", b))); var barLeft = string.Format("|{0} ", string.Concat(Enumerable.Repeat(" ", b))); var barRight = string.Format(" {0}|", string.Concat(Enumerable.Repeat(" ", b))); var barAll = string.Format("|{0}|", string.Concat(Enumerable.Repeat(" ", b))); var dashLines = new Dictionary<int, string> { {0, "23567890"}, {lineCount / 2, "2345689"}, {lineCount, "2356890"}, }; for (int i = 0; i <= lineCount; i++) { line.Clear(); foreach (var character in format) { if (character.Equals("|"[0])) { line.Append(" "); continue; } if (dashLines.ContainsKey(i)) { line.Append(dashLines[i].Contains(character) ? dash : blank); continue; } if(i < lineCount / 2) { if ("4890".Contains(character)) { line.Append(barAll); continue; } if ("1237".Contains(character)) { line.Append(barRight); continue; } line.Append(barLeft); } else { if ("086".Contains(character)) { line.Append(barAll); continue; } if ("1345679".Contains(character)) { line.Append(barRight); continue; } line.Append(barLeft); } } buffer.AppendLine(line.ToString()); } return buffer; }