我的代码旨在计算姓名分数测试,但是我无法应用以下规则来获得满分。
规则:
字母的首次出现会奖励该字母的正常分数。
第二次出现字母只会奖励四舍五入的分数。
第三次出现字母将获得双倍积分。
如果一个字母在字符串中相邻出现两次,则两个字母的正常分数加倍。
namespace NameScoreTest
{
using System;
using System.Collections.Generic;
public static class Program
{
private static Dictionary<char, int> Letters = 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}
};
static void Main(string[] args)
{
int score = CalculateScore("Thomas");
Console.WriteLine("Score for name Thomas is " + score);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
public static int CalculateScore(String input)
{
// The score
int score = 0;
foreach (char c in input)
{
char o = Char.ToUpper(c);
foreach (var item in Letters)
{
// Must apply rules here
if(o == item.Key)
{
score += item.Value;
}
}
}
return score;
}
}
}
答案 0 :(得分:1)
对于每个字母,必须存储出现的次数。为此,您需要创建一个包含值和出现的类。
class LetterInfo
{
public LetterInfo(int value)
{
Value = value;
}
public int Value { get; }
public int Occurrence{ get; set; }
}
现在您可以使用来初始化字典
private static Dictionary<char, LetterInfo> Letters = new Dictionary<char, LetterInfo>(){
['A'] = new LetterInfo(1),
['B'] = new LetterInfo(3),
['C'] = new LetterInfo(3),
['D'] = new LetterInfo(2),
['E'] = new LetterInfo(1),
['F'] = new LetterInfo(4),
['G'] = new LetterInfo(2),
['H'] = new LetterInfo(4),
['I'] = new LetterInfo(1),
['J'] = new LetterInfo(8),
['K'] = new LetterInfo(5),
['L'] = new LetterInfo(1),
['M'] = new LetterInfo(3),
['N'] = new LetterInfo(1),
['O'] = new LetterInfo(1),
['P'] = new LetterInfo(3),
['Q'] = new LetterInfo(10),
['R'] = new LetterInfo(1),
['S'] = new LetterInfo(1),
['T'] = new LetterInfo(1),
['U'] = new LetterInfo(1),
['V'] = new LetterInfo(4),
['W'] = new LetterInfo(4),
['X'] = new LetterInfo(8),
['Y'] = new LetterInfo(4),
['Z'] = new LetterInfo(10)
};
然后逻辑就这样
int score = 0;
int lastPoints = 0;
char lastLetter = (char)0;
foreach (char c in input) {
char o = Char.ToUpper(c);
if (Letters.TryGetValue(o, out var info)) {
info.Occurrence++; // Keep track of the occurrence.
if (o == lastLetter) {
score += -lastPoints + 4 * info.Points; // Subtract points for last letter
// then add double points for both.
lastPoints = 2 * info.Points;
} else {
switch (info.Occurrence) {
case 1:
lastPoints = info.Points;
break;
case 2:
lastPoints = (info.Points + 1) / 2;
break;
case 3:
lastPoints = 2 * info.Points;
break;
default:
lastPoints = 0;
break;
}
score += lastPoints;
}
lastLetter = o;
}
}
请注意,该代码会记住最后一个字母以及添加到该字母分数中的分数。如果当前字母与最后一个字母相同,则将删除在该字母的最后一个循环中先前计算的点,因为最后一个规则适用于该字母。然后,两个点都加了两倍(即正常点的4倍)。
托马斯-> 11
Emanuelle-> 14有趣,因为您遇到了3次E
和两次L
。
存储点和事件的另一种方法是将它们存储在数组中,并使用字符代码作为索引。在C#中,您可以在char
上执行整数算术运算。索引是用int index = o - 'A';
计算的,即o == 'A'
的索引是0
。
private static int[] Points = new int[26] { 1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3,
10, 1, 1, 1, 1, 4, 4, 8, 4, 10 };
实现基本相同,我们不需要额外的类。
int score = 0;
int lastPoints = 0;
char lastLetter = (char)0;
int[] occurrences = new int[26];
foreach (char c in input) {
char o = Char.ToUpper(c);
if ('A' <= o && o <='Z') {
int index = o - 'A';
occurrences[index]++;
int points = Points[index];
if (o == lastLetter) {
score += -lastPoints + 4 * points;
lastPoints = 2 * points;
} else {
switch (occurrences[index]) {
case 1:
lastPoints = points;
break;
case 2:
lastPoints = (points + 1) / 2;
break;
case 3:
lastPoints = 2 * points;
break;
default:
lastPoints = 0;
break;
}
score += lastPoints;
}
lastLetter = o;
}
}
答案 1 :(得分:0)
您可以使用另一本词典来保存每个字符及其出现次数,然后基于该字符计算点。
Dictionary<char, int> Letters2 = new Dictionary<char, int>() ;
foreach (char c in input)
{
char o = Char.ToUpper(c);
int countofoccur = input.Split(o).Length - 1;
Letters2.Add(o, countofoccur);
}
或使用linq:
Letters2.Add(o, input.Count(x => x == o));
对于点也许不是完美的方法,但是您可以使用switch语句,并且得分必须是double,请将其添加到先前的foreach的末行:
double score = 0;
Dictionary<char, double> Letters3 = new Dictionary<char, double>();
foreach(var c2 in Letters)
{
if (o == c2.Key)
{
switch(countofoccur)
{
case 1:
score = c2.Value;
Letters3.Add(o, score);
break;
case 2:
score = c2.Value+ (0.5 * c2.Value);
Letters3.Add(o, score);
break;
case 3:
score = c2.Value + (0.5 * c2.Value) +2*c2.Value;
Letters3.Add(o, score);
break;
default :
break;
}
}
}
答案 2 :(得分:0)
在这里,您可以使用其他字典来存储事件。我已经测试了几个例子:
public static class Program
{
private static Dictionary<char, int> Letters = 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}
};
private static Dictionary<char, int> occurences = new Dictionary<char, int>();
private static char previous = ' ';
static void Main(string[] args)
{
int score = CalculateScore("Thomas");
Console.WriteLine("Score for name Thomas is " + score);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
public static int CalculateScore(String input)
{
// The score
int score = 0;
foreach (char c in input)
{
char o = Char.ToUpper(c);
if (occurences.ContainsKey(o))
{
occurences[o] += 1;
if (occurences[o] == 2)
{
if (o == previous)
{
score += 3 * letters[o]; //if second letter, than previously was added normal value, thus we add triple value to get to double value for both letters
}
else
{
score += (int) Math.Ceiling(1.0 * letters[o] / 2);
}
}
else if (occurences[o] == 3)
{
if (o == previous)
{
score -= (int) Math.Ceiling(1.0 * letters[o] / 2); //subtracts previously added score for the letter (half of normal value)
score += 4 * letters[o]; //adds double value for 2 letters, thus equals 4
}
else
{
score += 2 * letters[o];
}
}
else if (o == previous)
{
score += 2 * letters[o];
}
}
else
{
occurences[o] = 1;
score += letters[o];
}
previous = o;
Console.WriteLine(score + " " + o);
}
return score;
}
}