Учитывая заданную загадку ввода, q
,
- Если текущий индекс
i
выходит за границы или был замечен ранее в mem
(базовый случай), вернуть False
- В противном случае (индуктивный)
i
равен в границах и имеет не , замеченный ранее. Если i
равно последнему индексу, вернуть решение, sln
- В противном случае (индуктивное)
i
равно в границах, не быловидел, и не окончательный индекс. Добавьте i
к mem
и sln
и рекурсивно попытайтесь найти i+q[i]
или i-q[i]
Объяснение выше соответствует нумерованным комментариям ниже -
def solve(q, i = 0, mem = set(), sln = ()):
if i in mem or i < 0 or i >= len(q): #1
return False
elif i == len(q) - 1: #2
return sln+(i,)
else: #3
return \
solve(q, i+q[i], mem|set([i]), sln+(i,)) \
or \
solve(q, i-q[i], mem|set([i]), sln+(i,))
puzzle = [1,4,2,3,6,1,1,2]
print(solve(puzzle))
# (0, 1, 5, 6, 7)
Ответом является последовательность индексов для достижения окончательного индекса -
0 1 2 3 4 5 6 7 <-- index
[1,4,2,3,6,1,1,2] <-- puzzle
^ ^ ^ ^ ^ <-- (0, 1, 5, 6, 7)
Необходимо использовать mem
, чтобы избежать проверки одних и тех же индексов более одного раза. То есть, некоторые входные загадки могут привести к тому, что решатель попадет в бесконечный цикл. Если мы уже посещали индекс i
один раз ранее, мы знаем, что это тупик, и поэтому мы возвращаем False
solve([3,0,1,1,1,0,3])
# False
В этом примере мы видим, что решение отскакивает, а затем, наконец, приземляется напоследний индекс -
solve([3,6,1,2,4,0,3,1,0,9])
# (0, 3, 1, 7, 6, 9)