リスト : 左優先則 (test.py)
class A:
def method(self):
super().method()
print("A")
class B:
def method(self):
print("B")
class C(A, B):
def method(self):
super().method()
print("C")
print(C.mro())
c = C()
c.method()
C>python test.py [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>] B A C
A B C
│ │ │
│ │ │
D E F
\ │ /
\│/
G
G→D→A→E→B→F→C
図 : 深さ優先則
リスト : 深さ優先則 (test.py)
class A:
def method(self):
super().method()
print("A")
class B:
def method(self):
print("B")
class C(A):
def method(self):
super().method()
print("C")
class D(B):
def method(self):
super().method()
print("D")
class E(C, D):
def method(self):
super().method()
print("E")
print(E.mro())
e = E()
e.method()
C>python test.py [<class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.D'>, <class '__main__.B'>, <class 'object'>] B D A C E
A
/ \
/ \
B C D→B→C→A
\ /
\ /
D
図 : 合流則
リスト : 合流則 (test.py)
class A:
def method(self):
print("A")
class B(A):
def method(self):
super().method()
print("B")
class C(A):
def method(self):
super().method()
print("C")
class D(B, C):
def method(self):
super().method()
print("D")
print(D.mro())
d = D()
d.method()
C>python test.py [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] A C B D
A
/
B
Mixin A / \ Mixin B
\ / \ /
C D
図 : Mix-in
| 名前 | 機能 |
|---|---|
| obj.member(func) | func が真となる要素を返す |
| obj.position(func) | func が真となる要素の位置を返す |
| obj.count(func) | func が真となる要素の個数を返す |
| obj.map(func) | 要素に func を適用した結果を返すジェネレータを生成する |
| obj.filter(func) | func が真となる要素を返すジェネレータを生成する |
| obj.fold(func, init) | すべての要素を func を用いて結合した結果を返す |
リスト : Mix-in 用のクラス Enumerable
class Enumerable:
# 探索
def member(self, func):
for x in self.each():
if func(x): return x
return False
# 位置を返す
def position(self, func):
n = 0
for x in self.each():
if func(x): return n
n += 1
return -1
# 個数を数える
def count(self, func):
n = 0
for x in self.each():
if func(x): n += 1
return n
# マップ
def map(self, func):
for x in self.each(): yield(func(x))
# フィルター
def filter(self, func):
for x in self.each():
if func(x): yield(x)
# 畳み込み
def fold(self, func, init):
a = init
for x in self.each():
a = func(a, x)
return a
class LinkedList(Enumerable): ... class FixedList(LinkedList, Enumerable): ... class MyList(FixedList, Enumeraable) ...
>>> from linkedlist import * >>> from enumerable import * >>> class MyList(FixedList, Enumerable): ... def __init__(self, *args): ... super().__init__(*args) ... >>> a = MyList(8, 1, 2, 3, 4, 5, 6, 7, 8) >>> a FixedList(8, 1, 2, 3, 4, 5, 6, 7, 8) >>> a.member(lambda x: x % 2 == 0) 2 >>> a.position(lambda x: x % 2 == 0) 1 >>> a.count(lambda x: x % 2 == 0) 4 >>> list(a.map(lambda x: x * x)) [1, 4, 9, 16, 25, 36, 49, 64] >>> list(a.filter(lambda x: x % 2 == 0)) [2, 4, 6, 8] >>> a.fold(lambda x, y: x + y, 0) 36
リスト : 例外処理
try:
処理A
処理B
処理C
except except_type:
処理D
処理E
else:
処理F
>>> def foo(a, b):
... try:
... return a / b
... except ZeroDivisionError:
... print('Error {} / {}'.format(a, b))
... return 0
...
>>> foo(10, 2)
5.0
>>> foo(1, 0)
Error 1 / 0
0
>>> foo(1, '0')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in foo
TypeError: unsupported operand type(s) for /: 'int' and 'str'
raise exception
>>> raise Exception
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception
>>> raise Exception('Oops')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception: Oops
>>> try:
... raise Exception('oops', 123)
... except Exception as err:
... print(err.args)
... print(err)
...
('oops', 123)
('oops', 123)
>>> class FooError(Exception): pass
...
>>> raise FooError('oops!')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.FooError: oops!
リスト : finally 節
try:
処理A
処理B
処理C
except except_type:
処理D
処理E
else:
処理F
finally:
処理G
>>> try:
... print('oops')
... finally:
... print('clean up!!')
...
oops
clean up!!
>>> try:
... raise Exception('oops')
... finally:
... print("clean up!!")
...
clean up!!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
Exception: oops
with expr as var, expr1 as var1, ...:
処理
...
def __enter__(self): ... def __exit__(self, exc_type, exc_value, traceback): ...
リスト : with 文の簡単な使用例
class Foo:
def __init__(self, a):
self.a = a
print("init")
def __enter__(self):
print("enter")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("exit")
print(exc_type)
print(exc_value)
print(traceback)
return True
with Foo(123) as a:
print(a.a)
with Foo(0) as a:
raise Exception('oops!', a.a)
C> python3 test.py
init
enter
123
exit
None
None
None
init
enter
exit
<class 'Exception'>
('oops!', 0)
<traceback object at 0x0000023D79F61E88>
単純な二分木です。詳しい説明は拙作のページ「Algorithms with Python: 二分木とヒープ」をお読みくださいませ。
リスト : 二分木 (tree.py)
# 節
class Node:
def __init__(self, item, left = None, right = None):
self.item = item
self.left = left
self.right = right
#
# 操作関数
#
# 探索
def search(node, x):
while node is not None:
if node.item == x: return True
elif x < node.item: node = node.left
else: node = node.right
return False
def search_min(node):
while node.left is not None: node = node.left
return node.item
def search_max(node):
while node.right is not None: node = node.right
return node.item
# 挿入
def insert(node, x):
if node is None:
return Node(x)
elif x < node.item:
node.left = insert(node.left, x)
elif x > node.item:
node.right = insert(node.right, x)
return node
# 削除
def delete_min(node):
if node.left is None: return node.right
node.left = delete_min(node.left)
return node
def delete_max(node):
if node.right is None: return node.left
node.right = delete_max(node.right)
return node
def delete(node, x):
if node is None: return node
if node.item == x:
if node.left is None: return node.right
if node.right is None: return node.left
node.item = search_min(node.right)
node.right = delete_min(node.right)
elif x < node.item:
node.left = delete(node.left, x)
else:
node.right = delete(node.right, x)
return node
# 巡回
def each(node):
if node is not None:
yield from each(node.left)
yield node.item
yield from each(node.right)
# 二分木
class Tree:
def __init__(self):
self.root = None
# 挿入
def insert(self, x):
self.root = insert(self.root, x)
# 探索
def search(self, x):
return search(self.root, x)
def max(self):
if self.root is None: return None
return search_max(self.root)
def min(self):
if self.root is None: return None
return search_min(self.root)
# 削除
def delete(self, x):
self.root = delete(self.root, x)
def delete_max(self):
if self.root is not None: delete_max(self.root)
def delete_min(self):
if self.root is not None: delete_min(self.root)
# 巡回
def each(self): return each(self.root)
# 空か?
def is_empty(self): return self.root is None
# 表示
def __repr__(self):
if self.root is None: return 'Tree()'
s = 'Tree('
for x in each(self.root):
s += '{}, '.format(x)
s = s[:-2]
s += ')'
return s
# テスト
if __name__ == '__main__':
import random
tree = Tree()
data = [random.randint(0, 100) for x in range(10)]
print(data)
print(tree)
print(tree.is_empty())
for x in data: tree.insert(x)
print(tree)
print(tree.is_empty())
print('max =', tree.max())
print('min =', tree.min())
print("delete max")
tree.delete_max()
print(tree)
print("delete min")
tree.delete_min()
print(tree)
for x in data:
print('search', x, tree.search(x))
print('delete', x)
tree.delete(x)
print('search', x, tree.search(x))
print(tree)
[82, 37, 15, 7, 93, 75, 21, 71, 47, 25] Tree() True Tree(7, 15, 21, 25, 37, 47, 71, 75, 82, 93) False max = 93 min = 7 delete max Tree(7, 15, 21, 25, 37, 47, 71, 75, 82) delete min Tree(15, 21, 25, 37, 47, 71, 75, 82) search 82 True delete 82 search 82 False Tree(15, 21, 25, 37, 47, 71, 75) search 37 True delete 37 search 37 False Tree(15, 21, 25, 47, 71, 75) search 15 True delete 15 search 15 False Tree(21, 25, 47, 71, 75) search 7 False delete 7 search 7 False Tree(21, 25, 47, 71, 75) search 93 False delete 93 search 93 False Tree(21, 25, 47, 71, 75) search 75 True delete 75 search 75 False Tree(21, 25, 47, 71) search 21 True delete 21 search 21 False Tree(25, 47, 71) search 71 True delete 71 search 71 False Tree(25, 47) search 47 True delete 47 search 47 False Tree(25) search 25 True delete 25 search 25 False Tree()
スタートからゴールまでの経路を求めるプログラムです。詳しい説明は拙作のページ「Algorithms with Python: 集合、グラフ、経路の探索」をお読みくださいませ。
1───3───5
/│ │
0 │ │
\│ │
2───4───6
経路図
リスト : 経路の探索 (keiro.py)
# 隣接リスト
adjacent = ((1, 2), # 0
(0, 2, 3), # 1
(0, 1, 4), # 2
(1, 4, 5), # 3
(2, 3, 6), # 4
(3,), # 5
(1,)) # 6
# 深さ優先探索
def depth_first_search(goal, path):
p = path[-1]
if p == goal:
print(path)
else:
for x in adjacent[p]:
if x in path: continue
path.append(x)
depth_first_search(goal, path)
path.pop()
print("----- depth first search -----")
depth_first_search(6, [0])
# 幅優先探索
def breadth_first_search(start, goal):
que = [[start]]
while len(que) > 0:
path = que.pop(0)
p = path[-1]
if p == goal:
print(path)
else:
for x in adjacent[p]:
if x in path: continue
que.append(path + [x])
print("----- breadth first search -----")
breadth_first_search(0, 6)
# 反復深化
def iterative_deepening_search(start, goal):
def dfs(goal, path, limit):
if len(path) == limit:
if path[-1] == goal: print(path)
else:
for x in adjacent[path[-1]]:
if x in path: continue
path.append(x)
dfs(goal, path, limit)
path.pop()
for limit in range(1, 7):
print("-----", limit, "-----")
dfs(goal, [start], limit)
print("----- iterative deepening search -----")
iterative_deepening_search(0, 6)
----- depth first search ----- [0, 1, 2, 4, 6] [0, 1, 3, 4, 6] [0, 2, 1, 3, 4, 6] [0, 2, 4, 6] ----- breadth first search ----- [0, 2, 4, 6] [0, 1, 2, 4, 6] [0, 1, 3, 4, 6] [0, 2, 1, 3, 4, 6] ----- iterative deepening search ----- ----- 1 ----- ----- 2 ----- ----- 3 ----- ----- 4 ----- [0, 2, 4, 6] ----- 5 ----- [0, 1, 2, 4, 6] [0, 1, 3, 4, 6] ----- 6 ----- [0, 2, 1, 3, 4, 6]
簡単なパズルの解法プログラムです。パズルの説明は以下のページをお読みくださいませ。
●───●───● 0───1───2
│\ /│\ /│ │\ /│\ /│
│ ● │ ● │ │ 3 │ 4 │
│/ \│/ \│ │/ \│/ \│
●───○───● 5───6───7
│\ /│\ /│ │\ /│\ /│
│ ● │ ● │ │ 8 │ 9 │
│/ \│/ \│ │/ \│/ \│
●───●───● 10───11───12
(1) Hoppers (2) 座標
図 : ペグ・ソリティア (Hoppers)
#
# sample03.py : 簡単なプログラム (3)
#
# Copyright (C) 2018 Makoto Hiroi
#
#
# 小町算
#
def calc_expr(expr):
n = expr[0]
for i in range(1, len(expr), 2):
if expr[i] == '+':
n += expr[i + 1]
else:
n -= expr[i + 1]
return n
def print_expr(expr):
for x in expr:
print('{} '.format(x), end='')
print('= 100')
def komachi(n, expr):
if n == 10:
if calc_expr(expr) == 100: print_expr(expr)
else:
komachi(n + 1, expr + ['+', n])
komachi(n + 1, expr + ['-', n])
komachi(n + 1, expr[:-1] + [expr[-1] * 10 + n])
print("----- komachi -----")
komachi(2, [1])
#
# N Queens Problem
#
def nqueens(n):
def attack(q, qs):
d = 1
for i in range(len(qs), 0, -1):
if q + d == qs[i - 1] or q - d == qs[i - 1]: return True
d += 1
return False
def nqueens_sub(qs):
if len(qs) == n:
print(qs)
else:
for x in range(1, n + 1):
if x in qs or attack(x, qs): continue
qs.append(x)
nqueens_sub(qs)
qs.pop()
nqueens_sub([])
print("----- N Queens Problem -----")
for x in range(4, 9): nqueens(x)
#
# ナンバープレース
#
# 盤面の表示
def print_board(board):
for xs in board:
for n in xs: print(n, end = ' ')
print('')
# 条件のチェック
def check_number(x, y, n, board):
for i in range(0, 9):
if board[i][y] == n or board[x][i] == n: return False
x1 = (x // 3) * 3
y1 = (y // 3) * 3
for i in range(0, 3):
for j in range(0, 3):
if board[x1 + i][y1 + j] == n: return False
return True
# ナンバープレースの解法
def numplace(x, y, board):
if y >= 9:
print_board(board)
elif x >= 9:
numplace(0, y + 1, board)
elif board[x][y]:
numplace(x + 1, y, board)
else:
for n in range(1, 10):
if not check_number(x, y, n, board): continue
board[x][y] = n
numplace(x + 1, y, board)
board[x][y] = 0
# 問題 (出典: 数独 - Wikipedia の問題例)
sudoku_board = [
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]]
print('----- number place -----')
print_board(sudoku_board)
print('--------------------')
numplace(0, 0, sudoku_board)
#
# マスターマインド
#
import itertools
# bulls を数える
def count_bulls(xs, ys):
c = 0
for i in range(0, 4):
if xs[i] == ys[i]: c += 1
return c
# 同じ数の個数を数える
def count_same_numbers(xs, ys):
c = 0
for x in xs:
if x in ys: c += 1
return c
# 今までの質問と矛盾がないか
def check_query(code, qs):
for q in qs:
b = count_bulls(code, q[0])
c = count_same_numbers(code, q[0]) - b
if b != q[1] or c != q[2]: return False
return True
# マスターマインドの解法
def master_mind(answer):
query_table = []
for code in itertools.permutations(range(0, 10), 4):
if check_query(code, query_table):
b = count_bulls(code, answer)
c = count_same_numbers(code, answer) - b
query_table.append((code, b, c))
print('{}: {}, bulls = {}, cows = {}'.format(len(query_table), code, b, c))
if b == 4:
print('Good Job!!!')
break
print('----- master mind -----')
master_mind([9,8,7,6])
master_mind([9,4,3,1])
#
# 水差し問題
#
MAX_A = 8
MAX_B = 5
# A を空にする
def move1(a, b): return 0, b
# A を満たす
def move2(a, b): return MAX_A, b
# A -> B
def move3(a, b):
c = MAX_B - b
if c >= a:
return 0, a + b
else:
return a - c, b + c
# B を空にする
def move4(a, b): return a, 0
# B を満杯にする
def move5(a, b): return a, MAX_B
# B -> A
def move6(a, b):
c = MAX_A - a
if c >= b:
return a + b, 0
else:
return a + c, b - c
def water_jug(g):
que = [[(0, 0)]]
while len(que) > 0:
moves = que.pop(0)
a, b = moves[-1]
if a == g or b == g:
print(moves)
break
for move_func in [move1, move2, move3, move4, move5, move6]:
new_state = move_func(a, b)
if new_state in moves: continue
que.append(moves + [new_state])
print('----- water jug -----')
water_jug(4)
water_jug(1)
#
# 農夫と山羊と狼とキャベツの問題
#
def check_side(side):
if 'wolf' in side and 'goat' in side: return False
if 'goat' in side and 'cabbage' in side: return False
return True
def move_boat(src, dst):
src1 = src.difference({'farmer'})
if check_side(src1):
yield src1, dst.union({'farmer'})
for x in ['goat', 'wolf', 'cabbage']:
if x not in src: continue
xs = {'farmer', x}
src1 = src.difference(xs)
if check_side(src1):
yield src1, dst.union(xs)
def farmer():
all = {'farmer', 'goat', 'wolf', 'cabbage'}
que = [[(all, set())]]
while len(que) > 0:
move = que.pop(0)
left, right = move[-1]
if right == all:
for xs in move: print(xs)
break
if 'farmer' in left:
# left -> right
for state in move_boat(left, right):
if state not in move:
que.append(move + [state])
else:
# right -> right
for r, l in move_boat(right, left):
state = l, r
if state not in move:
que.append(move + [state])
print('----- farmer -----')
farmer()
#
# ペグ・ソリティア (Hoppers)
#
# 定数
SIZE = 13
HOLE = 6
MAX_JUMP = 11
# 跳び先表 (del, to)
jump_table = (
((1, 2), (3, 6), (5, 10)),
((3, 5), (6, 11), (4, 7)),
((1, 0), (4, 6), (7, 12)),
((6, 9),),
((6, 8),),
((3, 1), (6, 7), (8, 11)),
((3, 0), (4, 2), (8, 10), (9, 12)),
((4, 1), (6, 5), (9, 11)),
((6, 4),),
((6, 3),),
((5, 0), (8, 6), (11, 12)),
((8, 5), (6, 1), (9, 7)),
((11, 10), (9, 6), (7, 2))
)
def print_move(moves):
print('[{}, '.format(moves[0][0]), end='')
p = moves[0][1]
for a, b in moves[1:]:
if a == p:
print('{}, '.format(p), end='')
else:
print('{}][{}, '.format(p, a), end='')
p = b
print('{}]'.format(p))
def move_peg(board, from_, del_, to):
board[from_] = 0
board[del_] = 0
board[to] = 1
def restore_peg(board, from_, del_, to):
board[from_] = 1
board[del_] = 1
board[to] = 0
def hoppers():
cnt = 0
def ids(board, jc, limit, moves):
nonlocal cnt
if jc > limit: return
if len(moves) == MAX_JUMP:
if board[HOLE]:
print_move(moves)
cnt += 1
else:
for from_ in range(0, SIZE):
if not board[from_]: continue
for del_, to in jump_table[from_]:
if not board[del_] or board[to]: continue
if moves[-1][1] == from_:
new_jc = jc
else:
new_jc = jc + 1
moves.append((from_, to))
move_peg(board, from_, del_, to)
ids(board, new_jc, limit, moves)
moves.pop()
restore_peg(board, from_, del_, to)
# 初手を 0 -> 6 に限定
board = [1] * SIZE
board[0] = 0
board[3] = 0
for limit in range(2, MAX_JUMP + 1):
print("-----", limit, "-----")
ids(board, 1, limit, [(0, 6)])
if cnt > 0:
print(cnt)
break
print('----- Hoppers -----')
hoppers()
#
# 三目並べ
#
# 定数
MARU = 1
BATU = -1
FREE = 0
MARU_WIN = 1
BATU_WIN = -1
DRAW = 0
MAX_VALUE = 2
MIN_VALUE = -2
# 直線
line = (
(0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6),
(1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)
)
# 勝敗の判定
def check_winner(board):
for a, b, c in line:
piece = board[a]
if piece != FREE and piece == board[b] == board[c]:
if piece == MARU:
return MARU_WIN
else:
return BATU_WIN
return DRAW
# 先手の指し手
def think_maru(board, n):
value = MIN_VALUE
for i in range(len(board)):
if board[i] != FREE: continue
board[i] = MARU
v = check_winner(board)
if v == DRAW and n < len(board) - 1:
v = think_batu(board, n + 1)
if v > value: value = v
board[i] = FREE
return value
# 後手の指し手
def think_batu(board, n):
value = MAX_VALUE
for i in range(len(board)):
if board[i] != FREE: continue
board[i] = BATU
v = check_winner(board)
if v == DRAW and n < len(board) - 1:
v = think_maru(board, n + 1)
if v < value: value = v
board[i] = FREE
return value
def tictactoe():
board = [FREE] * 9
for i in range(9):
board[i] = MARU
v = think_batu(board, 1)
print(i, 'value = ', v)
board[i] = FREE
print('----- tic tac toe -----')
tictactoe()
----- komachi -----
1 + 2 + 3 - 4 + 5 + 6 + 78 + 9 = 100
1 + 2 + 34 - 5 + 67 - 8 + 9 = 100
1 + 23 - 4 + 5 + 6 + 78 - 9 = 100
1 + 23 - 4 + 56 + 7 + 8 + 9 = 100
12 + 3 + 4 + 5 - 6 - 7 + 89 = 100
12 + 3 - 4 + 5 + 67 + 8 + 9 = 100
12 - 3 - 4 + 5 - 6 + 7 + 89 = 100
123 + 4 - 5 + 67 - 89 = 100
123 + 45 - 67 + 8 - 9 = 100
123 - 4 - 5 - 6 - 7 + 8 - 9 = 100
123 - 45 - 67 + 89 = 100
----- N Queens Problem -----
[2, 4, 1, 3]
[3, 1, 4, 2]
[1, 3, 5, 2, 4]
[1, 4, 2, 5, 3]
[2, 4, 1, 3, 5]
[2, 5, 3, 1, 4]
[3, 1, 4, 2, 5]
[3, 5, 2, 4, 1]
[4, 1, 3, 5, 2]
[4, 2, 5, 3, 1]
[5, 2, 4, 1, 3]
[5, 3, 1, 4, 2]
[2, 4, 6, 1, 3, 5]
[3, 6, 2, 5, 1, 4]
[4, 1, 5, 2, 6, 3]
[5, 3, 1, 6, 4, 2]
[1, 3, 5, 7, 2, 4, 6]
[1, 4, 7, 3, 6, 2, 5]
[1, 5, 2, 6, 3, 7, 4]
・・・省略・・・
[7, 3, 6, 2, 5, 1, 4]
[7, 4, 1, 5, 2, 6, 3]
[7, 5, 3, 1, 6, 4, 2]
[1, 5, 8, 6, 3, 7, 2, 4]
[1, 6, 8, 3, 7, 4, 2, 5]
[1, 7, 4, 6, 8, 2, 5, 3]
・・・省略・・・
[8, 2, 5, 3, 1, 7, 4, 6]
[8, 3, 1, 6, 2, 5, 7, 4]
[8, 4, 1, 3, 6, 2, 7, 5]
----- number place -----
5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 0 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 0 0 2 8 0
0 0 0 4 1 9 0 0 5
0 0 0 0 8 0 0 7 9
--------------------
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9
----- master mind -----
1: (0, 1, 2, 3), bulls = 0, cows = 0
2: (4, 5, 6, 7), bulls = 0, cows = 2
3: (5, 4, 8, 9), bulls = 0, cows = 2
4: (6, 7, 9, 8), bulls = 0, cows = 4
5: (8, 9, 7, 6), bulls = 2, cows = 2
6: (9, 8, 7, 6), bulls = 4, cows = 0
Good Job!!!
1: (0, 1, 2, 3), bulls = 0, cows = 2
2: (1, 0, 4, 5), bulls = 0, cows = 2
3: (2, 3, 5, 4), bulls = 0, cows = 2
4: (3, 4, 0, 6), bulls = 1, cows = 1
5: (3, 5, 6, 1), bulls = 1, cows = 1
6: (6, 5, 0, 2), bulls = 0, cows = 0
7: (7, 4, 3, 1), bulls = 3, cows = 0
8: (8, 4, 3, 1), bulls = 3, cows = 0
9: (9, 4, 3, 1), bulls = 4, cows = 0
Good Job!!!
----- water jug -----
[(0, 0), (0, 5), (5, 0), (5, 5), (8, 2), (0, 2), (2, 0), (2, 5), (7, 0),
(7, 5), (8, 4)]
[(0, 0), (8, 0), (3, 5), (3, 0), (0, 3), (8, 3), (6, 5), (6, 0), (1, 5)]
----- farmer -----
({'wolf', 'farmer', 'goat', 'cabbage'}, set())
({'wolf', 'cabbage'}, {'farmer', 'goat'})
({'wolf', 'farmer', 'cabbage'}, {'goat'})
({'cabbage'}, {'wolf', 'farmer', 'goat'})
({'farmer', 'cabbage', 'goat'}, {'wolf'})
({'goat'}, {'wolf', 'farmer', 'cabbage'})
({'farmer', 'goat'}, {'wolf', 'cabbage'})
(set(), {'wolf', 'farmer', 'cabbage', 'goat'})
----- Hoppers -----
----- 2 -----
----- 3 -----
----- 4 -----
----- 5 -----
----- 6 -----
----- 7 -----
[0, 6][9, 3][2, 0, 6][11, 1][10, 0, 2, 6][8, 4][12, 2, 6]
[0, 6][9, 3][2, 0, 6][11, 1][10, 6][4, 8][12, 2, 0, 10, 6]
[0, 6][9, 3][2, 0, 6][11, 1][12, 2, 6][8, 4][10, 0, 2, 6]
[0, 6][9, 3][2, 6][8, 4][10, 0, 2, 6][7, 5][12, 10, 0, 6]
[0, 6][9, 3][2, 6][8, 4][10, 0, 2, 6][11, 1][12, 2, 0, 6]
[0, 6][9, 3][2, 6][8, 4][10, 0, 6][7, 5][12, 10, 0, 2, 6]
[0, 6][9, 3][2, 6][8, 4][12, 2, 0, 6][5, 7][10, 12, 2, 6]
[0, 6][9, 3][2, 6][8, 4][12, 2, 0, 6][11, 1][10, 0, 2, 6]
[0, 6][9, 3][2, 6][8, 4][12, 2, 6][5, 7][10, 12, 2, 0, 6]
[0, 6][9, 3][10, 0, 6][7, 5][2, 0, 10, 6][4, 8][12, 10, 6]
[0, 6][9, 3][10, 0, 6][7, 5][2, 6][8, 4][12, 10, 0, 2, 6]
[0, 6][9, 3][10, 0, 6][7, 5][12, 10, 6][4, 8][2, 0, 10, 6]
[0, 6][9, 3][10, 6][4, 8][2, 0, 6][11, 1][12, 2, 0, 10, 6]
[0, 6][9, 3][10, 6][4, 8][2, 0, 10, 6][7, 5][12, 10, 0, 6]
[0, 6][9, 3][10, 6][4, 8][2, 0, 10, 6][11, 1][12, 2, 0, 6]
[0, 6][9, 3][10, 6][4, 8][12, 10, 0, 6][1, 11][2, 12, 10, 6]
[0, 6][9, 3][10, 6][4, 8][12, 10, 0, 6][7, 5][2, 0, 10, 6]
[0, 6][9, 3][10, 6][4, 8][12, 10, 6][1, 11][2, 12, 10, 0, 6]
18
----- tic tac toe -----
0 value = 0
1 value = 0
2 value = 0
3 value = 0
4 value = 0
5 value = 0
6 value = 0
7 value = 0
8 value = 0