新加坡总理公开多年前写的数独程序源码(C++版)

标签: c++facebook数读
1498人阅读 评论(0) 收藏 举报
分类:

/*---------------------------------------------------------------------------------------

新加坡总理李显龙两周前在一个创业者论坛上透露,他最后编写的一个程序是解决数独问题的程序(Sudoku solver),还是多年前用 C++ 实现的。

李显龙今天在个人 Facebook 主页公布了程序源码。


李显龙说:

这个程序非常基础,在 DOS 窗口下运行。按行输入数据(比如:1-3-8—6),程序会打印出解决方案(如果有多种方案,则输出所有的)、程序所用的步数,还有一些搜索数据。

该程序做了回溯搜索,选择下一个扇出(fanout)最小的单元格。


李显龙给读源码的朋友留了一个问题:如果 X 是一个(二进制)整数,那 (x & -x) 怎么计算的呢?

如果各位发现了他 Bug,可给他留言!


李显龙后来更新的小提示:

As several of you noted, (x & –x) returns the least significant ‘1’ bit of x, i.e. the highest power of two that divides x. This assumes two’s complement notation for negative numbers, as some of you also pointed out. e.g. if x=12 (binary 1100), then (x & -x) = 4 (binary 100). I didn’t invent this; it is an old programming trick.

-----------------------------------------------------------------------------------------*/

#include "stdio.h"

 
int InBlock[81], InRow[81], InCol[81];
 
const int BLANK = 0;
const int ONES = 0x3fe;     // Binary 1111111110
 
int Entry[81];  // Records entries 1-9 in the grid, as the corresponding bit set to 1
int Block[9], Row[9], Col[9];   // Each int is a 9-bit array
 
int SeqPtr = 0;
int Sequence[81];
 
int Count = 0;
int LevelCount[81];
 
void SwapSeqEntries(int S1, int S2)
{
     int temp = Sequence[S2];
     Sequence[S2] = Sequence[S1];
     Sequence[S1] = temp;
}
 
void InitEntry(int i, int j, int val)
{
     int Square = 9 * i + j;
     int valbit = 1 << val;
     int SeqPtr2;
 
     // add suitable checks for data consistency
 
     Entry[Square] = valbit;
     Block[InBlock[Square]] &= ~valbit;
     Col[InCol[Square]] &= ~valbit; // Simpler Col[j] &= ~valbit;
     Row[InRow[Square]] &= ~valbit; // Simpler Row[i] &= ~valbit;
 
     SeqPtr2 = SeqPtr;
     while (SeqPtr2 < 81 && Sequence[SeqPtr2] != Square)
           SeqPtr2++ ;
 
     SwapSeqEntries(SeqPtr, SeqPtr2);
     SeqPtr++;
}
 
void PrintArray()
{
     int i, j, valbit, val, Square;
     char ch;
 
     Square = 0;
 
     for (i = 0; i < 9; i++) {
         if (i % 3 == 0) putc('\n', stdout);
         for (j = 0; j < 9; j++) {
             if (j % 3 == 0) putc(' ', stdout);
             valbit = Entry[Square++];
             if (valbit == 0) ch = '-';
             else {
                 for (val = 1; val <= 9; val++)
                     if (valbit == (1 << val)) {
                        ch = '0' + val;
                        break;
                     }
             }   
             putc(ch,stdout);
         }
         putc ('\n', stdout);
     }
}
 
void ConsoleInput()
{
     int i, j;
     char InputString[80];
 
     for (i = 0; i < 9; i++) {
         printf("Row[%d] : ", i + 1);
         scanf("%s", InputString);
 
         for (j = 0; j < 9; j++) {
             char ch = InputString[j];
             if (ch >= '1' && ch <= '9')
                InitEntry(i, j, ch - '0');
         }
     }
 
     PrintArray();
}
 
void PrintStats()
{
    int i, j, S;
 
    printf("\nLevel Counts:\n\n");
 
    S = 0;
    while (LevelCount[S] == 0) S++;
 
    i = 0;
 
    while (S < 81) {
          int Seq = Sequence[S];
          printf("(%d, %d):%4d ", Seq / 9 + 1, Seq % 9 + 1, LevelCount[S]);
          if (i++ > 4){
             printf("\n");
             i = 0;
          }
          S++;
    }
 
    printf("\n\nCount = %d\n", Count);
}
 
void Succeed()
{
     PrintArray();
     PrintStats();
}
 
int NextSeq(int S)
{
    int S2, Square, Possibles, BitCount;
    int T, MinBitCount = 100;
 
    for (T = S; T < 81; T++) {
        Square = Sequence[T];
        Possibles = Block[InBlock[Square]] & Row[InRow[Square]] & Col[InCol[Square]];
        BitCount = 0;
        while (Possibles) {
           Possibles &= ~(Possibles & -Possibles);
           BitCount++;
        }
 
        if (BitCount < MinBitCount) {
           MinBitCount = BitCount;
           S2 = T;
        }
    }
 
    return S2;
}
 
void Place(int S)
{
    LevelCount[S]++;
    Count++;
 
    if (S >= 81) {
       Succeed();
       return;
    }
 
    int S2 = NextSeq(S);
    SwapSeqEntries(S, S2);
 
    int Square = Sequence[S];
 
    int     BlockIndex = InBlock[Square],
            RowIndex = InRow[Square],
            ColIndex = InCol[Square];
 
    int     Possibles = Block[BlockIndex] & Row[RowIndex] & Col[ColIndex];
    while (Possibles) {
          int valbit = Possibles & (-Possibles); // Lowest 1 bit in Possibles
          Possibles &= ~valbit;
          Entry[Square] = valbit;
          Block[BlockIndex] &= ~valbit;
          Row[RowIndex] &= ~valbit;
          Col[ColIndex] &= ~valbit;
 
          Place(S + 1);
 
          Entry[Square] = BLANK; // Could be moved out of the loop
          Block[BlockIndex] |= valbit;
          Row[RowIndex] |= valbit;
          Col[ColIndex] |= valbit;
    }
 
    SwapSeqEntries(S, S2);
}
 
int main(int argc, char* argv[])
{
    int i, j, Square;
 
    for (i = 0; i < 9; i++)
        for (j = 0; j < 9; j++) {
            Square = 9 * i + j;
            InRow[Square] = i;
            InCol[Square] = j;
            InBlock[Square] = (i / 3) * 3 + ( j / 3);
        }
 
    for (Square = 0; Square < 81; Square++) {
        Sequence[Square] = Square;
        Entry[Square] = BLANK;
        LevelCount[Square] = 0;
    }
 
    for (i = 0; i < 9; i++)
        Block[i] = Row[i] = Col[i] = ONES;
 
    ConsoleInput();
    Place(SeqPtr);
    printf("\n\nTotal Count = %d\n", Count);
 
    return 0;

}




程序运行的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
C:\CPP>sudoku2
Row[1] : ---------
Row[2] : -----3-85
Row[3] : --1-2----
Row[4] : ---5-7---
Row[5] : --4---1--
Row[6] : -9-------
Row[7] : 5------73
Row[8] : --2-1----
Row[9] : ----4---9
 
 --- --- ---
 --- --3 -85
 --1 -2- ---
 
 --- 5-7 ---
 --4 --- 1--
 -9- --- ---
 
 5-- --- -73
 --2 -1- ---
 --- -4- --9
 
 987 654 321
 246 173 985
 351 928 746
 
 128 537 694
 634 892 157
 795 461 832
 
 519 286 473
 472 319 568
 863 745 219
 
Level Counts:
 
(3, 9):   1 (8, 9):   2 (4, 9):   4 (5, 9):   8 (6, 9):  15 (1, 9):  23
(3, 8):  33 (8, 8):  46 (4, 8):  79 (1, 8): 119 (5, 8): 182 (6, 8): 250
(9, 8): 287 (4, 7): 347 (6, 7): 478 (6, 5): 588 (6, 1): 732 (6, 3): 828
(6, 4): 862 (6, 6): 895 (4, 5): 795 (4, 3): 761 (5, 5): 843 (7, 5): 829
(2, 5): 616 (1, 5): 594 (2, 7): 543 (2, 3): 565 (7, 3): 551 (2, 4): 577
(3, 6): 565 (3, 4): 590 (1, 4): 572 (1, 6): 595 (7, 4): 612 (5, 4): 576
(7, 6): 476 (7, 7): 389 (7, 2): 262 (4, 2): 184 (2, 2): 140 (2, 1):  95
(5, 6):  56 (8, 7):  34 (8, 6):  18 (3, 1):  13 (8, 1):  10 (3, 7):   7
(3, 2):   8 (1, 7):  10 (5, 1):  10 (5, 2):   6 (8, 2):   4 (8, 4):   2
(9, 1):   1 (1, 1):   1 (9, 2):   1 (9, 3):   1 (9, 4):   1 (4, 1):   1
(9, 6):   1 (9, 7):   1 (1, 3):   1 (1, 2):   1
 
Count = 17698
 
Total Count = 24395
 
C:\CPP>

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3733453次
    • 积分:34419
    • 等级:
    • 排名:第133名
    • 原创:523篇
    • 转载:28篇
    • 译文:13篇
    • 评论:707条
    微信公众号
      我的微信公众号
      为你推荐最新的博文~更有惊喜等着你
    头条号
      我的头条号
      为你推荐最新的博文~更有惊喜等着你
    时光荏苒
      白驹过隙
    博客专栏
    文章分类
    百度统计
    Google Analytics