#
# data : 2020.12.02
# author : sangmandu at Dankook Univ.
# program : river crossing
# language : python
#
#
# H : Human, W : Wolf, S : Sheep, C : Cabbage
# 1 ... W eat S when there are only W and S
# 2 ... S eat C when there are only S and C
# 3 ... boat can be accommodate in up to 2 elements and Human essential
# 4 ... objective is that all element moves left to right
#
#
# two lists that left and right
# prior : keep from generating duplicate
# dir : direction left to right or vice versa
# record : the procedure to success(or failure)
#
# failure 1) left check issue : collision with rule 1 or 2
# 2) left check issue : collision with rule 1 or 2
# 3) duplicate case : prevent that infinite loop
#
# initialization
_left = ['H', 'W', 'S', 'C']
_prior = ''
_right = []
_dir = '>'
_record = []
# check rule 1 and 2
# when breaking rule then True else False
def checkIssue(rand):
if len(rand) == 2 and 'S' in rand:
if 'W' in rand or 'C' in rand:
return True
return False
stack = [(_left, _prior, _right, _dir, _record)]
while stack:
left, prior, right, dir, record = stack.pop(0)
print()
print("selected element : ", left, prior, right, dir)
print("and remained stack : ", stack)
if not left:
_record.append(record)
continue
if dir == ">":
for ele in left:
if ele == 'H':
continue
print(f"ele is {ele}")
l, p, r, rec = left[:], prior[:], right[:], record[:]
if ele == prior:
print("ele == prior")
continue
l.remove(ele)
l.remove('H')
if checkIssue(l):
print("left check issue")
continue
r.append(ele)
r.append('H')
if checkIssue(r):
print("right check issue")
continue
memo = f"{ele} and human move from left : {left} to right : {right}"
if memo in rec:
print("duplicate issue")
continue
rec.append(memo)
stack.append((l, ele, r, '<', rec))
print(f"stack append {(l, ele, r, '<', rec)}")
else: # dir == "<"
for ele in right:
if ele == 'H':
continue
print(f"ele is {ele}")
l, p, r, rec = left[:], prior[:], right[:], record[:]
if ele == prior:
print("ele == prior")
continue
r.remove(ele)
r.remove('H')
if checkIssue(r):
print("right check issue")
continue
l.append(ele)
l.append('H')
if checkIssue(l):
print("left check issue")
continue
memo = f"{ele} and human move to left : {left} from right : {right} "
if memo in rec:
print("duplicate issue")
continue
rec.append(memo)
stack.append((l, ele, r, '>', rec))
print(f"stack append {(l, ele, r, '>', rec)}")
record.append(f"only human moves to left : {left} from right : {right} ")
right.remove('H')
left.append('H')
if checkIssue(right):
print("right check issue when human only on board")
continue
stack.append((left, '', right, '>', record))
print(f"stack append that only human {(l, '', r, '>', rec)}")
print()
for idx, record in enumerate(_record, 1):
print(f"#{idx} success case")
for rec in record:
print(rec)
print()