Convert lots of if's to something smaller - c#

I need to check a char array and convert every char to a random number value into a int array;
I have managed to do this but with a lot of code.
Is there anyway I can write less code?
for (int i = 0; i < 8; i++)
{
if (oddF[i] == '0')
{
oddFlValue[i] = 1;
continue;
}
else if (oddF[i] == '1')
{
oddFValue[i] = 0;
continue;
}
else if (oddFiscal[i] == '8')
{
oddFiscalValue[i] = 19;
continue;
}
else if (oddF[i] == '9')
{
oddFValue[i] = 21;
continue;
}
else if ((oddF[i] == 'a') || (oddF[i] == 'A'))
{
oddFValue[i] = 1;
continue;
}
else if ((oddF[i] == 'b') || (oddF[i] == 'B'))
{
oddFValue[i] = 0;
continue;
}
This is just a sample as I need to check for every number and letter type.
Thanks!

I think the easiest way to do this would be to use a Dictionary<char, int>, and get its value. Something like this:
Dictionary<char, int> MyCombinations = new Dictionary<char, int>{
{'0', 1},
{'5', 15},
/*etc etc etc*/
};
And then use it like:
for (int i = 0; i < 8; i++)
{
oddFValue[i] = MyCombinations[oddFiscal[i]];
}

class Program
{
static void Main(string[] args)
{
char[] oddF = new char[8]{'0','1','8','A','b','9','a','B'};
int[] oddFValue = new int[8];
Dictionary<char, int> table = new Dictionary<char, int>(){
{ '0', 1 },
{ '1', 0 },
{ '8', 19 },
{ '9', 21 },
{ 'a', 1 },
{ 'A', 1 },
{ 'b', 0 },
{ 'B', 0 }
};
for (int i = 0; i < 8; i++)
{
oddFValue[i] = table[oddF[i]]; // Lookup which function should be called, and call it.
}
}
}

How about:
public int? ConvertCharToInt(char c)
{
switch (c)
{
case '0': return 1;
case '1': return 0;
case '8': return 19;
case '9': return 21;
case 'a':
case 'A': return 1;
case 'b':
case 'B': return 0;
// ...
default: return null;
}
}
And then:
for (int i = 0; i < 8; i++)
{
int? number = ConvertCharToInt(oddF[i]);
if (number.HasValue)
oddFValue[i] = number.Value;
else
// Character cannot be converted to int value
}

Related

Determine whether each character in the first string can be uniquely replaced by a character in the second string so that the two strings are equal

Give two strings of equal size. Determine whether each character in the first string can be uniquely replaced by a character in the second string so that the two strings are equal. Display also the corresponding character pairs between the two strings. The code works well now.
Example 1:
For input data:
aab
ttd
The console will display:
True
a => t
b => d
Example 2:
For input data:
tab
ttd
The console will display:
False
In the second example the answer is false because there is no unique correspondence for the character 'a': both 't' and 'd' correspond to it.
This is my code:
using System;
namespace problemeJM
{
class Program
{
static void Main(string[] args)
{
string firstPhrase = Convert.ToString(Console.ReadLine());
string secondPhrase = Convert.ToString(Console.ReadLine());
string aux1 = string.Empty, aux2 = string.Empty;
bool x = true;
for (int i = 0; i < firstPhrase.Length; i++)
{
if (!aux1.Contains(firstPhrase[i]))
{
aux1 += firstPhrase[i];
}
}
for (int i = 0; i < secondPhrase.Length; i++)
{
if (!aux2.Contains(secondPhrase[i]))
{
aux2 += secondPhrase[i];
}
}
if (aux1.Length != aux2.Length)
{
Console.WriteLine("False");
}
else
{
for (int i = 0; i < firstPhrase.Length - 2; i++)
{
for (int j = 1; j < secondPhrase.Length - 1; j++)
{
if (firstPhrase[i] == firstPhrase[j] && secondPhrase[i] == secondPhrase[j])
{
x = true;
}
else if (firstPhrase[i] != firstPhrase[j] && secondPhrase[i] != secondPhrase[j])
{
x = true;
}
else if (firstPhrase[i] == firstPhrase[j] && secondPhrase[i] != secondPhrase[j])
{
x = false;
break;
}
else if (firstPhrase[i] != firstPhrase[j] && secondPhrase[i] == secondPhrase[j])
{
x = false;
break;
}
}
}
Console.WriteLine(x);
aux1 = string.Empty;
aux2 = string.Empty;
if (x == true)
{
for (int i = 0; i < firstPhrase.Length; i++)
{
if (!aux1.Contains(firstPhrase[i]))
{
aux1 += firstPhrase[i];
}
}
for (int i = 0; i < secondPhrase.Length; i++)
{
if (!aux2.Contains(secondPhrase[i]))
{
aux2 += secondPhrase[i];
}
}
for (int i = 0; i <= aux1.Length - 1; i++)
{
for (int j = 1; j <= aux2.Length; j++)
{
if (aux1[i] == aux1[j] && aux2[i] == aux2[j])
{
Console.WriteLine(aux1[i] + " => " + aux2[i]);
break;
}
else if (aux1[i] != aux1[j] && aux2[i] != aux2[j])
{
Console.WriteLine(aux1[i] + " => " + aux2[i]);
break;
}
}
}
}
}
}
}
}
I think you should use a Dictionary<char, char> as commented. But you need to check if there's a unique mapping in both string, so from s1 to s2 and from s2 to s1:
static bool UniqueMapping(string s1, string s2)
{
int length = Math.Min(s1.Length, s2.Length);
var dict = new Dictionary<char, char>(length);
for (int i = 0; i < length; i++)
{
char c1 = s1[i];
char c2 = s2[i];
bool contained = dict.TryGetValue(c1, out char c);
if (contained && c2 != c)
{
return false;
}
dict[c1] = c2;
}
return true;
}
Here are your samples. Note that i use UniqueMapping twice(if true after 1st):
static void Main(string[] args)
{
var items = new List<string[]> { new[]{ "aab", "ttd" }, new[] { "tab", "ttd" }, new[] { "ala bala portocala", "cuc dcuc efghficuc" }, new[] { "ala bala portocala", "cuc dcuc efghijcuc" } };
foreach (string[] item in items)
{
bool result = UniqueMapping(item[0], item[1]);
if(result) result = UniqueMapping(item[1], item[0]);
Console.WriteLine($"Word 1 <{item[0]}> Word 2 <{item[1]}> UniqueMapping? {result}");
}
}
.NET Fiddle: https://dotnetfiddle.net/4DtIyH

Counting vowels in each line in an array of string C#

I'm writing a code which counts the most frequent word in an array of string , I'm also trying to count the number of vowels in each line of the word , in other words the total number of vowels in all the words which are in the array , I've written the code but it's not working and I can't figure out what's the problem with it , is it because I'm comparing string with char ?
using System;
using System.Collections.Generic;
namespace lab1._2
{
class Program
{
static String findWord(String[] arr)
{
Dictionary<String, int> hs =
new Dictionary<String, int>();
for (int i = 0; i < arr.Length; i++)
{
if (hs.ContainsKey(arr[i]))
{
hs[arr[i]] = hs[arr[i]] + 1;
}
else
{
hs.Add(arr[i], 1);
}
}
String key = "";
int value = 0;
foreach (KeyValuePair<String, int> me in hs)
{
if (me.Value > value)
{
value = me.Value;
key = me.Key;
}
}
return key;
}
static void Main(string[] args)
{
int s;
//char[] v = new char[10] {'a','A','e','E','i','I','o','O','u','U'};
Console.WriteLine("Enter size of array : ");
s = Convert.ToInt32(Console.ReadLine());
string[] arr = new string[s];
Console.WriteLine("Enter string elements : ");
for (int i = 0; i < s; i++)
{
arr[i] = Console.ReadLine();
}
Console.WriteLine("\nArray elements : ");
for (int i = 0; i < s; i++)
{
Console.WriteLine(arr[i]);
}
Console.WriteLine("\nThe most frequent word : ");
Console.WriteLine(findWord(arr));
int vowel = 0, cons = 0;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] == "a" || arr[i] == "e" || arr[i] == "i" || arr[i] == "o" || arr[i]
== "u")
{
vowel++;
}
else
cons++;
}
Console.WriteLine("Vowels : ");
Console.WriteLine(vowel);
Console.WriteLine("Consants : ");
Console.WriteLine(cons);
}
}
}
I think the problem is that arr is an array of string and you are iterating through it as if it was a single string.
A simple way of doing this would be to have a nested loop.
foreach (var s in arr) // s is a string
{
for (int i = 0; i < s.Length; i++)
{
if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u')
{
vowel++;
}
else
cons++;
}
}
https://dotnetfiddle.net/tI3oTc
using System;
public class Program
{
public static void Main()
{
int vowel = 0;
int cons = 0;
string[] arr = new string[]{"test"};
foreach (var s in arr) // s is a string
{
for (int i = 0; i < s.Length; i++)
{
if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u')
{
vowel++;
}
else
cons++;
}
}
Console.WriteLine(vowel);
}
}

C# algorithm searching words by numbers

I have to write algotithm in C# where input is:
3 2
aj
oj
ck
25
73
and the output:
aj ck
DOES NOT EXIST
The first line in iput is two numbers, the first one is number of words. And the second one is number of numbers for which we will be searching for words. Each character is represented by number like this below:
2 (abc)
3 (def)
4 (ghi)
5 (jkl)
6 (mno)
7 (pqrs)
8 (tuv)
9 (wxyz)
For example for number 25, there are 9 two-char-words: aj, ak, al, bj, bk, bl, cj, ck, cl.
For number 438, there are 27 three-char-words, etc.
So far I have this code, but something is not working properly, and I have no idea what is it that is not working.
int n;
int k;
string input;
List<string> dict = new List<string>();
List<string> res = new List<string>();
n = int.Parse(Console.ReadLine());
k = int.Parse(Console.ReadLine());
for (int i = 0; i < n; i++)
{
input = Console.ReadLine();
dict.Add(input);
}
dict.Sort();
for (int i = 0; i < k; i++)
{
input = Console.ReadLine();
res = new List<string>(dict);
int inputLength = input.Length;
for (int j = 0; j < inputLength; ++j)
{
switch (input[j])
{
case '2':
res = new List<string>(filter(res, i, 'a', 'b', 'c'));
break;
case '3':
res = new List<string>(filter(res, i, 'd', 'e', 'f'));
break;
case '4':
break;
case '5':
res = new List<string>(filter(res, i, 'j', 'k', 'l'));
break;
case '6':
res = new List<string>(filter(res, i, 'm', 'n', 'o'));
break;
case '7':
res = new List<string>(filterWithFour(res, i, 'p', 'q', 'r', 's'));
break;
case '8':
res = new List<string>(filter(res, i, 't', 'u', 'v'));
break;
case '9':
res = new List<string>(filterWithFour(res, i, 'w', 'x', 'y', 'z'));
break;
}
}
if (res.Any())
foreach (var item in res.ToList())
Console.WriteLine(item);
else
Console.WriteLine("DOES NOT EXIST");
}
static List<string> filterWithFour(List<string> resGiven, int pos, char a, char b, char c, char d)
{
List<string> res = new List<string>();
foreach (var item in resGiven.ToList())
{
if (item.Length > pos)
if (item[pos] == a || item[pos] == b || item[pos] == c || item[pos] == d)
res.Add(item);
}
return res;
}
static List<string> filter(List<string> resGiven, int pos, char a, char b, char c)
{
List<string> res = new List<string>();
foreach (var item in resGiven.ToList())
{
if (item.Length > pos)
if (item[pos] == a || item[pos] == b || item[pos] == c)
res.Add(item);
}
return res;
}
Thank you for any help, because I stuck on this one, and I can't go through it.
In order to do what you want, I would replace the numbers with Regex pattern as such:
using System.IO;
using System;
using System.Collections.Generic;
using System.Linq; // so you can use .Where on List
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
int n;
int k;
string input;
List<string> dict = new List<string>();
n = int.Parse(Console.ReadLine());
k = int.Parse(Console.ReadLine());
for (int i = 0; i < n; i++)
{
input = Console.ReadLine();
dict.Add(input);
}
dict.Sort();
for (int i = 0; i < k; i++)
{
input = Console.ReadLine();
// get the full pattern for the whole number
string patternToSearch = "";
foreach(var c in input)
{
patternToSearch += GetPattern(c);
}
Console.WriteLine(patternToSearch);
// find the words that matches the pattern
var filteredDict = dict.Where(w => Regex.Match(w, patternToSearch).Success);
if(!filteredDict.Any())
Console.WriteLine("DOES NOT EXIST");
else
Console.WriteLine(string.Join(" ", filteredDict));
}
}
// returns the regex pattern for one number
static string GetPattern(char c)
{
switch(c)
{
case '2': return "[abc]";
case '3': return "[def]";
case '4': return "[ghi]";
case '5': return "[jkl]";
case '6': return "[mno]";
case '7': return "[pqrs]";
case '8': return "[tuv]";
case '9': return "[wxyz]";
default: return "";
}
}
}
With input:
3
2
aj
oj
ck
25
73
It outputs:
[abc][jkl]
aj ck
[pqrs][def]
DOES NOT EXIST

How to calculate output of Infix-Expression by using stacks in C#

I already found different solutions on Stackoverflow, but there were some things I didnĀ“t understand.
Whats the best method to calculate the Output of e.g.: ((1+(4*(2+3)))+((2+3)*(4*5))) ?
My method looks as following, but I know there are lots of mistakes in it:
public static int ComputeInfix(string infix) {
Stack<char> operatorstack = new Stack<char>();
Stack<int> operandstack = new Stack<int>();
for(int j = 0; j < infix.Length; j++) {
char c = infix[j];
if (c => 0 && c <= 9) {
operandstack.Push(c);
}
else if ((c == '+' || c == '*' || c == '/' || c == '-')) {
if (operatorstack.IsEmpty()) {
operatorstack.Push(c);
}
else {
if (operatorstack.Peek() != '*' || operatorstack.Peek() != '/') {
operatorstack.Push(c);
}
}
}
else if (c == '(') {
operatorstack.Push(c);
}
else if (c == ')') {
operatorstack.Pop();
}
}
return infix;
}
Now changed it to:
Stack<char> operatorstack = new Stack<char>();
Stack<char> operandstack = new Stack<char>();
for(int j = 0; j < infix.Length; j++) {
char c = infix[j];
if (c => '0' && c <= '9') {
operandstack.Push(c);
}
But get error:
Infix.cs(16,8): error CS0136: A local variable named c' cannot be
declared in this scope because it would give a different meaning to
c', which is already used in a `parent or current' scope to denote
something else
Since I spent the time to write it, here is my solution:
public static int ComputeInfix(string infix) {
var operatorstack = new Stack<char>();
var operandstack = new Stack<int>();
var precedence = new Dictionary<char, int> { { '(', 0 }, { '*', 1 }, { '/', 1 }, { '+', 2 }, { '-', 2 }, { ')', 3 } };
foreach (var ch in $"({infix})") {
switch (ch) {
case var digit when Char.IsDigit(digit):
operandstack.Push(Convert.ToInt32(digit.ToString()));
break;
case var op when precedence.ContainsKey(op):
var keepLooping = true;
while (keepLooping && operatorstack.Count > 0 && precedence[ch] > precedence[operatorstack.Peek()]) {
switch (operatorstack.Peek()) {
case '+':
operandstack.Push(operandstack.Pop() + operandstack.Pop());
break;
case '-':
operandstack.Push(-operandstack.Pop() + operandstack.Pop());
break;
case '*':
operandstack.Push(operandstack.Pop() * operandstack.Pop());
break;
case '/':
var divisor = operandstack.Pop();
operandstack.Push(operandstack.Pop() / divisor);
break;
case '(':
keepLooping = false;
break;
}
if (keepLooping)
operatorstack.Pop();
}
if (ch == ')')
operatorstack.Pop();
else
operatorstack.Push(ch);
break;
default:
throw new ArgumentException();
}
}
if (operatorstack.Count > 0 || operandstack.Count > 1)
throw new ArgumentException();
return operandstack.Pop();
}

Creating a Score Method for an Array

My goal is to create a score method for a simple game based in an array. The game consists of putting 'R's or 'B's in one of 11 positions in an array. Once the array is full, the score method will execute as follows:
Any single 'R' or 'B' is worth 0 points
Any pair of 'R's or 'B's is worth 4 points
Any triple of 'R's or 'B's is worth 6 points
... and so on.
I'm having trouble calculating the score and I feel like I am missing something obvious so I'm coming here. The code I have looks for pairs and adds 2 to the score, but I end up missing 2 points (since the first pair is worth 4 and each additional "pair" is worth another 2).
public int score(char color)
{
int score = 0;
for (int i = 0; i < gameBoard.Length - 1; i++)
{
if (gameBoard[i] == color && gameBoard[i + 1] == color)
score += 2;
else
score += 0;
}
return score;
}
Your problem can be solved by regular expressions.
public int CalculateScore(char color)
{
var boardStr = String.Join("", gameBoard);
return GetCharacterSequences(color, boardStr)
.Sum(str => str.Length * 2);
}
//Returns same character sequences of length more than two.
private IEnumerable<string> GetCharacterSequences(char color, string boardStr)
{
return Regex.Matches(boardStr, $#"({color})\1+").OfType<Match>()
.SelectMany(match => match.Groups.OfType<Group>())
.Select(#group => #group.Value)
.Where(str => str.Length > 1);
}
Idea of sum function: Each pair costs 4 points, each triple costs 6 points hence each single char costs 2 points.
GetCharacterSequences looks little bit complex but it makes CalculateScore method very simple.
Well you could create a boolean variable and use that to determine the number of points added.
Note: This code doesn't account for triple matches as you've mentioned in your question.
public int score(char color)
{
int score = 0;
bool firstMatch = true;
for (int i = 0; i < gameBoard.Length - 1; i++)
{
if (gameBoard[i] == color && gameBoard[i + 1] == color) {
if (firstMatch == true) {
score += 4;
firstMatch = false;
} else {
score += 2;
}
}
else
{
score += 0;
}
}
return score;
}
Here's another approach, based on a pair being 4 points, 3 being 6 points, and assuming 4 being 8 points and so forth (basically number of adjacent colors * 2 if there is at least a pair).
public int score(char color)
{
int adj = 0;
int score = 0;
for (int i = 0; i < gameBoard.Length; i++)
{
if (gameBoard[i] == color)
{
adj++;
}
else
{
if (adj > 1)
{
score += adj * 2;
}
adj = 0;
}
}
}
This code loops through the array, and keeps a count of the number of adjacent spots marked by the specified color. When it comes to an element of the array that is not the right color, it checks to see how many adjacent elements had the correct color.
If it's greater than 1, then it multiplies the number of adjacent elements by 2 and resets the adjacent elements counter to 0 and continues through the array.
Given an array of 'R', 'R', 'B', 'B', 'B', 'R', 'R', 'R', 'B', 'R', 'B', it produces a score of 10 for 'R' (4 + 6) and 6 for 'B' (6), as follows:
'R', 'R' = 4
'R', 'R', 'R' = 6
'R' = 0
'B', 'B', 'B' = 6
'B' = 0
Here is what i came up with
namespace TestApp1
{
class Program
{
static void Main(string[] args)
{
string[] test = GetValues();
string testView = String.Join(String.Empty, test);
string score = GetScore(test).ToString();
Console.WriteLine(testView);
Console.WriteLine(score);
Console.ReadLine();
}
public static int GetScore(string[] test)
{
int score = 0;
int occurence = 0;
string LastChar = string.Empty;
for (int i = 0; i < test.Length; i++)
{
if(LastChar == string.Empty)
{
LastChar = test[i];
occurence += 1;
continue;
}
if(LastChar == test[i])
{
occurence += 1;
if(i == test.Length - 1)
{
if (occurence > 1)
{
score += occurence * 2;
}
}
}
else
{
if(occurence > 1)
{
score += occurence * 2;
}
LastChar = test[i];
occurence = 1;
}
}
return score;
}
public static string[] GetValues()
{
List<string> values = new List<string>();
for (int i = 0; i < 12; i++)
{
var rnd = new Random(DateTime.Now.Millisecond);
int ticks = rnd.Next(0, 2);
values.Add(ticks == 1 ? "R" : "B");
System.Threading.Thread.Sleep(2);
}
return values.ToArray();
}
}
}
To calculate each score independently
namespace TestApp1
{
class Program
{
static void Main(string[] args)
{
string[] test = GetValues();
string testView = String.Join(String.Empty, test);
int rScore = 0;
int bScore = 0;
GetScore(test,out rScore, out bScore);
string score = "R: " + rScore.ToString() + " B: " + bScore.ToString();
Console.WriteLine(testView);
Console.WriteLine(score);
Console.ReadLine();
}
public static void GetScore(string[] test, out int rScore, out int bScore)
{
int occurence = 0;
string LastChar = string.Empty;
rScore = 0;
bScore = 0;
for (int i = 0; i < test.Length; i++)
{
if(LastChar == string.Empty)
{
LastChar = test[i];
occurence += 1;
continue;
}
if(LastChar == test[i])
{
occurence += 1;
if(i == test.Length - 1)
{
if (occurence > 1)
{
if(LastChar == "R")
{
rScore += occurence * 2;
}
else
{
bScore += occurence * 2;
}
}
}
}
else
{
if(occurence > 1)
{
if (LastChar == "R")
{
rScore += occurence * 2;
}
else
{
bScore += occurence * 2;
}
}
LastChar = test[i];
occurence = 1;
}
}
}
public static string[] GetValues()
{
List<string> values = new List<string>();
for (int i = 0; i < 12; i++)
{
var rnd = new Random(DateTime.Now.Millisecond);
int ticks = rnd.Next(0, 2);
values.Add(ticks == 1 ? "R" : "B");
System.Threading.Thread.Sleep(2);
}
return values.ToArray();
}
}
}

Categories