-
Notifications
You must be signed in to change notification settings - Fork 2
/
missionariesandcannibals.py
155 lines (129 loc) · 5.42 KB
/
missionariesandcannibals.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import copy
# The problem starts with 3 Missionaries (M) and 3 Cannibals (C) in the left side of a river (leftCoast) trying to
# cross with a boat(B) going to the right side (rightCoast) with the restriction that never the number of Cannibals
# will outnumber the Missionaries on either side
class CoastState:
def __init__(self, c, m):
self.cannibals = c
self.missionaries = m
# This is an intermediate state of Coast where the missionaries have to outnumber the cannibals
def valid_coast(self):
if self.missionaries >= self.cannibals or self.missionaries == 0:
return True
else:
return False
def goal_coast(self):
if self.cannibals == 3 and self.missionaries == 3:
return True
else:
return False
class GameState:
def __init__(self, data):
self.data = data
self.parent = None
# Creating the Search Tree
def building_tree(self):
children = []
coast = ""
across_coast = ""
temp = copy.deepcopy(self.data)
if self.data["boat"] == "left":
coast = "left"
across_coast = "right"
elif self.data["boat"] == "right":
coast = "right"
across_coast = "left"
# MOVING 2 CANNIBALS (CC)
if temp[coast].cannibals >= 2:
temp[coast].cannibals = temp[coast].cannibals - 2
temp[across_coast].cannibals = temp[across_coast].cannibals + 2
temp["boat"] = across_coast
if temp[coast].valid_coast() and temp[across_coast].valid_coast():
child = GameState(temp)
child.parent = self
children.append(child)
temp = copy.deepcopy(self.data)
# MOVING 2 MISSIONARIES (MM)
if temp[coast].missionaries >= 2:
temp[coast].missionaries = temp[coast].missionaries - 2
temp[across_coast].missionaries = temp[across_coast].missionaries + 2
temp["boat"] = across_coast
if temp[coast].valid_coast() and temp[across_coast].valid_coast():
child = GameState(temp)
child.parent = self
children.append(child)
temp = copy.deepcopy(self.data)
# MOVING 1 CANNIBAL (C)
if temp[coast].cannibals >= 1:
temp[coast].cannibals = temp[coast].cannibals - 1
temp[across_coast].cannibals = temp[across_coast].cannibals + 1
temp["boat"] = across_coast
if temp[coast].valid_coast() and temp[across_coast].valid_coast():
child = GameState(temp)
child.parent = self
children.append(child)
temp = copy.deepcopy(self.data)
# MOVING 1 MISSIONARY (M)
if temp[coast].missionaries >= 1:
temp[coast].missionaries = temp[coast].missionaries - 1
temp[across_coast].missionaries = temp[across_coast].missionaries + 1
temp["boat"] = across_coast
if temp[coast].valid_coast() and temp[across_coast].valid_coast():
child = GameState(temp)
child.parent = self
children.append(child)
temp = copy.deepcopy(self.data)
# MOVING 1 CANNIBAL AND 1 MISSIONARY (CM && MM)
if temp[coast].missionaries >= 1 and temp[coast].cannibals >= 1:
temp[coast].missionaries = temp[coast].missionaries - 1
temp[across_coast].missionaries = temp[across_coast].missionaries + 1
temp[coast].cannibals = temp[coast].cannibals - 1
temp[across_coast].cannibals = temp[across_coast].cannibals + 1
temp["boat"] = across_coast
if temp[coast].valid_coast() and temp[across_coast].valid_coast():
child = GameState(temp)
child.parent = self
children.append(child)
return children
def breadth_first_search():
left = CoastState(3, 3)
right = CoastState(0, 0)
root_data = {"left": left, "right": right, "boat": "left"}
explored = []
nodes = []
path = []
nodes.append(GameState(root_data))
while len(nodes) > 0:
g = nodes.pop(0)
explored.append(g)
if g.data["right"].goal_coast():
path.append(g)
return g
else:
next_children = g.building_tree()
for x in next_children:
if (x not in nodes) or (x not in explored):
nodes.append(x)
return None
def print_path(g):
path = [g]
while g.parent:
g = g.parent
path.append(g)
print(" " + "Left Side" + " " + "Right Side" + " " + "Boat ")
print(
" Cannibals" + " Missionaries" + " " + "Cannibals" + " Missionaries" + " Boat Position")
counter = 0
for p in reversed(path):
print("State " + str(counter) + " Left C: " + str(p.data["left"].cannibals) + ". Left M: " + str(
p.data["left"].missionaries) + ". | Right C: " + str(
p.data["right"].cannibals) + ". Right M: " + str(p.data["right"].missionaries) + ". | Boat: " + str(
p.data["boat"]))
counter = counter + 1
print("End of Path!")
def main():
solution = breadth_first_search()
print("Missionaries and Cannibals AI Problem Solution using Breath - First Search:")
print_path(solution)
if __name__ == "__main__":
main()