谋杀脑细胞:13球称重问题(II 验证程序)
在前一篇随笔谋杀脑细胞:13球称重问题及我的解法中我描述了一下我的解法,但有好几个朋友都说我的解法有些问题, 说的我都信心动摇.. 于是把写过的一个验证我的解法的程序修改一下再跑一遍... 其实吧,当时是想写自动求解的程序的, 没思路,没写成,只好改成一个验证程序了. (像UnitTest不? 嘿嘿)
代码送上:
Main Console App
1 using System;
2 using System.Linq;
3
4 class Program
5 {
6 static void Main(string[] args)
7 {
8 var resolver = new Ball13Resolver();
9 IBall13Simulator simulator = null;
10 for (int i = 2; i <= 27; i++)
11 {
12 int wishBadBall = i / 2;
13 bool wishLighter = (i & 1) == 0;
14 simulator = new Ball13Simulator(wishBadBall, wishLighter);
15 bool? isLighter = null;
16 int badBall = resolver.Resolve(simulator, out isLighter);
17
18 if (wishBadBall != badBall) //Incorrect detection.
19 {
20 Console.ForegroundColor = ConsoleColor.Red;
21 }
22 else if (isLighter.HasValue && isLighter == wishLighter) //Correct detection.
23 {
24 Console.ForegroundColor = ConsoleColor.DarkGreen;
25 }
26 else //Correctly detected the bad ball, but could not tell or telled a wrong result that the bad ball is lighter or heavier.
27 {
28 Console.ForegroundColor = ConsoleColor.Yellow;
29 }
30
31 Console.WriteLine("Wish: {0}:{1} \t\tGet:{2}:{3}",
32 wishBadBall,
33 wishLighter ? "Lighter" : "Heavier",
34 badBall,
35 isLighter.HasValue ? (isLighter.Value ? "Lighter" : "Heavier") : "Unknown",
36 simulator.TestedCount);
37 }
38
39 Console.ResetColor();
40 Console.Read();
41 }
42 }
2 using System.Linq;
3
4 class Program
5 {
6 static void Main(string[] args)
7 {
8 var resolver = new Ball13Resolver();
9 IBall13Simulator simulator = null;
10 for (int i = 2; i <= 27; i++)
11 {
12 int wishBadBall = i / 2;
13 bool wishLighter = (i & 1) == 0;
14 simulator = new Ball13Simulator(wishBadBall, wishLighter);
15 bool? isLighter = null;
16 int badBall = resolver.Resolve(simulator, out isLighter);
17
18 if (wishBadBall != badBall) //Incorrect detection.
19 {
20 Console.ForegroundColor = ConsoleColor.Red;
21 }
22 else if (isLighter.HasValue && isLighter == wishLighter) //Correct detection.
23 {
24 Console.ForegroundColor = ConsoleColor.DarkGreen;
25 }
26 else //Correctly detected the bad ball, but could not tell or telled a wrong result that the bad ball is lighter or heavier.
27 {
28 Console.ForegroundColor = ConsoleColor.Yellow;
29 }
30
31 Console.WriteLine("Wish: {0}:{1} \t\tGet:{2}:{3}",
32 wishBadBall,
33 wishLighter ? "Lighter" : "Heavier",
34 badBall,
35 isLighter.HasValue ? (isLighter.Value ? "Lighter" : "Heavier") : "Unknown",
36 simulator.TestedCount);
37 }
38
39 Console.ResetColor();
40 Console.Read();
41 }
42 }
Simulate the balance
public interface IBall13Simulator
{
char Test(int[] left, int[] right);
int BadBallNumber { get; }
int TestedCount { get; }
bool IsBadBallLighter { get; }
}
public class Ball13Simulator : IBall13Simulator
{
private int _badBall;
private bool _isBadBallLighter;
private int _testedCount;
public Ball13Simulator(int badBallNum, bool isBadBallLighter)
{
this._badBall = badBallNum;
this._isBadBallLighter = isBadBallLighter;
this._testedCount = 0;
}
#region IBall13Simulator Members
public char Test(int[] left, int[] right)
{
this._testedCount++;
char result = 'X';
if (left == null || left.Length == 0 || right == null || right.Length == 0 || left.Length != right.Length)
{
throw new Exception("Input error.");
}
if (left.Contains(this.BadBallNumber))
{
result = IsBadBallLighter ? '<' : '>';
}
else if (right.Contains(this.BadBallNumber))
{
result = IsBadBallLighter ? '>' : '<';
}
else
{
result = '=';
}
return result;
}
public int BadBallNumber
{
get { return this._badBall; }
}
public bool IsBadBallLighter
{
get { return this._isBadBallLighter; }
}
public int TestedCount
{
get { return _testedCount; }
}
#endregion
}
{
char Test(int[] left, int[] right);
int BadBallNumber { get; }
int TestedCount { get; }
bool IsBadBallLighter { get; }
}
public class Ball13Simulator : IBall13Simulator
{
private int _badBall;
private bool _isBadBallLighter;
private int _testedCount;
public Ball13Simulator(int badBallNum, bool isBadBallLighter)
{
this._badBall = badBallNum;
this._isBadBallLighter = isBadBallLighter;
this._testedCount = 0;
}
#region IBall13Simulator Members
public char Test(int[] left, int[] right)
{
this._testedCount++;
char result = 'X';
if (left == null || left.Length == 0 || right == null || right.Length == 0 || left.Length != right.Length)
{
throw new Exception("Input error.");
}
if (left.Contains(this.BadBallNumber))
{
result = IsBadBallLighter ? '<' : '>';
}
else if (right.Contains(this.BadBallNumber))
{
result = IsBadBallLighter ? '>' : '<';
}
else
{
result = '=';
}
return result;
}
public int BadBallNumber
{
get { return this._badBall; }
}
public bool IsBadBallLighter
{
get { return this._isBadBallLighter; }
}
public int TestedCount
{
get { return _testedCount; }
}
#endregion
}
My Resolver
public class Ball13Resolver
{
public int Resolve(IBall13Simulator simulator, out bool? isLighter)
{
#region Draft
/*
1,2,3,4 v 5,6,7,8
=
1,2,3 v 9,10,11
= # Bad in(12,13)
1 v 12
= @ 13 Bad
< @ 12 Bad #wBad > wGood
> @ 12 Bad #wBad < wGood
> #Bad in(9, 10, 11), wBad < wGood
9 v 10
= @ 11 Bad
< @ 9 Bad
> @ 10 Bad
< #Bad in(9, 10, 11), wBad > wGood
9 v 10
= @ 11 Bad
< @ 10 Bad
> @ 9 Bad
< # Bad in (1-8); (9 - 13) Good
1,2,3,5,6 v 9,10,11,12,13
= #Bad in(4,7,8), (Bad=4 wB<wG || Bad in (7,8) wB>wG)
7 v 8
= @ Bad = 4 #wB < wG
< @ Bad = 8
> @ Bad = 7
< #Bad in(1,2,3), wBad < wGood
$((1,2,3),<)
> #Bad in(5,6), wBad > wGood
$((5,6),>)
> #The opposite to '<'
*/
#endregion
int badBall = 0;
isLighter = null;
switch (simulator.Test(new int[] { 1, 2, 3, 4 }, new int[] { 5, 6, 7, 8 }))
{
case '=': //Bad in 9 - 13
switch (simulator.Test(new int[] { 1, 2, 3 }, new int[] { 9, 10, 11 }))
{
case '=': //Bad in 12,13
badBall = solve2(new int[] { 12, 13 }, 1, out isLighter, simulator);
break;
case '<': //Bad in 9,10,11, Heavier
isLighter = false;
badBall = solve3(new int[] { 9, 10, 11 }, false, simulator);
break;
case '>': //Bad in 9,10,11, Lighter
isLighter = true;
badBall = solve3(new int[] { 9, 10, 11 }, true, simulator);
break;
}
break;
case '<':
switch (simulator.Test(new int[] { 1, 2, 3, 5, 6 }, new int[] { 9, 10, 11, 12, 13 }))
{
case '=': //Bad in(4,7,8), (Bad=4 wB<wG || Bad in (7,8) wB>wG)
badBall = solve3(new int[] { 7, 8, 4 }, false, simulator);
isLighter = badBall == 4;
break;
case '<': //Bad in(1,2,3), wBad < wGood
isLighter = true;
badBall = solve3(new int[] { 1, 2, 3 }, true, simulator);
break;
case '>': //Bad in(5,6), wBad > wGood
isLighter = false;
badBall = solve2(new int[] { 5, 6 }, false, simulator);
break;
}
break;
case '>': //The opposite to '<'
switch (simulator.Test(new int[] { 5, 6, 7, 1, 2 }, new int[] { 9, 10, 11, 12, 13 }))
{
case '=': //Bad in(8,3,4), (Bad=8 wB<wG || Bad in (3,4) wB>wG)
badBall = solve3(new int[] { 3, 4, 8 }, false, simulator);
isLighter = badBall == 8;
break;
case '<': //Bad in(5,6,7), wBad < wGood
isLighter = true;
badBall = solve3(new int[] { 5, 6, 7 }, true, simulator);
break;
case '>': //Bad in(1,2), wBad > wGood
isLighter = false;
badBall = solve2(new int[] { 1, 2 }, false, simulator);
break;
}
break;
}
return badBall;
}
private int solve3(int[] balls, bool isLighter, IBall13Simulator simulator)
{
int badBall = 0;
switch (simulator.Test(new int[] { balls[0] }, new int[] { balls[1] }))
{
case '=':
badBall = balls[2];
break;
case '<':
badBall = isLighter ? balls[0] : balls[1];
break;
case '>':
badBall = isLighter ? balls[1] : balls[0];
break;
}
return badBall;
}
private int solve2(int[] balls, int goodBall, out bool? isLighter, IBall13Simulator simulator)
{
int badBall = 0;
bool? islighter = null;
switch (simulator.Test(new int[] { balls[0] }, new int[] { goodBall }))
{
case '=':
badBall = balls[1];
islighter = null;
break;
case '<':
badBall = balls[0];
islighter = true;
break;
case '>':
badBall = balls[0];
islighter = false;
break;
}
isLighter = islighter;
return badBall;
}
private int solve2(int[] balls, bool isLighter, IBall13Simulator simulator)
{
int badBall = 0;
switch (simulator.Test(new int[] { balls[0] }, new int[] { balls[1] }))
{
case '=':
badBall = balls[2];
break;
case '<':
badBall = isLighter ? balls[0] : balls[1];
break;
case '>':
badBall = isLighter ? balls[1] : balls[0];
break;
}
return badBall;
}
}
{
public int Resolve(IBall13Simulator simulator, out bool? isLighter)
{
#region Draft
/*
1,2,3,4 v 5,6,7,8
=
1,2,3 v 9,10,11
= # Bad in(12,13)
1 v 12
= @ 13 Bad
< @ 12 Bad #wBad > wGood
> @ 12 Bad #wBad < wGood
> #Bad in(9, 10, 11), wBad < wGood
9 v 10
= @ 11 Bad
< @ 9 Bad
> @ 10 Bad
< #Bad in(9, 10, 11), wBad > wGood
9 v 10
= @ 11 Bad
< @ 10 Bad
> @ 9 Bad
< # Bad in (1-8); (9 - 13) Good
1,2,3,5,6 v 9,10,11,12,13
= #Bad in(4,7,8), (Bad=4 wB<wG || Bad in (7,8) wB>wG)
7 v 8
= @ Bad = 4 #wB < wG
< @ Bad = 8
> @ Bad = 7
< #Bad in(1,2,3), wBad < wGood
$((1,2,3),<)
> #Bad in(5,6), wBad > wGood
$((5,6),>)
> #The opposite to '<'
*/
#endregion
int badBall = 0;
isLighter = null;
switch (simulator.Test(new int[] { 1, 2, 3, 4 }, new int[] { 5, 6, 7, 8 }))
{
case '=': //Bad in 9 - 13
switch (simulator.Test(new int[] { 1, 2, 3 }, new int[] { 9, 10, 11 }))
{
case '=': //Bad in 12,13
badBall = solve2(new int[] { 12, 13 }, 1, out isLighter, simulator);
break;
case '<': //Bad in 9,10,11, Heavier
isLighter = false;
badBall = solve3(new int[] { 9, 10, 11 }, false, simulator);
break;
case '>': //Bad in 9,10,11, Lighter
isLighter = true;
badBall = solve3(new int[] { 9, 10, 11 }, true, simulator);
break;
}
break;
case '<':
switch (simulator.Test(new int[] { 1, 2, 3, 5, 6 }, new int[] { 9, 10, 11, 12, 13 }))
{
case '=': //Bad in(4,7,8), (Bad=4 wB<wG || Bad in (7,8) wB>wG)
badBall = solve3(new int[] { 7, 8, 4 }, false, simulator);
isLighter = badBall == 4;
break;
case '<': //Bad in(1,2,3), wBad < wGood
isLighter = true;
badBall = solve3(new int[] { 1, 2, 3 }, true, simulator);
break;
case '>': //Bad in(5,6), wBad > wGood
isLighter = false;
badBall = solve2(new int[] { 5, 6 }, false, simulator);
break;
}
break;
case '>': //The opposite to '<'
switch (simulator.Test(new int[] { 5, 6, 7, 1, 2 }, new int[] { 9, 10, 11, 12, 13 }))
{
case '=': //Bad in(8,3,4), (Bad=8 wB<wG || Bad in (3,4) wB>wG)
badBall = solve3(new int[] { 3, 4, 8 }, false, simulator);
isLighter = badBall == 8;
break;
case '<': //Bad in(5,6,7), wBad < wGood
isLighter = true;
badBall = solve3(new int[] { 5, 6, 7 }, true, simulator);
break;
case '>': //Bad in(1,2), wBad > wGood
isLighter = false;
badBall = solve2(new int[] { 1, 2 }, false, simulator);
break;
}
break;
}
return badBall;
}
private int solve3(int[] balls, bool isLighter, IBall13Simulator simulator)
{
int badBall = 0;
switch (simulator.Test(new int[] { balls[0] }, new int[] { balls[1] }))
{
case '=':
badBall = balls[2];
break;
case '<':
badBall = isLighter ? balls[0] : balls[1];
break;
case '>':
badBall = isLighter ? balls[1] : balls[0];
break;
}
return badBall;
}
private int solve2(int[] balls, int goodBall, out bool? isLighter, IBall13Simulator simulator)
{
int badBall = 0;
bool? islighter = null;
switch (simulator.Test(new int[] { balls[0] }, new int[] { goodBall }))
{
case '=':
badBall = balls[1];
islighter = null;
break;
case '<':
badBall = balls[0];
islighter = true;
break;
case '>':
badBall = balls[0];
islighter = false;
break;
}
isLighter = islighter;
return badBall;
}
private int solve2(int[] balls, bool isLighter, IBall13Simulator simulator)
{
int badBall = 0;
switch (simulator.Test(new int[] { balls[0] }, new int[] { balls[1] }))
{
case '=':
badBall = balls[2];
break;
case '<':
badBall = isLighter ? balls[0] : balls[1];
break;
case '>':
badBall = isLighter ? balls[1] : balls[0];
break;
}
return badBall;
}
}
编译运行一下,很好玩的. 输出结果也说明了我在前一篇随笔<<谋杀脑细胞:13球称重问题及我的解法>>中的解法和结论是正确的. 希望几天后能把自动求解的程序也发上来.