Coding Conundrums 2
Number two in a series of more than one. Definitely.
Welcome to my solutions to Rob Miles' Coding Conundrums 2. The problem descriptions can be found below, along with pastebin and 32 bit binary links (other binary type available upon request). If you need any help, please ask in the comments below.
2.1: Crazy Times Tables
Description
A teacher friend wants to be able to print out stupid times-tables for their kids at school. Perhaps they are not a maths teacher. I have no idea. Anyhoo, the program should request the number of the table (for examplethe3.7 times table) and then print out 1 to 12 timesthat value:
What times table do you want? 3.71
times 3.7 is 3.72 times 3.5 is 7.4..
and so on
The teacher tells you that the 0 times table and the 1 times table are too easy and the program should reject those, but any other value (including negative ones) is OK.
My Solution
This solution works ok, but you get a few inaccuracies with certain values. Changing float
to double
or decimal
would probably solve those issues.
using System;
public class CrazyTables
{
public static void Main(string[] args)
{
if(args.Length != 1)
{
Console.WriteLine("Use it like this: ");
Console.WriteLine(" CrayTables.exe <float>");
Console.WriteLine("\n<float>: The number to use when generating the times table.");
return;
}
float number = float.Parse(args[0].Trim());
if(number == 0 || number == 1)
{
Console.WriteLine("Invalid times table number.");
return;
}
for(int i = 0; i < 12; i++)
{
Console.WriteLine("{0,2} times {1} is {2,2}", i + 1, number, (i + 1) * number);
}
}
public static bool ValidateInput(float number)
{
if (number == 0 || number == 1)
return false;
else
return true;
}
}
(Pastebin, 32 bit binary)
2.2: Scrabble Scores
Description
Scrabble is a word game. Players take turns to make words out of letter tiles. Each tile has a particular value. Generally, the rarer the letter in words, the higher the value. The tiles have the following values:
- (1 point)-A, E, I, O, U, L, N, S, T, R
- (2 points)-D, G
- (3 points)-B, C, M, P
- (4points)-F, H, V, W, Y
- (5 points)-K
- (8 points)-J, X
- (10 points)-Q, Z
I want a program that will tell me how much a given word is worth in Scrabble. Turns out that Rob Miles is worth 12 points, I'd like to be able to find out if anyone else has a name worth more than mine.
My Solution
Another C♯ Dictionary here.
using System;
using System.Collections.Generic;
public class ScrabbleScorer
{
public static void Main(string[] args)
{
if(args.Length != 1)
{
Console.WriteLine("Use it like this:");
Console.WriteLine(" ScrabbleScorer.exe <word>");
Console.WriteLine("\n<word>: The word to calculate the score for.");
return;
}
Console.WriteLine("'{0}' scores {1} points.", args[0], CalculateWordValue(args[0]));
}
public static Dictionary<char, int> wordValues = new Dictionary<char, int>()
{
{ 'a', 1 }, { 'b', 3 }, { 'c', 3 }, { 'd', 2 }, { 'e', 1 }, { 'f', 4 }, { 'g', 2 }, { 'h', 4 }, { 'i', 1 },
{ 'j', 8 }, { 'k', 5 }, { 'l', 1 }, { 'm', 3 }, { 'n', 1 }, { 'o', 1 }, { 'p', 3 }, { 'q', 10 },{ 'r', 1 },
{ 's', 1 }, { 't', 1 }, { 'u', 1 }, { 'v', 4 }, { 'w', 4 }, { 'x', 8 }, { 'y', 4 }, { 'z', 10 }
};
public static int CalculateWordValue(string word)
{
word = word.ToLower();
int totalScore = 0;
foreach(char ch in word)
{
int chScore = 0;
if(wordValues.TryGetValue(ch, out chScore))
{
totalScore += chScore;
}
}
return totalScore;
}
}
(pastebin, 32 bit binary)
2.3: Scrabble Validity Tester
Description
Staying with Scrabble. A standardScrabble&153; set contains the following set of tiles:
A-9. B-2. C-2. D-4. E-12. F-2. G-3. H-2. I-9. J-1. K-1. L-4. M-2. N-6. O-8. P-2. Q-1. R-6. S-4. T-6. U-4. V-2.
Plus two blanks which can be assigned any letter when they are played.
For extra bonus points you could improve your program so that it indicates whether or not the word could actually entered during the game. The program could also indicate whether or not a blank tile is required.
My Solution
The problem description is missing some of the tile counts for me, so I am using data from [this website]. I tried to compact the array of tile counts for this one, but it didn't work too well because I ended up writing more code to read the array than I saved by compacting it.....
using System;
using System.Collections.Generic;
class ScrabbleValidator
{
// from http://scrabblewizard.com/scrabble-tile-distribution/
// the coding conundrums seems to have a few letter counts missing
public static string[] letterCounts = new string[]
{
"", // 0
"jkqxz", // 1
"bcfhmpvwy*", // 2 - * = blank tile
"g", // 3
"dlsu", // 4
"", // 5
"nrt", // 6
"", // 7
"o", // 8
"ai", // 9
"", // 10
"", // 11
"e", // 12
};
public static int blankTileCount = 2;
static void Main(string[] args)
{
if(args.Length != 1)
{
Console.WriteLine("This program works out whether a word is a valid scrabble word.");
Console.WriteLine("Use it like this:");
Console.WriteLine(" ScrabbleValidator.exe <word>");
Console.WriteLine("\n<word>: The word you want to validate.");
return;
}
string word = args[0].Trim().ToLower();
// count the number of each letter in the word
Dictionary<char, int> letterCounts = new Dictionary<char, int>();
foreach (char ch in word)
{
if (letterCounts.ContainsKey(ch))
{
letterCounts[ch] += 1;
}
else
{
letterCounts.Add(ch, 1);
}
}
// loop over the letter counts and validate the word
string invalidReasons = "";
int usedBlanks = 0;
foreach (KeyValuePair<char, int> letterCount in letterCounts)
{
char currentChar = letterCount.Key;
int currentCharCount = letterCount.Value;
int maxCharCount = getLetterCount(currentChar);
if (currentCharCount > maxCharCount)
{
if(usedBlanks + (currentCharCount - maxCharCount) <= blankTileCount)
{
usedBlanks += currentCharCount - maxCharCount;
}
else
{
invalidReasons += String.Format("The character '{0}' is used {1} times (scrabble has {2} tiles for that letter).\n", currentChar, currentCharCount, maxCharCount);
}
}
}
if(invalidReasons.Length > 0)
{
Console.WriteLine("{0} is not valid. Reasons: ", word);
Console.WriteLine(invalidReasons);
}
else
{
Console.WriteLine("{0} is a valid scrabble word.", word);
Console.WriteLine("It would use {0} blank tiles.", usedBlanks);
}
}
static int getLetterCount(char ch)
{
for(int i = 0; i < letterCounts.Length; i++)
{
if(letterCounts[i].Contains(Char.ToLower(ch).ToString()))
{
return i;
}
}
return 0; // the character wasn't recognised, so there won't be any tiles that match it.
}
}
(pastebin, 32 bit binary)
Note that I don't have any analytics on this site yet, so the only way I know you have been here at all is through the comments (and the server logs).