同樣演算法的Python和C求解數獨程式速度比較

lt發表於2016-09-17

從網上看到一個毫秒級的C程式,於是把它改寫為python版本,沒想到速度差了很多。
c程式碼,出處 http://tieba.baidu.com/p/718506898

#include "stdio.h"
#include "time.h"
#define bool int
#define false 0
#define true 1
char sd[81];
bool isok = false;

//顯示數獨
void show()
{
    if (isok) puts("求解完成");
else puts("初始化完成");

for (int i = 0; i 〈 81; i++)
    {
    putchar(sd[i] + '0');
    if ((i + 1) % 9 == 0) putchar('\n');
    }
    putchar('\n');
}

//讀取數獨
bool Init()
{
    for (int i = 0; i 〈 81; i++)
    {
    if (sd[i] >= '1' && sd[i] 〈= '9') sd[i] -= '0';
    else sd[i] = 0;
    }
    show();
    return true;
}

//遞迴解決數獨
void force(int k)
{
    if (isok) return;
    if (!sd[k])
    {
    for (int m = 1; m 〈= 9; m++)
    {
    bool mm = true;
    for (int n = 0; n 〈 9; n++)
    {
    if ((m == sd[k/27*27+(k%9/3)*3+n+n/3*6]) || (m == sd[9*n+k%9]) || (m == sd[k/9*9+n]))
    {
    mm = false;
    break;
    }
    }
    if (mm)
    {
    sd[k] = m;
    if (k == 80)
    {
    isok = true;
    show(); //must be here
    return;
    }
    force(k + 1);
    }
    }
    sd[k] = 0;
    }
    else
    {
    if (k == 80)
    {
    isok = true;
    show();
    return;
    }
    force(k + 1);
    }
}

int main()
{
strcpy(sd,"800000000003600000070090200050007000000045700000100030001000068008500010090000400");
    if (Init())
    {
    double start = clock();
    force(0);
    //show();
    printf("耗時%.0fms",clock()-start);
    }
    else puts("初始化錯誤");
}

注:markdown會吃掉程式碼中的小於號,所以改為全形的“〈”。
python程式碼


def force(k):
  global isok
  if isok:  
    return
  if sd[k]==0:
    for m in range(1,10):
     mm = 1
     for n in range(0,9):
        if ((m == sd[k//27*27+(k%9//3)*3+n+n//3*6]) or (m == sd[9*n+k%9]) or (m == sd[k//9*9+n])):
          mm = 0
          break
     if mm:
       sd[k] = m
       if (k == 80):
         isok = 1
         print(sd) #show new sd
         return
       force(k + 1)
    sd[k] = 0
  else:
    if (k == 80):
      isok = 1
      print(sd) #show new sd
      return
    force(k + 1)

isok=0
s="800000000003600000070090200050007000000045700000100030001000068008500010090000400"
sd=list(range(81))
for i in range(81):
  sd[i]=int(s[i])
force(0)
#print(sd) #print old sd

執行比較:

D:\>\timer python py3.py
Timer 9.01 : Igor Pavlov : Public domain : 2009-05-31
[8, 1, 2, 7, 5, 3, 6, 4, 9, 9, 4, 3, 6, 8, 2, 1, 7, 5, 6, 7, 5, 4, 9, 1, 2, 8, 3, 1, 5, 4, 2, 3, 7, 8, 9, 6, 3, 6, 9, 8, 4, 5, 7, 2,
 1, 2, 8, 7, 1, 6, 9, 5, 3, 4, 5, 2, 1, 9, 7, 4, 3, 6, 8, 4, 3, 8, 5, 2, 6, 9, 1, 7, 7, 9, 6, 3, 1, 8, 4, 5, 2]

Kernel Time  =     0.078 =    2%
User Time    =     2.948 =   96%
Process Time =     3.026 =   98%
Global Time  =     3.059 =  100%

D:\>\timer tcc\tcc -run sd2.c
Timer 9.01 : Igor Pavlov : Public domain : 2009-05-31
初始化完成
800000000
003600000
070090200
050007000
000045700
000100030
001000068
008500010
090000400

求解完成
812753649
943682175
675491283
154237896
369845721
287169534
521974368
438526917
796318452

耗時94ms
Kernel Time  =     0.031 =   15%
User Time    =     0.109 =   54%
Process Time =     0.140 =   70%
Global Time  =     0.199 =  100%

同樣的程式,在ptyhon 2.7比3.5也快很多

D:\>python
Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:19:22) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
Timer 3.01  Copyright (c) 2002-2003 Igor Pavlov  2003-07-10
[8, 1, 2, 7, 5, 3, 6, 4, 9, 9, 4, 3, 6, 8, 2, 1, 7, 5, 6, 7, 5, 4, 9, 1, 2, 8, 3, 1, 5, 4, 2, 3, 7, 8, 9, 6, 3, 6, 9, 8, 4, 5, 7, 2, 1, 2, 8, 7, 1, 6,
 9, 5, 3, 4, 5, 2, 1, 9, 7, 4, 3, 6, 8, 4, 3, 8, 5, 2, 6, 9, 1, 7, 7, 9, 6, 3, 1, 8, 4, 5, 2]

Kernel Time  =     0.015 = 00:00:00.015 =   1%
User Time    =     0.951 = 00:00:00.951 =  93%
Process Time =     0.967 = 00:00:00.967 =  95%
Global Time  =     1.014 = 00:00:01.014 = 100%

pypy比python2執行速度也快很多

D:\pypy>\timer python py2.py

Timer 3.01  Copyright (c) 2002-2003 Igor Pavlov  2003-07-10
[8, 1, 2, 7, 5, 3, 6, 4, 9, 9, 4, 3, 6, 8, 2, 1, 7, 5, 6, 7, 5, 4, 9, 1, 2, 8, 3, 1, 5, 4, 2, 3, 7, 8, 9, 6, 3, 6, 9, 8, 4, 5, 7, 2, 1, 2, 8, 7, 1, 6,
 9, 5, 3, 4, 5, 2, 1, 9, 7, 4, 3, 6, 8, 4, 3, 8, 5, 2, 6, 9, 1, 7, 7, 9, 6, 3, 1, 8, 4, 5, 2]

Kernel Time  =     0.031 = 00:00:00.031 =   2%
User Time    =     0.951 = 00:00:00.951 =  83%
Process Time =     0.982 = 00:00:00.982 =  86%
Global Time  =     1.139 = 00:00:01.139 = 100%

D:\pypy>pypy
Python 2.7.10 (c95650101a99, Sep 06 2016, 15:44:55)
[PyPy 5.4.1 with MSC v.1500 32 bit] on win32
Type "help", "copyright", "credits" or "license" for more information.
D:\pypy>timer pypy py2.py

Timer 3.01  Copyright (c) 2002-2003 Igor Pavlov  2003-07-10
[8, 1, 2, 7, 5, 3, 6, 4, 9, 9, 4, 3, 6, 8, 2, 1, 7, 5, 6, 7, 5, 4, 9, 1, 2, 8, 3, 1, 5, 4, 2, 3, 7, 8, 9, 6, 3, 6, 9, 8, 4, 5, 7, 2, 1, 2, 8, 7, 1, 6,
 9, 5, 3, 4, 5, 2, 1, 9, 7, 4, 3, 6, 8, 4, 3, 8, 5, 2, 6, 9, 1, 7, 7, 9, 6, 3, 1, 8, 4, 5, 2]

Kernel Time  =     0.031 = 00:00:00.031 =  13%
User Time    =     0.140 = 00:00:00.140 =  60%
Process Time =     0.171 = 00:00:00.171 =  73%
Global Time  =     0.234 = 00:00:00.234 = 100%

相關文章