Saturday, November 3, 2012

Code Kata: Bowling Game

Problem:

Write a program, to score a game of Ten-Pin Bowling.

The scoring rules:

Each game, or "line" of bowling, includes ten turns, or "frames" for the bowler.

In each frame, the bowler gets up to two tries to knock down all ten pins.

If the first ball in a frame knocks down all ten pins, this is called a "strike". The frame is over. The score for the frame is ten plus the total of the pins knocked down in the next two balls.

If the second ball in a frame knocks down all ten pins, this is called a "spare". The frame is over. The score for the frame is ten plus the number of pins knocked down in the next ball.

If, after both balls, there is still at least one of the ten pins standing the score for that frame is simply the total number of pins knocked down in those two balls.

If you get a spare in the last (10th) frame you get one more bonus ball. If you get a strike in the last (10th)
frame you get two more bonus balls. These bonus throws are taken as part of the same turn. If a bonus ball knocks down all the pins, the process does not repeat. The bonus balls are only used to calculate the score of the final frame.

The game score is the total of all frame scores.

Examples:

X indicates a strike
/ indicates a spare
- indicates a miss
| indicates a frame boundary

X|X|X|X|X|X|X|X|X|X||XX
Ten strikes on the first ball of all ten frames.
Two bonus balls, both strikes.
Score for each frame == 10 + score for next two
balls == 10 + 10 + 10 == 30
Total score == 10 frames x 30 == 300

9-|9-|9-|9-|9-|9-|9-|9-|9-|9-||
Nine pins hit on the first ball of all ten frames.
Second ball of each frame misses last remaining pin.
No bonus balls.
Score for each frame == 9
Total score == 10 frames x 9 == 90

5/|5/|5/|5/|5/|5/|5/|5/|5/|5/||5
Five pins on the first ball of all ten frames.
Second ball of each frame hits all five remaining pins, a spare.
One bonus ball, hits five pins.
Score for each frame == 10 + score for next one
ball == 10 + 5 == 15
Total score == 10 frames x 15 == 150

Solution:

The written program allows the user to input their bowling score into the console ball by ball. Then the program prints out the summary tally along with the final score.

Source Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace _02_TenPinBowling
{
    public class TenPinBowling
    {
        static void Main(string[] args)
        {
            ScoreKeeper scoring = new ScoreKeeper();
            scoring.Start();
            scoring.PrintTally();
            WaitForEnterToExit();
        }

        sealed class ScoreKeeper
        {
            private string[] _frameNumbers = {  "1st", "2nd", "3rd", "4th", "5th", 
                              "6th", "7th", "8th", "9th", "10th (last)" };
            private string[] _frameResults = new string[TotalFrames];
            private List<string> _ballResults = new List<string>();
            private string _bonusBallResults;

            public void Start()
            {
                PrintWelcomeMessage();
                InputPlayerScores();
            }

            private static void PrintWelcomeMessage()
            {
                Console.WriteLine("Welcome to Ten Pin Bowling Alley DownUnder!");
            }

            private void InputPlayerScores()
            {
                for (int i = 0; i < _frameNumbers.Length; i++)
                {
                    Console.WriteLine("Pins knocked down on first ball in {0} frame? [number, X, /]", 
                    _frameNumbers[i]);
                    InputBallScoresInFrame(i);
                }
            }

            private void InputBallScoresInFrame(int index)
            {
                string firstBallResult = Console.ReadLine();
                _ballResults.Add(firstBallResult);
                string secondBallResult = InputSecondBallScoreInFrame(index, firstBallResult);
                _frameResults[index] = firstBallResult + secondBallResult;
                InputBonusBallScores(index, firstBallResult, secondBallResult);
            }

            private string InputSecondBallScoreInFrame(int index, string firstBallResult)
            {
                string secondBallResult = string.Empty;
                if (!firstBallResult.Equals(Strike, StringComparison.InvariantCultureIgnoreCase))
                {
                    Console.WriteLine("Pins knocked down on second ball in {0} frame? [number, X, /]", 
                    _frameNumbers[index]);
                    secondBallResult = Console.ReadLine();
                    _ballResults.Add(secondBallResult);
                }
                return secondBallResult;
            }

            private void InputBonusBallScores(int index, string firstBallResult, string secondBallResult)
            {
                if (index == _frameNumbers.Length - 1)
                {
                    if (firstBallResult.Equals(Strike, StringComparison.InvariantCultureIgnoreCase) 
                    || secondBallResult == Spare)
                    {
                        Console.WriteLine("Pins knocked down on first bonus ball? [number, X]");
                        string firstBonusBallResult = Console.ReadLine();
                        _ballResults.Add(firstBonusBallResult);
                        string secondBonusBallResult = GetSecondBonusBallScore(firstBallResult);
                        _bonusBallResults = firstBallResult + secondBonusBallResult;
                    }
                }
            }

            private string GetSecondBonusBallScore(string firstBallResult)
            {
                string secondBonusBallResult = string.Empty;
                if (firstBallResult.Equals(Strike, StringComparison.InvariantCultureIgnoreCase))
                {
                    Console.WriteLine("Pins knocked down on second bonus ball? [number, X]");
                    secondBonusBallResult = Console.ReadLine();
                    _ballResults.Add(secondBonusBallResult);
                }
                return secondBonusBallResult;
            }

            public void PrintTally()
            {
                Console.WriteLine("The tally of your game: ");
                for (int i = 0; i < _frameNumbers.Length; i++)
                    Console.Write(_frameResults[i] + "|");
                Console.WriteLine("||" + _bonusBallResults);
                Console.WriteLine("Final score is {0}", GetFinalScore());
            }

            private int GetFinalScore()
            {
                int finalScore = 0;
                for (int i = 0; i < _ballResults.Count; i++)
                {
                    finalScore += GetBallScore(i) + GetScoreForNextBalls(ref i);
                }
                return finalScore;
            }

            private int GetScoreForNextBalls(ref int index)
            {
                int currentIndex = index;
                string result = _ballResults[index];
                if (result.Equals(Strike, StringComparison.InvariantCultureIgnoreCase))
                {
                    if (index == _ballResults.Count - 3)
                        index += 2;
                    return GetBallScore(currentIndex + 1) + GetBallScore(currentIndex + 2);
                }
                else if (result == Spare)
                {
                    if (index == _ballResults.Count - 2)
                        index++;
                    return GetBallScore(currentIndex + 1);
                }
                return 0;
            }

            private int GetBallScore(int index)
            {
                string score = _ballResults[index];
                if (score.Equals(Strike, StringComparison.InvariantCultureIgnoreCase))
                    return TotalPins;
                else if (score == "/")
                    return TotalPins - Convert.ToInt32(_ballResults[index - 1]);
                return Convert.ToInt32(score);
            }
        }

        private const string Strike = "x";
        private const string Spare = "/";
        private const int TotalPins = 10;
        private const int TotalFrames = 10;

        private static void WaitForEnterToExit()
        {
            Console.WriteLine("Press enter to exit");
            Console.Read();
        }
    }
}

Saturday, October 27, 2012

Code Kata: Anagrams

Let's do some code katas. Starting with ones from cyber-dojo. The programming language is in C#. Please let me know if  you have any comments. Thanks~

Problem:

Write a program to generate all potential
anagrams of an input string.

For example, the potential anagrams of "biro" are

biro bior brio broi boir bori
ibro ibor irbo irob iobr iorb
rbio rboi ribo riob roib robi
obir obri oibr oirb orbi orib

Solution:

The solution comes with two flavors: recursive and non-recursive ones. The recursive one is more intuitive and easier to come up with. The non-recursive one I had to reference from the existing Knuth algorithms.

Source Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace _01_Anagrams
{
    class Anagrams
    {
        static void Main(string[] args)
        {
            RecursivePermutation();
            NonRecursivePermutation();
        }

        private static void RecursivePermutation()
        {
            new Anagrams().ProduceAnagrams("biro", "");
        }

        private static void NonRecursivePermutation()
        {
            Permutation perm = new Permutation("biro");
            do
            {
                string value = perm.GetNext();
                Debug.WriteLine(value);
            }
            while (perm.NextPermutation());
        }

        private void ProduceAnagrams(string input, string prefix)
        {
            for (int i = 0; i < input.Length; i++)
            {
                if (input.Length > 1)
                {
                    string remainingInput = input.Remove(i, 1);
                    ProduceAnagrams(remainingInput, prefix + input[i]);
                }
                else if (input.Length == 1)
                {
                    Debug.WriteLine(prefix + input[i]);
                }
            }
        }
    }

    class Permutation
    {
        private List<string> _input = new List<string>();
        private int[] _indices;

        public Permutation(string input)
        {
            foreach (char c in input)
                _input.Add(c.ToString());
            _indices = new int[input.Length];
            for (int i = 0; i < _indices.Length; i++)
                _indices[i] = i;
        }

        public string GetNext()
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < _indices.Length; i++)
                sb.Append(_input[_indices[i]]);
            return sb.ToString();
        }

        public bool NextPermutation()
        {
            int i, j, l;
            for (j = _input.Count - 2; j >= 0; j--)
                if (_indices[j + 1] > _indices[j])
                    break;
            if (j == -1)
                return false;
            
            for (l = _input.Count - 1; l > j; l--)
                if (_indices[l] > _indices[j])
                    break;
            
            int swap = _indices[j];
            _indices[j] = _indices[l];
            _indices[l] = swap;

            for (i = j + 1; i < _input.Count; i++)
            {
                if (i > _indices.Length - i + j)
                    break;
                swap = _indices[i];
                _indices[i] = _indices[_indices.Length - i + j];
                _indices[_indices.Length - i + j] = swap;
            }
            return true;
        }
    }
}

Friday, September 28, 2012

Touchscreen no longer works => Remote control your android device

So I have a case of an android device (HTC tattoo, almost three years in running) with its touchscreen not functioning anymore. I was like OK, there's got to be a way for me to still use it with the hardware inputs/buttons. I wanted to connect to Wifi but I had no idea how I can possibly enter the password. Moreover, I wanted to register my Line application by email, so I can use Line on other devices, e.g. iPad. Again, malfunctioned touchscreen equates to no keyboard input.

The way around this is to remote control my android device via USB debugging, accompanied by the useful androidscreencast Java program. The steps are simple:

(1) Enable debugging by USB on your device
(2) Download the Android SDK and then the Android SDK Platform tools
(3) Download the androidscreencast application
(4) Connect the Android device to your computer via USB
(5) Run the androidscreencast application

Long and behold, you will see and feel your Android device in a new light!


More details can be found here.

Monday, August 20, 2012

How to pack your luggage

This link How To: Pack a Suitcase is titled for busy moms. But I think it can very well suit most folks as well. I googled this topic on how to pack a luggage as I will soon travel and live in Australia. And today, I got heaps of stuff to pack with a maximum limit of 20 kg to bring!

Friday, July 27, 2012

A High Availability problem that can only be guided by the expert availability

Sometimes, after searching on ends for a possible and most elegant solution for a technical problem just doesn't come up with the goods. Then it is time to deploy your question on a domain/expert forum. In my case, I had a High Availability (HA) setup problem. I won't go into the specifics here. But it is just interesting that I find asking your own question on a forum like the SQL server forum can draw the attention of experts who will be able to offer their opinions most tailored to your problem!

So here's my Forum Question of the Day as a sample~

Sunday, July 22, 2012

Interop Las Vegas (May, 2012)


Interop, the leading business technology event, is held at different times of the year at locations including Las Vegas, New York, Tokyo, and Mumbai. This year, I was very privileged to attend the one in Las Vegas, where there were over 300 exhibitors in the expo and 100 conferences by topics. Here, except for gambling, the areas covered in the conference are very wide range: cloud computing, virtualization, security, mobility and data center advances.

In the enterprise cloud summit, firstly, there is a fact that cloud is becoming generally accepted as companies gain experience with the concepts. According to CompTIA’s survey, 69% (vs. 42% last year) of individuals rated themselves as familiar with the cloud. And 69% of companies are using some form of SaaS application, whilst 36% of companies not using IaaS/PaaS currently plan to do so in the future. So the reliance on cloud is every so increasing. The sited reasons are lower costs, simpler/quicker implementation, and expanded capabilities. There are challenges however, such as integration with existing systems, vendor lock-in & selection, and changes to IT policy and staff training. And there are hidden costs of the cloud as suggested by company like Cloudability. If not under control (which can be hard), high costs due to unused instances and over-provisioning are expected.

Other points of interests as mentioned in this cloud summit are:

  1. Openness in cloud platforms are starting to see momentum as initiatives such as OpenStack gains success. The open cloud ecosystem is now very rich. Rackspace, Cloud Stack, Cloud Foundry, Eucalyptus and cloudscaling are just some to name a few. Diversity and cheaper implementation are the two key reasons to adopt these open cloud systems. And since the code is open, these systems should be secure and more trustworthy.
  2. Generally, users tend to choose fun(ctionality) over security. And this brings lots of headaches to the IT administrators. One of the solutions at the virtualization level is that the Hypervisor will undergo massive changes starting this year to become the root of security for clients and clouds alike. Startups like Bromium looks toward a Byzantine Secure System as a part of the change. 
  3. To be in the economic game these days, companies are building and opening APIs for accessing their data services. The data services can be monetized by APIs to sell to external vendors and partners. In turn, the ecosystem of your business consolidates and grows at a higher level of pace. 
  4. The increasing number of people bring their own devices (BYOD) to work is an open security question left still largely unaddressed at this point.

Interop has been mostly a business driven event. The number of topics and products on display at the expo were staggering. And security will continue to be the cornerstone and concern from both the vendor’s and customer’s points of views. It will be very interesting to see how new security problems and opportunities will be created in this every changing cloud era!


Tuesday, July 17, 2012

Oh, why that DLL is not found!

I was testing a piece of code to do with KMIP (Key Management Interoperability Protocol). The KMIP client code includes a C# wrapper that loads a C++ client library. However, I was stuck in a weird problem where I was getting the exception saying that this particular C++ KmipClient.dll is not found. But in fact, the file is located where the program expects it to be. So a chat with a fellow worker led me to check the DLL dependency for the DLL. I then went onto using the Dependency Walker tool. Below is the result of loading the KmipClient.dll.


The issue has been discovered! The root cause was the INGICAPI.DLL which is needed by KmipClient.dll was not loaded because it was not placed along with KmipClient.dll. So check your dependencies, folks :)