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

1747人阅读 评论(0)

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

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

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

### 李显龙后来更新的小提示：

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网站的观点或立场
个人资料
• 访问：4342933次
• 积分：39569
• 等级：
• 排名：第110名
• 原创：559篇
• 转载：28篇
• 译文：13篇
• 评论：749条
微信公众号
我的微信公众号
为你推荐最新的博文~更有惊喜等着你
时光荏苒
白驹过隙
博客专栏
 Go从不放弃到实战 文章：71篇 阅读：420436
 Go从入门到不放弃 文章：45篇 阅读：288934
 Windows客户端开发那些事儿 文章：51篇 阅读：427065