谋杀脑细胞: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 }
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
}
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[] { 1234 }, new int[] { 5678 }))
        {
            
case '='//Bad in 9 - 13
                switch (simulator.Test(new int[] { 123 }, new int[] { 91011 }))
                {
                    
case '='//Bad in 12,13
                        badBall = solve2(new int[] { 1213 }, 1out isLighter, simulator);
                        
break;
                    
case '<'//Bad in 9,10,11, Heavier
                        isLighter = false;
                        badBall 
= solve3(new int[] { 91011 }, false, simulator);
                        
break;
                    
case '>'//Bad in 9,10,11, Lighter
                        isLighter = true;
                        badBall 
= solve3(new int[] { 91011 }, true, simulator);
                        
break;
                }
                
break;
            
case '<':
                
switch (simulator.Test(new int[] { 12356 }, new int[] { 910111213 }))
                {
                    
case '='//Bad in(4,7,8), (Bad=4 wB<wG || Bad in (7,8) wB>wG)
                        badBall = solve3(new int[] { 784 }, false, simulator);
                        isLighter 
= badBall == 4;
                        
break;
                    
case '<'//Bad in(1,2,3), wBad < wGood
                        isLighter = true;
                        badBall 
= solve3(new int[] { 123 }, true, simulator);
                        
break;
                    
case '>'//Bad in(5,6), wBad > wGood
                        isLighter = false;
                        badBall 
= solve2(new int[] { 56 }, false, simulator);
                        
break;
                }
                
break;
            
case '>'//The opposite to '<'
                switch (simulator.Test(new int[] { 56712 }, new int[] { 910111213 }))
                {
                    
case '='//Bad in(8,3,4), (Bad=8 wB<wG || Bad in (3,4) wB>wG)
                        badBall = solve3(new int[] { 348 }, false, simulator);
                        isLighter 
= badBall == 8;
                        
break;
                    
case '<'//Bad in(5,6,7), wBad < wGood
                        isLighter = true;
                        badBall 
= solve3(new int[] { 567 }, true, simulator);
                        
break;
                    
case '>'//Bad in(1,2), wBad > wGood
                        isLighter = false;
                        badBall 
= solve2(new int[] { 12 }, 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球称重问题及我的解法>>中的解法和结论是正确的. 希望几天后能把自动求解的程序也发上来.

 

posted @ 2009-12-21 15:11  Colin.Niu  阅读(373)  评论(0编辑  收藏  举报