ठीक है, आप वाक्य रचना को ठीक करके चीजों को थोड़ा आसान बना सकते हैं:
def r(a):
i = a.find('0')
~i or exit(a)
[m in[(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3)or a[j]for j in range(81)] or r(a[:i]+m+a[i+1:])for m in'%d'%5**18]
from sys import *
r(argv[1])
थोड़ी सफाई:
from sys import exit, argv
def r(a):
i = a.find('0')
if i == -1:
exit(a)
for m in '%d' % 5**18:
m in[(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3) or a[j] for j in range(81)] or r(a[:i]+m+a[i+1:])
r(argv[1])
ठीक है, इसलिए यह स्क्रिप्ट एक कमांड-लाइन तर्क की अपेक्षा करता है, और इस पर फ़ंक्शन आर को कॉल करता है। अगर उस तार में कोई शून्य नहीं है, तो आर बाहर निकलता है और अपने तर्क को छापता है।
(यदि किसी अन्य प्रकार की वस्तु को पारित किया जाता है, तो कोई भी शून्य पास करने के बराबर नहीं है, और किसी भी अन्य वस्तु को sys.stderr पर प्रिंट किया जाता है और 1 के बाहर निकलने के कोड में परिणाम होता है। विशेष रूप से, sys.exit ("कुछ त्रुटि संदेश") एक प्रकार है किसी प्रोग्राम में त्रुटि होने पर बाहर निकलने का त्वरित तरीका। http://www.python.org/doc/2.5.2/lib/module-sys.html देखें
)
मुझे लगता है कि इसका मतलब यह है कि शून्य खुली जगहों के अनुरूप है, और बिना शून्य वाली पहेली हल हो जाती है। फिर वहाँ है कि बुरा पुनरावर्ती अभिव्यक्ति।
लूप दिलचस्प है: for m in'%d'%5**18
5 ** 18 क्यों? यह पता चला है कि '%d'%5**18मूल्यांकन करता है '3814697265625'। यह एक स्ट्रिंग है जिसमें प्रत्येक अंक 1-9 कम से कम एक बार होता है, इसलिए शायद यह उनमें से प्रत्येक को रखने की कोशिश कर रहा है। वास्तव में, ऐसा दिखता है कि यह क्या r(a[:i]+m+a[i+1:])कर रहा है: पुनरावर्ती कॉलिंग आर, उस स्ट्रिंग से एक अंक द्वारा भरे गए पहले रिक्त के साथ। लेकिन यह केवल तभी होता है जब पहले की अभिव्यक्ति झूठी हो। आइए देखें:
m in [(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3) or a[j] for j in range(81)]
इसलिए प्लेसमेंट केवल तभी किया जाता है जब m उस राक्षस सूची में नहीं है। प्रत्येक तत्व या तो एक संख्या है (यदि पहली अभिव्यक्ति nonzero है) या एक चरित्र (यदि पहली अभिव्यक्ति शून्य है)। मी को एक संभावित प्रतिस्थापन के रूप में खारिज किया जाता है यदि यह एक चरित्र के रूप में प्रकट होता है, जो केवल तभी हो सकता है जब पहली अभिव्यक्ति शून्य हो। अभिव्यक्ति शून्य कब है?
इसके तीन भाग हैं जिन्हें गुणा किया जाता है:
(i-j)%9 जो शून्य है यदि i और j 9 का एक जोड़ है, अर्थात एक ही कॉलम।
(i/9^j/9) जो शून्य है यदि i / 9 == j / 9, अर्थात एक ही पंक्ति।
(i/27^j/27|i%9/3^j%9/3) जो शून्य है यदि ये दोनों शून्य हैं:
i/27^j^27 जो शून्य है यदि i / 27 == j / 27, अर्थात तीन पंक्तियों का एक ही ब्लॉक
i%9/3^j%9/3 जो शून्य है यदि i% 9/3 == j% 9/3, अर्थात तीन कॉलम का एक ही ब्लॉक
यदि इन तीन भागों में से कोई भी शून्य है, तो संपूर्ण अभिव्यक्ति शून्य है। दूसरे शब्दों में, यदि मैं और j एक पंक्ति, स्तंभ, या 3x3 ब्लॉक साझा करते हैं, तो j का मान i पर रिक्त के लिए उम्मीदवार के रूप में उपयोग नहीं किया जा सकता है। अहा!
from sys import exit, argv
def r(a):
i = a.find('0')
if i == -1:
exit(a)
for m in '3814697265625':
okay = True
for j in range(81):
if (i-j)%9 == 0 or (i/9 == j/9) or (i/27 == j/27 and i%9/3 == j%9/3):
if a[j] == m:
okay = False
break
if okay:
r(a[:i]+m+a[i+1:])
r(argv[1])
ध्यान दें कि यदि कोई भी प्लेसमेंट काम नहीं करता है, तो आर वापस आ जाएगा और उस बिंदु पर वापस आ जाएगा, जहां कुछ और चुना जा सकता है, इसलिए यह एक बुनियादी गहराई पहले एल्गोरिथ्म है।
किसी भी आंकड़े का उपयोग नहीं करना, यह विशेष रूप से कुशल नहीं है। मैंने इस पहेली को विकिपीडिया ( http://en.wikipedia.org/wiki/Sudoku ) से लिया है :
$ time python sudoku.py 530070000600195000098000060800060003400803001700020006060000280000419005000080079
534678912672195348198342567859761423426853791713924856961537284287419635345286179
real 0m47.881s
user 0m47.223s
sys 0m0.137s
परिशिष्ट: मैं इसे एक रखरखाव प्रोग्रामर के रूप में कैसे लिखूंगा (इस संस्करण में लगभग 93x स्पीडअप है :)
import sys
def same_row(i,j): return (i/9 == j/9)
def same_col(i,j): return (i-j) % 9 == 0
def same_block(i,j): return (i/27 == j/27 and i%9/3 == j%9/3)
def r(a):
i = a.find('0')
if i == -1:
sys.exit(a)
excluded_numbers = set()
for j in range(81):
if same_row(i,j) or same_col(i,j) or same_block(i,j):
excluded_numbers.add(a[j])
for m in '123456789':
if m not in excluded_numbers:
r(a[:i]+m+a[i+1:])
if __name__ == '__main__':
if len(sys.argv) == 2 and len(sys.argv[1]) == 81:
r(sys.argv[1])
else:
print 'Usage: python sudoku.py puzzle'
print ' where puzzle is an 81 character string representing the puzzle read left-to-right, top-to-bottom, and 0 is a blank'