s2.1p36 - Money Algorithm!

This chapter seems to talk about basic stuff like what algorithms are and operators. This reminds me of when I was first scratching the surface of C# 4 years ago. Back then, I was messing around a lot with Unity - the 3D game engine. Unity uses a mono runtime so I was slowly learning C# from my own accord. Little did how know just how extensive and awesome C# was. I remember Unity also had a javascript API called unityscript. I remember I used to use that a lot before learning C#. In fact, I may have never even started using C# if it wasn’t for something that happened out of the blue, I’ll make a post on it later.

Anyway, this chapter is about stuff like operators and printing to the console and whatnot - basic stuff.


Hello World

The first question makes me display “Hello World” on the screen. That’s how basic this book is :p If only I read this book 4 years ago… no wait, I take that back. Learning everything by yourself is much better, I think, than having it be told to you. Much more in-depth. The only thing is that it takes a longer time to do.

So as you may already know, here’s how to print to the console:

Console.WriteLine("Hello World");

Well, I thought this was a bit boring so let’s give it a cool animation MULTITHREADING TIME :)

Ok, so this is pretty easy to do. All you have to do is make a method that will print some dots to the console. Include a while loop in the method with a counter variable (an integer which shows keeps track of how many times you have looped). Print counter amount of dots every time you loop. You might want to also make the thread sleep with System.Threading.Thread.Sleep(x) while you are at it.

You probably don’t want loads of dots filling the console so reset the counter every 3 or so goes. You can do this with:

if(counter == 3)counter=0;

or if you are feeling fancy:

if(counter %3 == 0)counter=0;

I was feeling fancy today :p

So here’s the method:

private static void Anim(string txt)
{
     int no = 0; //counter
     while (animrun)
     {
     Console.Clear();
     Console.Write(txt);

     StringBuilder sb = new StringBuilder(); //do the dots
     sb.Append('.', no);
     Console.Write(sb.ToString());

     System.Threading.Thread.Sleep(300); //wait
     if (no % 3 == 0) //if no is fully divisible by 3
     {
        no = 0; //reset
     }
     no++;
    }
}

You use the method like this:

System.Threading.Thread t = new System.Threading.Thread(() => Anim("Hello World"));
t.Start();//print hello world (q1)
Console.ReadKey(); animrun = false; //after pressed a key, halt anim thread
Console.Write(Environment.NewLine); //print line ending (add new line)
t.Suspend(); //suspend animation thread
Console.Clear();

Output: Fancy Hello World


Displaying two messages

Ok so the next exercise is to: >Display two messages of your choice on the screen, seperated by an empty line

You know, if I was actually learning C# for the first time whilst reading this book, I bet you I would have done my own message for exercise 1 because imma rebel. Probably something like Hello World - PixelZerg is awesome or like Hello World - If you don't eat food you will die.

But this question allows you to do just that. This is simple enough, using the method we previously made, we can easily complete the exercise by doing:

animrun = true;
t = new System.Threading.Thread(() => Anim("Do you like food?" + 
Environment.NewLine + Environment.NewLine + "I like food")); t.Start();
Console.ReadKey(); animrun = false; t.Suspend();
Console.Clear();

Output:


Average Algorithm

Display the sum and average of three numbers entered at the keyboard.

hmm… that question doesn’t seem to be in English. Let’s translate it: >Display the sum and average of three numbers entered with the keyboard.

Oh ok, that makes more sense. jk…

The chapter had an example for an algorithm that found the average of two numbers. I am not satisfied with the algorithm at all. It…

  • defines variables at the start for no reason - they are never used anywhere else
  • supports only 2 numbers
  • is very manual and not flexible
  • uses `System.Convert.ToDouble()` rather than a cast or a conversion like `Double.Parse()` and uses up space for no reason
  • is doing everything right in the Main method
  • has `string[] args` as a parameter for the Main method but not actually using it
  • is declared that it is using certain namespaces but they aren't used in the code at all
  • is not surrounded with try/catch

Here’s me replicating the code in one line of code:

Console.WriteLine("Average = "+(double.Parse(Console.ReadLine()) + double.Parse(Console.ReadLine())) / 2);

Boom!

But anyway, like I said, the code in the book isn’t very flexible at all. The question says to make a program that displays the sum and average of 3 numbers, but imma rebel so let’s make it so that our method can do an unlimited amount of numbers.

private static decimal GetAverage(params decimal[] numbers)
        {
            decimal sum = 0;
            foreach (decimal number in numbers)
            {
                sum += number; //find sum
            }
            return sum / numbers.Length; //divide sum by no of numbers
        }

There’s the method I made. That’s all there is to it! Funny thing is, this method is still way shorter than the algorithm in the book. I suppose the algorithm is good for complete beginners at C# but c’mon dude…

So, as you can see, in my method, I use an array then find the sum of that array then find the sum of the numbers in the array then divide it by the amount of items in the array (which is how you find averages). Awesome right?

Nope! That was a trick question, it’s not awesome! You can reduce that method down to one line of code:

private static decimal GetAverage(params decimal[] numbers){
return numbers.Sum() / numbers.Length;
}

(and yes, that is one line of code because you can do this: private static decimal GetAverage(params decimal[] numbers){return numbers.Sum() / numbers.Length;})

You can probably imagine just how bad the code in the book was now. You don’t really need me to show you the code…

Anyway, let’s try not to get too heated over the example and continue. Here’s how you use my method:

Console.WriteLine("Enter some numbers to find the average");
List<decimal> numbers = new List<decimal>();
bool done = false;
while (!done)
{
  numbers.Add(ReadDecimal("Enter a number"));
  Console.WriteLine("Add more numbers? (y/n)");
  done = Console.ReadKey().Key != ConsoleKey.Y;
}
Console.Clear();
Console.WriteLine("The average of those numbers is: " +
GetAverage(numbers.ToArray()) + " and the sum is " +
numbers.Sum());
Console.ReadKey();
Console.Clear();

Output:


Modulo Operator

Read in two integers and display how many times the first integer divides into the second integer (using integer division). Display the remainder from this division. Hint: use the modulo operation.

This exercise is very basic and I couldn’t find a way of making it more interesting like I did with exercise 1 so I guess i’ll just do it:

int num1 = ReadInt("Enter x where x/y=output");
int num2 = ReadInt("Enter y where x/y=ouput");
Console.WriteLine("output = " + num1 / num2 + " remainder " + num1 % num2 
+ Environment.NewLine + "i.e: " + num1 / num2 + " " + num2 + "s go into " 
+ num1 + " with a remainder of " + num1 % num2);
Console.ReadKey();//wait for keycodess
Console.Clear();

Oh yeah, I forgot to mention, I also made a method ReadInt() that gets input from the console, but only integers. It has cool features e.g it doesn’t allow you to type any non-numeric characters or go over the maximum value that an integer can store. Here it is (the indentation weird because I want it to fit on the screen):

private static int ReadInt(string prompt)
{
Console.Clear();
Console.WriteLine(prompt);
string rawin = string.Empty;
int integer = 0;
Regex numpattern = new Regex("^[0-9]*$");
bool done = false;
while (!done)
{
 ConsoleKeyInfo k = Console.ReadKey(); //read a key
 if (k.Key == ConsoleKey.Enter) //enter means done
 {
  done = true;
 }
 if (k.Key == ConsoleKey.Backspace)
 {
  try
  {
   rawin = rawin.Substring(0, rawin.Length - 1);
  }
 catch { }
 }
{
 if (numpattern.IsMatch(k.KeyChar.ToString()))
 {
  if (Int32.TryParse(rawin + k.KeyChar, out integer))
  {
   rawin += k.KeyChar;
  }
 }
}
Console.Clear();
Console.WriteLine(prompt);
Console.WriteLine(rawin);
}
return integer;
}

Output:


Money Algorithm

The user enters an amount of money as a whole number. The program should calculate and display how many £20, £10 and £5 and £2 and £1 coins are needed to make up this amount of money.

Making this method was the most interesting of all of the methods so far. But this is only because again, me being such a rebel I decided to allow the user to input not whole numbers, i.e pennies are supported to.

First of all, I made this primitive algorithm for working out which different coins/notes to use to make up the inputed value. (If you look on github, I have commented all of the code in this post)

private static void MoneyAlgorithm(decimal money)
{
money = Math.Round(money, 2);
decimal[] coinvalues = new decimal[] 
{ 20m, 10m, 5m, 2m, 1m, 0.5m, 0.2m, 0.1m, 0.05m, 0.02m, 0.01m };
decimal curval = money;
while (curval > 0)
{
bool found = false;
for (int no = 0; no != coinvalues.Length; no++)
{
if ((curval - coinvalues[no]) >= 0 && !found)
{
curval -= coinvalues[no];
if (coinvalues[no] < 1)
{
Console.WriteLine(Math.Truncate(coinvalues[no] * 100) + "p coin");
}
else
{
Console.Write("£" + coinvalues[no]);
if (coinvalues[no] == 2m || coinvalues[no] == 1m)
{
Console.Write(" coin");
}
else
{
Console.Write(" note");
}
Console.Write(Environment.NewLine);
}
found = true;
}
}
}
}

Now, we need to find how many £20, £10, etc do you need to make the given value. This is easy, you just need to convert the value and everything to integers and then finding the answer using integer division and modulo. Converting directly to integer is lossy in this case so I first multiply the numbers by 100 (to retain 2 decimal points).

Once I had the integer division value, I just input the remainder into the MoneyAlgorithm. Simple as this:

private static void MoneyAlgorithm(decimal money, decimal val, string valname)
{
 Console.Clear();
 int times = (int)Math.Truncate(money * 100) / (int)Math.Truncate(val * 100);
 decimal rem = money % val;//find remainder
 Console.WriteLine(times + " " + valname + Environment.NewLine 
+ "Plus an aditional "+rem+" which is made with:");
 MoneyAlgorithm(rem);
}

Here’s how to use the methods:

decimal money = ReadDecimal("Enter an amount of money. e.g 5.37 = five pounds and thrity seven pence");
Console.Clear();
Console.WriteLine("Make that value with:");
string[] written = new string[] { "Most Efficient Combination", "1p coin(s)"
,"2p coin(s)", "5p coin(s)", "10p coin(s)", "20p coin(s)", "50p coin(s)", "£1 coin(s)"
,"£2 coin(s)", "£5 note(s)", "£10 note(s)", "£20 note(s)" };
switch (MenuChoose(written))
{
case 0:
Console.Clear();
Console.WriteLine("How to make £" + money + " with conventional brittish money:");
MoneyAlgorithm(money);
break;
case 1:
MoneyAlgorithm(money, 0.01m, written[1]);
break;
case 2:
MoneyAlgorithm(money, 0.02m, written[2]);
break;
case 3:
MoneyAlgorithm(money, 0.05m, written[3]);
break;
case 4:
MoneyAlgorithm(money, 0.1m, written[4]);
break;
case 5:
MoneyAlgorithm(money, 0.2m, written[5]);
break;
case 6:
MoneyAlgorithm(money, 0.5m, written[6]);
break;
case 7:
MoneyAlgorithm(money, 1m, written[7]);
break;
case 8:
MoneyAlgorithm(money, 2, written[8]);
break;
case 9:
MoneyAlgorithm(money, 5, written[9]);
break;
case 10:
MoneyAlgorithm(money, 10, written[10]);
break;
case 11:
MoneyAlgorithm(money, 20m, written[11]);
break;
}
Console.ReadKey();
Console.Clear();

As you can see in that code, a method Menu Choose is used. This is a method that was taken from one of my previous projects, actually, - The Universal Program

Output:

Look how awesome it looks seeing the algorithm work out how to make up money:


Time taken to write: 2 or so hr.


Cover Image by William Neuheisel. It has not been edited.