I am trying to solve one of the Euler Project problems using c# (problem 22). Though I have run into a problem. It's probably worth noting I am relatively new to programming, especially c#.
I need to come up with a word score for a set of strings that I have. This involves summing up the score of each letter in a a word, e.g. a=1, b=2, c=3 and so on. To do this I have assigned all 26 letters of the alphabet as variables with the relevant scores. I then want to compare each letter in the word with the relevant variables of the same name. However what I am left with is a char data type, what's the best way for me to compare the character to the relevant variable, and then use the variable value in my integer calculation. I have included the code I have so far below, with the problem occuring in the last 2 lines excluding braces. (I have had a quick look, and it appears this is not supported in c++, though i'm not sure about c#). Any help would be greatly appreciated.
string[] lines = File.ReadAllLines(#"C:\Users\john\Downloads\names.txt");
//Console.WriteLine(lines[1]);
char[] delimiterChars = { ',', '\t' };
string text = lines[0];
string[] names = text.Split(delimiterChars);
Console.WriteLine("{0} words in text:", names.Length);
Array.Sort(names);
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;
int f = 6;
int g = 7;
int h = 8;
int i = 9;
int j = 10;
int k = 11;
int l = 12;
int m = 13;
int n = 14;
int o = 15;
int p = 16;
int q = 17;
int r = 18;
int s = 19;
int t = 20;
int u = 21;
int v = 22;
int w = 23;
int x = 24;
int y = 25;
int z = 26;
int[] nameTotal;
for (int count = 0; count < names.Length; count++)
{
string name = names[count];
int total = 0;
for (int count2 = 0; count2 < name.Length; count2++)
{
nameTotal[count] = name.Substring(count2) + total;
total = total + nameTotal[count];
}
}
You can do this by taking advantage of the layout of the standard ASCII table.
In ASCII, the 'a' character has a decimal value of 97. Lower-case letters then continue up until 122.
Therefore, you can easily convert an 'a' char value to your required value by using:
char charToConvert = 'a';
int requiredValue = (int)charToConvert - 96;
If you want to calculate the sum of the letters in a name, you can also use Linq (just an example):
string name = "ABCD";
int sum = name.Select(letter => letter - 'A' + 1).Sum();
You can perform calculations with letters just like with integers in C#.
The Select method (which is an extension method from Linq) projects each letter of the string to it's corresponding value. These values are then summed by the extension method Sum().
Edit: As jlafay pointed out, you can omit the Select call and put the projection into the Sum method:
name.Sum(letter => letter - 'A' + 1)
And regarding your original question: You can't access the name of a local variable, even with reflection. That information is not included in the metadata of the compiled code.
Instead of assigning 26 variables for each letter, create an IDictionary<TKey, TValue> where the TKey is the character and the TValue is whatever value you assign. Then you can access the value by passing in the character much more easily.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SO
{
static class Program
{
static void Main()
{
WebClient wc = new WebClient();
var text = wc.DownloadString("http://projecteuler.net/project/names.txt");
var names = Regex.Matches(text, "[A-Z]+").Cast<Match>()
.Select(x => x.Value)
.OrderBy(x => x)
.Select((name, inx) => new
{
Name = name,
Score = name.Sum(c => c - 'A' + 1) * (inx + 1)
});
foreach (var n in names)
{
Console.WriteLine("{0}: {1}", n.Name, n.Score);
}
}
}
}
Related
I want to set each letter of the alphabet to a numeric value: a = 1, b = 2, c = 3, etc.
I created a dictionary to set each letter to a value. I created a function that takes in a word and finds the total value of its letters. How do I access my created dictionary within my function?
Console.WriteLine("YOUR NAME VALUE IS: " + hashFunction("b"));//I want the output to be 2 (b = 2) in this case.
int hashFunction(string name)
{
int totalSum = 0;
Char [] characters = name.ToCharArray();
for (int letterIndex = 0; letterIndex < characters.Length; letterIndex++)
{
totalSum += Convert.ToInt32(characters[letterIndex]);
}
return totalSum;
}
Dictionary<char, int> charValues = new Dictionary<char, int>();
charValues.Add('a', 1);
charValues.Add('b', 2);
charValues.Add('c', 3);
charValues.Add('d', 4);
charValues.Add('e', 5);
//etc etc etc
}
Since letters a..z within ASCII table are consequent we can compute letter index as
letter - 'a' + 1
without elaborated mappig based on dictionary. Then we can use Linq to find the Sum:
using System.Linq;
...
// static : we don't want "this" within the method
static int hashFunction(string name) => name
.Where(c => c >= 'a' && c <= 'z')
.Sum(c => c - 'a' + 1);
Edit: if you insist on dictionary based solution, you can put it like this:
using System.Linq;
...
static IReadOnlyDictionary<char, int> charValues = Enumerable
.Range('a', 'z' - 'a' + 1)
.ToDictionary(letter => (char)letter, letter - 'a' + 1);
int hashFunction(string name)
{
int totalSum = 0;
foreach (char c in name)
if (charValues.TryGetValue(c, out int v))
totalSum += v;
return totalSum;
}
Why do you need a dictionary?
IEnumerable<int> MapCharsToInts( IEnumerable<char> chars )
{
foreach ( char ch in chars.Map( c => Char.ToLower(c) )
{
int v = 1 + ch - 'a' ;
yield v >= 1 && v <= 26 ? v : 0 ;
}
}
How do I access my created dictionary within my function?
by the name of the variable. You use the [ ] brakets like in an array, but you pass a key values as parameter into it. In your case one of the chars that you retrieve from your char array. You can actually use the string directly to access the chars, since it is a char array under the hood:
int hashFunction(string name)
{
int totalSum = 0;
for (int letterIndex = 0; letterIndex < name.Length; letterIndex++)
{
char theKey = name[letterIndex];
totalSum += charValues[theKey];
}
return totalSum;
}
the dictionary will then return the appropriate integer, or it will throw an exception if it does not find any match.
The most important part is that the dictionary has to be declared as field or property on class level! not a local variable in some other method.
This question already has answers here:
Convert char to int in C#
(20 answers)
Closed 3 years ago.
I have just wrote a code(c#) for my sample exam in C# basics study.
Еven though I was able to write it correctly and receive all points, I am not quite satisfied with the way I have used to cast the char ASCII value to the desired int value.
I am asking for a better way to express the following code:
using System;
namespace MultiplyTable
{
class Program
{
static void Main(string[] args)
{
//Input:
string inputNumber = Console.ReadLine();
//Logic:
int firstNumber = 0;
int secondNumber = 0;
int thirdNumber = 0;
for (int i = 0; i < inputNumber.Length; i++)
{
firstNumber = inputNumber[0] - 48;
secondNumber = inputNumber[1] - 48;
thirdNumber = inputNumber[2] - 48;
}
for (int p = 1; p <= thirdNumber; p++)
{
for (int j = 1; j <= secondNumber; j++)
{
for (int k = 1; k <= firstNumber; k++)
{
Console.WriteLine($"{p} * {j} * {k} = {p * j * k};");
}
}
}
}
}
}
The input is an integer three-digit number in the range [111… 999].
I have used string instead of int, to quicker read and store all char values.
The issue here is that when I have the char let's say '3' I need to use the int value of '3' and not the ASCII Dec value of 51.
As I had a limited time to write this code I succeeded to resolve it by subtracting 48 as you can see in the code provided.
What is the correct/more advanced way to do this exercise ?
Thank you in advance!
Substracting foo's ASCII value from 0's ASCII value will give you number.
char foo = '2';
int bar = foo - '0';
Or you can just simply convert char to string and then convert to int:
int bar = int.Parse(foo.ToString());
I have:
int a = 9;
int b = 7;
int c = 3;
How to merge those so it becomes int d = 973; ?
The only thing i managed to come up with is:
string merge = $"{a}{b}{c}";
int d = Int32.Parse(merge);
Is there a more efficient way?
You could do this using Linq's Aggregate:
var input = new[] { a, b, c };
var number = input.Aggregate((t, c) => t * 10 + c);
This multiplies the total by 10 and adds the current number for each number in the input sequence.
Iteratively you'd write it like this:
var number = 0;
foreach (var i in input)
{
number = number * 10 + i;
}
Console.WriteLine(number);
Note that both approaches are prone to integer overflow.
I've tried solving Project Euler Problem 8
I believe I have the right approach, but for some reason I get the exception ("An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll") in below code when i=494.
Line is 38 I believe.
PS. The length of the string is 1000 as shown by debugger too.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace euler8
{
class Program
{
static void Main(string[] args)
{
const String candidate = "73167176531330624919225119674426574742355349194934"+
"96983520312774506326239578318016984801869478851843"+
"85861560789112949495459501737958331952853208805511"+
"12540698747158523863050715693290963295227443043557"+
"66896648950445244523161731856403098711121722383113"+
"62229893423380308135336276614282806444486645238749"+
"30358907296290491560440772390713810515859307960866"+
"70172427121883998797908792274921901699720888093776"+
"65727333001053367881220235421809751254540594752243"+
"52584907711670556013604839586446706324415722155397"+
"53697817977846174064955149290862569321978468622482"+
"83972241375657056057490261407972968652414535100474"+
"82166370484403199890008895243450658541227588666881"+
"16427171479924442928230863465674813919123162824586"+
"17866458359124566529476545682848912883142607690042"+
"24219022671055626321111109370544217506941658960408"+
"07198403850962455444362981230987879927244284909188"+
"84580156166097919133875499200524063689912560717606"+
"05886116467109405077541002256983155200055935729725"+
"71636269561882670428252483600823257530420752963450";
long max = 0;
int length = candidate.Length;
for (int i = 0; i < length - 13; i++)
{
string substring = candidate.Substring(i, i + 13);
int [] x = new int [13];
for(int j = 0; j<13; j++)
x[j]= int.Parse(substring[j].ToString());
long product = 1;
for (int k = 0; k < 13; k++)
product = product * x[k];
if (product > max)
max = product;
}
Console.WriteLine(max.ToString());
}
}
}
Does anyone spot the issue?
It looks like this is stemming from a misunderstanding of how .SubString() works.
string substring = candidate.Substring(i, i + 13);
Most likely should be:
string substring = candidate.Substring(i, 13);
.SubString() is : .SubString(startPosition, length) So adding i + 13 doesn't net you the next 13 characters, but instead the next i + 13 characters from start position i.
String.Substring needs a starting position plus a length, not and end position.
So just use
string substring = candidate.Substring(i, 13);
I have strings that look like "01", "02". Is there an easy way that I can change the string into a number, add 1 and then change it back to a string so that these strings now look like "02", "03" etc. I'm not really good at C# as I just started and I have not had to get values before.
To get from a string to an integer, you can youse int.Parse():
int i = int.Parse("07");
To get back into a string with a specific format you can use string.Format():
strings = string.Format("{0:00}",7);
The latter should give "07" if I understand http://www.csharp-examples.net/string-format-int/ correctly.
You can convert the string into a number using Convert.ToInt32(), add 1, and use ToString() to convert it back.
int number = Convert.ToInt32(originalString);
number += 1;
string newString = number.ToString();
Parse the integer
int i = int.Parse("07");
add to your integer
i = i + 1;
make a new string variable and assign it to the string value of that integer
string newstring = i.ToString();
AddStringAndInt(string strNumber, int intNumber)
{
//TODO: Add error handling here
return string.Format("{0:00}", (int.TryParse(strNumber) + intNumber));
}
static string StringsADD(string s1, string s2)
{
int l1 = s1.Count();
int l2 = s2.Count();
int[] l3 = { l1, l2 };
int minlength = l3.Min();
int maxlength = l3.Max();
int komsu = 0;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < maxlength; i++)
{
Int32 e1 = Convert.ToInt32(s1.PadLeft(maxlength, '0').ElementAt(maxlength - 1 - i).ToString());
Int32 e2 = Convert.ToInt32(s2.PadLeft(maxlength, '0').ElementAt(maxlength - 1 - i).ToString());
Int32 sum = e1 + e2 + komsu;
if (sum >= 10)
{
sb.Append(sum - 10);
komsu = 1;
}
else
{
sb.Append(sum);
komsu = 0;
}
if (i == maxlength - 1 && komsu == 1)
{
sb.Append("1");
}
}
return new string(sb.ToString().Reverse().ToArray());
}
I needed to add huge numbers that are 1000 digit. The biggest number type in C# is double and it can only contain up to 39 digits. Here a code sample for adding very huge numbers treating them as strings.