Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
курсач.docx
Скачиваний:
51
Добавлен:
25.11.2018
Размер:
1.35 Mб
Скачать

Составление судоку

Составление судоку может осуществляться двумя методами – либо сокрытием случайной ячейки после составления правильного латинского квадрата, либо наоборот открытием случайных ячеек. В первом случае после каждого шага выполняется решение и проверяется количество итераций и их сложность (применение методов первичных, slicing and dicing, предположений).

Составление открытием

Но несмотря на то, что цифры из доски выполняется в порядке, обратном заполнению, всё равно возможно получение недетерменированного судоку и данную проблему разрешить невозможно.

Решение вычёркиванием

Решение вычёркиванием состоит в получении правильного латинского квадрата. Затем в полученном латинском квадрате рекурсивно осуществляются перестановки строк, столбцов и малых квадратов в соответствие с требованиями. Затем происходит вычёркивание случайного элемента и решение полученного судоку на основе методов решения. Сложность алгоритма определяется количеством итераций, которые необходимы для решения.

Переносимость и интегрируемость

Так как программа написана на Python, программа является переносимой на любую платформу (Windows, Linux, MacOS).

В целях интегрируемости программа принимает параметры в командной строке. Перечень параметров:

-t, --type – [math | sudoku] – тип шаблона, математические формулы по предметной области или судоку

-a, --task – [solve | generate] – задание, решить или создать, для шаблона math по умолчанию - решить

-m, --method – [[None] | [brute | analytic] | [opening | cut]] – метод, не применим для шаблона math, принимает значения brute или analytic при задании solve или opening или cut при задании generate

-q, --template – шаблон для математических формул

-i, --input – входной файл

-o, --output – выходной файл

Литература

  1. Нечаев В.В. Концептуальное модельное представление задачи как системы. Информационные технологии, № --. 2009. ----- с.

  2. http://www.angusj.com/sudoku/hints.php

Приложение. Программный код Решатель математических моделей

# -*- coding: cp1251 -*-

import math

import codecs

import re

import sys

import string

import graphWindow

import copy

class solver():

def __init__(self, data, rules, goals, **kwargs):

self._recursionLevel = 0

self.data = (data.lower()).split("\n")

self.rules = (rules.lower()).split("\n")

self.goals = (goals.lower()).split("\n")

self.rawgoals = self.goals

self.templateVars = kwargs.get('templateVars', {})

self.templateFull = kwargs.get('templateFull', {})

self.sErrTxt = ''

self.sSolveTxt = ''

self.env = kwargs.get('env', {})

self.__globals = {}

self.__locals = {}

self.fString = []

self.parent = kwargs.get('parent', None)

self.analyzeData()

self.analyzeRules()

self.analyzeGoals()

self.makeSolveFor()

#for g in self.goals:

#self.makeSolveFor(g)

def analyzeData(self):

self.definiedVariables = []

for q in self.data:

r = q.split('=')

self.definiedVariables.append(r[0].strip())

self.definiedVariablesFirst = copy.copy(self.definiedVariables)

def analyzeRules(self):

print self.rules

self.ruledVariablesLeft = []

self.ruledVariablesRight = []

l = 0

for q in self.rules:

r = q.split('=')

self.ruledVariablesLeft.append(r[0])

try:

r[1]

except IndexError:

self.solveErr = 31

self.solveErrExtend = { 'vString' : r}

self.solveErrorsText()

return

splRules = re.split('([A-Za-z]+)([0-9]*)', r[1])

self.ruledVariablesRight.append([])

print splRules

for sId in range(len(splRules)-1):

sRule = splRules[sId]

nsRule = splRules[sId+1]

if re.match('^[A-Za-z]+$', sRule) and ('' == nsRule or re.match('^[0-9]+$', nsRule)):

print sRule+nsRule

self.ruledVariablesRight[l].append(str(sRule+nsRule))

l = l + 1

def analyzeGoals(self):

goals = self.goals

self.goals = []

for i in goals:

goalParts = re.split('(^[A-Za-z]+)([0-9]+)$', i)

self.goals.append({ 'goalLine' : i,

'goalParts' : goalParts if goalParts[0] != '' else goalParts[1:3]

})

def makeSolveFor(self):

print 'Solving'

print self.ruledVariablesLeft

print self.ruledVariablesRight

print self.goals

self.solveErr = 0

self.solveErrExtend = {}

self.solution = 0

self.solutionString = 'крабе'

exec('import math', self.__globals, self.__locals)

for cGoal in self.goals:

if cGoal['goalParts'][0] not in self.templateVars['vars'].lower().split(','):

self.solveErr = 24

self.solveErrExtend = { 'vName' : cGoal['goalParts'][0], 'dVars' : self.templateVars['vars']}

for cGoal in self.goals:

print 'definded: '+ ''.join(self.definiedVariables)

print 'goal:'+cGoal['goalLine']

if cGoal['goalLine'] in self.definiedVariables:

print 'Found'

self.solveErr = 14

self.solveErrExtend = cGoal['goalLine']

self.solveErrorsText()

return

if self._recursionLevel == 0:

for iData in self.data:

if iData.strip() == '':

break

try:

exec(iData+';', self.__globals, self.__locals)

self.log("Ввод (exec) начальной информации: %s"%(iData))

except NameError as err:

print 'NameError %s' %(err)

self.solveErr = 1

self.solveErrExtend = { 'vName' : err }

return

except:

print 'Unknown exception %s'%sys.exc_info()[0]

self.solveErr = 3

self.solveErrExtend = {}

for m in range(len(self.goals)):

self.log('Step %d:\n'%m)

for iRule in self.rules:

if iRule.strip() == '':

break

try:

self.log('Применяем правило %s' %iRule)

exec(iRule+';', self.__globals, self.__locals)

except NameError as err:

print 'NameError %s' %(err)

self.solveErr = 15

self.solveErrExtend = { 'vName' : err }

self.solveErrorsText()

return

except:

print 'Unknown exception'

self.solveErr = 18

self.solveErrExtend = {}

self.solveErrorsText()

return

l = self.preFind()

#l = [0]

if (l[0] not in (0, 2, 5, 13)):

if 12 == l[0]:

self.solveErrorsText()

if self._recursionLevel < 2:

self._recursionLevel = self._recursionLevel + 1

self.makeSolveFor()

pass

else:

self.solveErrorsText()

return

elif 2 == l[0]:

self.solveErrorsText()

elif 5 == l[0]:

try:

self.solveErrorsText()

exec(l[1]['ruleString'], self.__globals, self.__locals)

self.log(l[1]['varName'])

self.log("%s = %2.8lf" %(l[1]['varName'], eval(l[1]['varName'], self.__globals, self.__locals)))

return

except NameError as s:

print 'NameError in right solving %s' %s

self.solveErr = 21

self.solveErrExtend = l[1]

self.solveErrorsText()

return

for (key, val) in self.templateFull.iteritems():

if (key == self.goals[m]['goalParts'][0]):

print 'Found %s'%key

try:

if -1 != self.goals[m]['goalParts'][1]:

# заменяем шаблон

lf = val.lower()

for ctr in self.templateVars['vars'].lower().split(','):

lf = string.replace(lf, ctr, ctr+str(self.goals[m]['goalParts'][1]))

except IndexError as s:

print 'IndexError %s'%s

lf = val.lower()

pass

self.log('Применение шаблона %s = %s для переменной %s (%s = %s)' % (key, val, self.goals[m]['goalLine'], self.goals[m]['goalLine'], lf))

try:

exec("%s=%s"%(self.goals[m]['goalLine'], lf), self.__globals, self.__locals)

self.fString.append((self.goals[m]['goalLine'], lf))

self.log(self.goals[m]['goalLine'])

r = eval(self.goals[m]['goalLine'], self.__globals, self.__locals)

self.log("%s = %2.8lf" %(self.goals[m]['goalLine'], r))

self.data.append(r)

self.definiedVariables.append(self.goals[m]['goalLine'])

self.checkEnv(self.goals[m]['goalLine'], r)

continue

except NameError as err:

self.solveErr = 36

self.solveErrExtend = { 'line' : "%s=%s"%(self.goals[m]['goalLine'], lf), 'err' : err}

return

except:

self.solveErr = 37

self.solveErrExtend = { 'line' : "%s=%s"%(self.goals[m]['goalLine'], lf), 'err' : sys.exc_info()[0]}

return

# if (key == self.goals[m]['goalLine']):

def preFind(self):

print 'Analyzing'

print self.goals, self._recursionLevel

for sGoal in self.goals:

goalLine = sGoal['goalLine']

for sRule in self.ruledVariablesRight:

if goalLine in sRule:

self.solveErr = 2

self.solveErrExtend = {'vName' : goalLine}

return (2, {})

if goalLine in self.ruledVariablesLeft:

self.solveErr = 5

rS = self.retRuleStringByVal(goalLine)

self.solveErrExtend = { 'vName' : goalLine, 'ruleString' : rS }

return (5, {'ruleString' : rS, 'varName' : goalLine})

err = 0

for sRule in self.ruledVariablesRight:

for l in sRule:

if l in self.definiedVariables:

err = 1

if l in self.ruledVariablesLeft:

err = 2

if 1 == err:

return (0, {})

elif 2 == err:

self.solveErr = 13

return (0, {})

else:

q = self.analyzeGoalsNeeded()

print q

if q == '':

return (0, {})

else:

self.solveErr = 12

line = self.analyzeGoalsNeeded()

self.solveErrExtend = { 'vName' : line }

#self.goals = ('%s' %(line)).split('\'')[1]+"\n".join(self.rawgoals)

self.goals = []

self.goals.append(('%s' %(line)).split('\'')[1])

for i in self.rawgoals:

self.goals.append(i)

self.log('Поиск \'%s\''%('%s' %(line)).split('\'')[1])

print 'Поиск \'%s\''%('%s' %(line)).split('\'')[1]

self.analyzeGoals()

return (12, {})

def analyzeGoalsNeeded(self):

for goalLine in self.goals:

gL = goalLine['goalLine']

gP = goalLine['goalParts']

for (key, val) in self.templateFull.iteritems():

if key == gP[0]:

try:

if -1 != gP[1]:

# заменяем шаблон

lf = val.lower()

for ctr in self.templateVars['vars'].lower().split(','):

lf = string.replace(lf, ctr, ctr+str(self.goals[m]['goalParts'][1]))

except IndexError as s:

print 'IndexError %s'%s

lf = val.lower()

pass

try:

print lf

exec(lf, self.__globals, self.__locals)

except NameError as err:

return err

return ''

def simpleCheckEnv(self, varName, envVar, envParts, envElem):

try:

envParts[1]

except:

return

if envVar == varName:

l = eval(envElem, self.__globals, self.__locals)

if l:

print 'TRUE'

else:

self.log('Переменная %s не удовлетворяет параметрам внешней среды (%s)'%(varName, envElem))

print 'FALSE'

def checkEnv(self, varName, res):

print 'Checking %s by %lf'%(varName, res)

print self.env

for (envKey, envElem) in self.env.iteritems():

envParts = envElem.split('>=')

envVar = envParts[0].lower().strip()

self.simpleCheckEnv(varName, envVar, envParts, envElem)

envParts = envElem.split('<=')

envVar = envParts[0].lower().strip()

self.simpleCheckEnv(varName, envVar, envParts, envElem)

envParts = envElem.split('>')

envVar = envParts[0].lower().strip()

self.simpleCheckEnv(varName, envVar, envParts, envElem)

envParts = envElem.split('<')

envVar = envParts[0].lower().strip()

self.simpleCheckEnv(varName, envVar, envParts, envElem)

def retRuleStringByVal(self, val):

for i in self.rules:

if val == i.split('=')[0].strip():

return i

def retSolving(self, **kwargs):

ret = { 'err' : self.solveErr,

'errTxt' : self.sSolveTxt,

'sol' : self.solution,

'solStr' : self.sSolveTxt

}

return ret

def solveErrorsText(self):

self.log({

0 : lambda q: 'ОК',

1 : lambda q: "Переменная %s используется, но не задана" %(q['vName']),

2 : lambda q: "Переменная %s задана для поиска и в то же время используется в правиле. Возможна рекурсия"%(q),

3 : lambda q: 'Неизвестная ошибка при задании начальных условий',

5 : lambda q: "Переменная %s прямо вычисляется по правилу %s"%(q['vName'], q['ruleString']),

6 : lambda q: "Не задана переменная %s" %(q['vName']),

12 : lambda q: 'Какая-то из переменных правой части правил не может быть найдена в условиях и/или других правилах, ожидается %s'%(q['vName']),

13 : lambda q: 'Переменная правой части условий найдена в задании левой. Может вызвать ошибку',

14 : lambda q: 'Избыточные данные: переменная %s задана и требуется найти'%(q),

15 : lambda q: "Попытка использовать незаданную переменную %s в правилах" %(q['vName']),

18 : lambda q: 'Неизвестная ошибка при задании правил',

21 : lambda q: 'Ошибка прямого подсчёта, строка %s, переменная %s: '%(q['ruleString'], q['varName']),

24 : lambda q:

"Переменная %s не найдена среди возможных (%s)" %(q['vName'], q['dVars']),

31 : lambda q: 'Не заданы правило: строка должна быть формата A=(B) (дано: %s'%(''.join(q['vString'])),

36 : lambda q: 'Ошибка обработки строки %s: %s'%(q['line'], q['str'])

}[self.solveErr](self.solveErrExtend), True)

def log(self, txt, error=False, onlyError=False):

if error:

self.sErrTxt = self.sErrTxt + "\n" + txt

if not onlyError:

self.sSolveTxt = self.sSolveTxt + "\n" + txt

def graph(self, event):

print self.definiedVariables

print self.definiedVariablesFirst

graphWindow.graphWindow(self.parent, globals=self.__globals, locals=self.__locals,

defined=self.definiedVariablesFirst,

data=self.data,

fString=self.fString)