使用LINQ在C#中使用MasterMind评分算法
我正在寻找一种优雅的方法来计算C#中MasterMind游戏的猜测得分,最好是使用LINQ。
在MasterMind中,代码生成器使用数字1到6生成4位数的密码。可以多次使用数字。 例如,密码是:
int[] secret = { 1, 2, 3, 1 };
代码破解者试图通过猜测来破解密码。 在这个例子中,猜测是:
int[] guess = { 1, 1, 2, 2 };
(代码和猜测现在都存储在一个数组中,但其他集合类型也可以)。
然后,代码制作者通过宣布“黑人”和“白人”的数量来“评分”这个猜测。 从猜测的每个数字中获得黑色,其在值和位置都是正确的。 对于放置在错误位置的每个正确数字,将获得白色。 在该示例中,得分为1黑色(对于位置1中的“1”)和2个白色(对于位置2和3中的“1”和“2”)。
回到问题:我正在寻找一种优雅的方法来计算C#中的猜测分数,最好使用LINQ。 到目前为止,我已经提出了一个计算黑人数量的声明:
int blacks = new int[] { 0, 1, 2, 3 }.Count(i => (guess[i] == secret[i]));
我打算继续说明白人数是总匹配数(3)减去黑人数。 所以我尝试过:
int whites = guess.Intersect(secret).Count() - blacks;
但是,唉,IEnumerable.Intersect()产生{1,2}而不是{1,1,2},因为它只查看不同的数字。 所以它计算白色= 1而不是2。
除了使用“C”样式的嵌套循环之外,我无法想出另一种计算“白人”的方法。 你能? 最好使用LINQ – 我喜欢使用LINQ在代码中表示算法的方式。 执行速度不是真正的问题。
var black = guess .Zip(secret, (g, s) => g == s) .Count(z => z); var white = guess .Intersect(secret) .Sum(c => System.Math.Min( secret.Count(x => x == c), guess.Count(x => x == c))) - black;
鉴于:
int[] secret = { 1, 2, 3, 1 }; int[] guess = { 1, 1, 2, 2 };
然后:
black == 1 && white == 2
这是一种方式(假设我已正确理解问题):
-
找到黑色分数 – 这很容易; 它只是压缩序列并计算匹配的相应元素的数量。
-
找出两个序列之间“共同元素”的数量 – 这必须是白色和黑色分数的总和。
-
找到白色分数 – 只需2.和1之间的差异。
// There must be a nicer way of doing this bit int blackPlusWhite = secret.GroupBy(sNum => sNum) .Join(guess.GroupBy(gNum => gNum), g => g.Key, g => g.Key, (g1, g2) => Math.Min(g1.Count(), g2.Count())) .Sum(); int black = guess.Zip(secret, (gNum, sNum) => gNum == sNum) .Count(correct => correct); int white = blackPlusWhite - black;
编辑:混合黑色和白色。
编辑:( OP不在.NET 4上)在.NET 3.5中,您可以使用以下方法计算黑色:
int black = Enumerable.Range(0, secret.Count) .Count(i => secret[i] == guess[i]);
Ani的答案很好。 这是一种更好(更清晰)的方式来进行分组和加入。
ILookup guessLookup = guess.ToLookup(i => i); int blackPlusWhite ( from secretNumber in secret.GroupBy(i => i) let secretCount = secretNumber.Count() let guessCount = guessLookup[secretNumber.Key].Count() select Math.Min(secretCount, guessCount) ).Sum() int black = Enumerable.Range(0, secret.Count).Count(i => guess[i] == secret[i]); int white = blackPlusWhite - black;