SORU
14 EKİM 2008, Salı


En kısa Python Çözücü - Nasıl çalışır?Sudoku

Etrafında benim kendi Sudoku çözücü ile oynuyordum ve bu rastladım iyi ve hızlı tasarım için bazı öneriler arıyordu:

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])

Benim uygulama ben kafamda bunları çözmek aynı şekilde Sudokular ama nasıl bu algoritma işe şifreli mi? çözer

http://scottkirkwood.blogspot.com/2006/07/shortest-sudoku-solver-in-python.html

CEVAP
14 EKİM 2008, Salı


Eh, işler biraz daha kolay sözdizimi tamir yapabilirsiniz:

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])

Biraz temizlik:

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])

Tamam, bu yüzden bu komut satırı bağımsız değişkeni bir bekliyor ve aramalar bu işlev r. Eğer bu dize sıfır ise yok, r ve bağımsız çıkar yazdırır.

(Nesnenin başka bir türü geçirilir Yok sıfır geçen eşdeğerdir ve başka bir nesneye yazdırılır sys.bir çıkış stderr ve sonuçları 1 kod. Özellikle, sys.("hata mesajı") exit çıkmak için hızlı bir şekilde bir program ne zaman bir hata oluşur. Bakın http://www.python.org/doc/2.5.2/lib/module-sys.html)

Bu sıfır açık alanlar için uygun olduğu anlamına gelir sanırım, ve sıfır ile bir bulmaca çözüldü. Sonra o iğrenç özyinelemeli ifade var.

İlginç döngü: for m in'%d'%5**18

Nedeni%9/3^j%9/35? '%d'%5**18 '3814697265625' veren çıkıyor. Bu her basamak 1-9 en az bir kez olan bir dize, belki de her yerde çalışıyor. Aslında, bu r(a[:i] m a[i 1:]) ne yapıyor gibi görünüyor: özyinelemeli olarak r, ilk boş bir dize. bir basamak tarafından doldurulmuş arıyorum Ama bu sadece eğer daha önce ifade yanlış olur. Diyelim şuna bak:

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)]

Yerleşim ise m o canavar listesinde ise sadece yapılır. Her öğe ya da bir dizi Eğer ilk ifade sıfır ise () veya bir karakter Eğer ilk ifade sıfırsa (). m yalnızca ilk ifadeyi sıfır ise meydana gelebilecek bir karakter gibi görünür, olası bir ikame olarak dışladı. Ne zaman ifade sıfır olur?

Çarpılır üç bölümden oluşur:

  • Eğer ı ve j 9 ayrı katları ise sıfır olan (i-j)%9, yani aynı sütunda.
  • Ben sıfır olan (i/9^j/9)/9 = = /9, yani aynı satır j.
  • Bunların her ikisi de sıfır olan, (i/27^j/27|i%9/3^j%9/3) sıfır
    • Ben sıfır olan i/27^j^27/27 == j, yani/27 üç sıra aynı blok
    • Ben sıfır olan i%9/3^j%9/3 %9/3 = = %9/3, yani üç sütun aynı blok j

Eğer bu üç bölümden herhangi sıfırsa, tüm ifade sıfır. Eğer ı ve j satır, sütun veya 3 x 3 blok paylaşırsanız diğer bir deyişle, o zaman j değerini ben de boş adayı olarak kullanılabilir. Aha!

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:
      # At this point, m is not excluded by any row, column, or block, so let's place it and recurse
      r(a[:i] m a[i 1:])

r(argv[1])

Eğer yerleşimleri hiçbiri işe eğer, r dönün ve başka bir şey daha temel bir derinlik ilk algoritma, bu yüzden tercih edilebilir bir noktaya yedeklemek unutmayın.

Herhangi bir sezgisel yöntem kullanarak değil, özellikle de verimli değil. Wikipedia (http://en.wikipedia.org/wiki/Sudoku) bu puzzle aldım:

$ time python sudoku.py 530070000600195000098000060800060003400803001700020006060000280000419005000080079
534678912672195348198342567859761423426853791713924856961537284287419635345286179

real    0m47.881s
user    0m47.223s
sys 0m0.137s

Bakım bir programcı olarak (bu sürüm hakkında 93x bir hızlanma var:) yeniden yazmak isterdim . ek:

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:
      # At this point, m is not excluded by any row, column, or block, so let's place it and recurse
      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'

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Matus Slovak

    Matus Slovak

    5 Temmuz 2007
  • Stanislav Petrov

    Stanislav Pe

    7 ŞUBAT 2009
  • WePlayWeWatch

    WePlayWeWatc

    3 Temmuz 2013