def process(g): for i in range(len(capacities)): nc = g(i) ns = T.makeLeaf(nc, state) if(isNewContents(ns)): T.addSubtree(state, ns) nss.append(ns)
def extendSolution(n): nss = [] for i in D: nc = i st = T.makeLeaf(nc, n) if(shouldBeAdded(st)): T.addSubtree(n, st) nss.append(st) return nss
def extendSolution(n): nss = [] for i in choices: ncs = process(i) for nc in ncs: st = T.makeLeaf(nc, n) if(shouldBeAdded(st)): T.addSubtree(n, st) nss.append(st) return nss
def search(ic, extendSolution, isSolution): initialState = T.makeLeaf(ic, None) # root state queue = [initialState] while(len(queue) is not 0): s = queue.pop(0) if(isSolution(s)): strace = T.getTrace(s) strace.pop(0) return [T.getContents(s) for s in strace] es = extendSolution(s) queue.extend(es) return None
def makeChange(Q, D): ## Helper functions - begin ###################### def getValue(n): p = T.parent(n) if(p == None): return T.getContents(n) else: return T.getContents(n) + getValue(p) def shouldBeAdded(n): return (not getValue(n) > Q) # Given a partial solution s, extend it by one step using each of the denominations available in D. def extendSolution(n): nss = [] for i in D: nc = i st = T.makeLeaf(nc, n) if(shouldBeAdded(st)): T.addSubtree(n, st) nss.append(st) return nss def isSolution(n): return getValue(n) == Q ## Helper functions - end ###################### ## Main algorithm - begin ###################### initialContents = 0 queue = [T.makeLeaf(initialContents, None)] while(len(queue) is not 0): s = queue.pop(0) if(isSolution(s)): strace = T.getTrace(s) strace.pop(0) return [T.getContents(s) for s in strace] es = extendSolution(s) queue.extend(es) return None
def fillJug(capacities, Q): def isSolution(s): def numOfNonEmptyJugs(c): def f(x): if(x == 0): return 0 return 1 ne = [f(i) for i in c] return reduce(lambda x, y: x + y, ne, 0) def totalQuantity(c): return reduce(lambda x, y: x + y, c, 0) c = T.getContents(s) return (numOfNonEmptyJugs(c) == 1) and (totalQuantity(c) == Q) ##### extendSolution - Begin ################## # Given an incomplete solution state, extend it by performing all the atomic operations: # -- Create a new solution by emptying each jug one by one. # -- Create a new solution by filling each jug to its capacity one by one. # -- Create a new solution by transferring the contents of each jug to every other. def extendSolution(state): contents = T.getContents(state) # empty the ith jug. def empty(i): newcontents = contents[:] newcontents[i] = 0 return newcontents # fill the ith jug to its capacity def fill(i): newcontents = contents[:] newcontents[i] = capacities[i] return newcontents # transfer the contents of jug i to jug j. Do it only if: # -- i is not empty # -- j is not full # Transfer only so much as j can hold (in case i holds more fluid than j can take) def transfer(i, j): def min(x, y): if(x < y): return x return y def isEmpty(i): return contents[i] == 0 def isFull(i): return contents[i] == capacities[i] newcontents = contents[:] if(not (isEmpty(i) or isFull(j))): q = min(contents[i], capacities[j] - contents[j]) newcontents[i] -= q newcontents[j] += q return newcontents def isNewContents(n): return not T.searchNode(n, T.getContents) nss = [] def process(g): for i in range(len(capacities)): nc = g(i) ns = T.makeLeaf(nc, state) if(isNewContents(ns)): T.addSubtree(state, ns) nss.append(ns) # Create new states by emptying jug i. process(empty) # Create new states by filling jug i. process(fill) # Create new states by transferring i's contents to each other j. for i in range(len(capacities)): process(lambda n: transfer(i, n)) return nss ##### extendSolution - End ################## initialContents = [0] * len(capacities) initialState = T.makeLeaf(initialContents, None) # root state queue = [initialState] while(len(queue) is not 0): s = queue.pop(0) if(isSolution(s)): strace = T.getTrace(s) strace.pop(0) return [T.getContents(s) for s in strace] es = extendSolution(s) queue.extend(es) return None