/hw2/scratch/hw2_part2_sol1.py
Python | 304 lines | 194 code | 47 blank | 63 comment | 88 complexity | 4a262a3bac50522101b311219fdb9d83 MD5 | raw file
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import sys
- # GLOBAL AGENT STATES
- item1 = 0 # int >= 0, 0: empty
- item2 = 0 # int >= 0, 0: empty
- hand = 0 # int >= 0, 0: empty
- def ReflexAgentWithState(\
- belta_current, belta_next, beltb_current, beltb_next, power):
- """Return two-belt conveyor action based on agent perception.
- Args:
- belta_current: int >= -1
- belta_next: int >= -1
- beltb_current: int >= -1
- beltb_next: int >= -1
- power: int >= 0
- Returns:
- str of ACTION
- """
- global item1
- global item2
- global hand
-
- items = [
- (1, item1),
- (2, item2),
- ]
- items.sort(key=lambda x: x[1])
- belts = [
- (('A', 0), belta_current),
- (('A', 1), belta_next),
- (('B', 0), beltb_current),
- (('B', 1), beltb_next),
- ]
- belts.sort(key=lambda x: x[1], reverse=True)
-
- # Place hand in empty slot: this is free
- # =====================
- if hand:
- if item1 == 0:
- item1 = hand
- hand = 0
- return "FILL_ITEM1"
- elif item2 == 0:
- item2 = hand
- hand = 0
- return "FILL_ITEM2"
- else:
- raise Exception, "No slot for hand item. Error State."
- # Handle terminal cases
- # =====================
- # no power; nothing in hand
- if power == 0:
- return "STOP"
- # end of belts
- if belta_current == beltb_current == -1:
- return "STOP"
-
- # Handle low power edge cases (empty hand)
- # ===========================
- if power == 1:
- # if a slot is available, get best current item
- if item1 == 0 or item2 == 0:
- if belta_current > beltb_current:
- hand = belta_current
- return "PICKUP_A"
- else:
- hand = beltb_current
- return "PICKUP_B"
- else:
- return "STOP"
-
- elif power == 2:
- # 2+1 power to move and get new item, consider best current items
- if item1 != 0 and item2 != 0:
- if max(belta_current, beltb_current) > min(item1, item2):
- if items[0][0] == 1:
- item1 = 0
- return "DROP_ITEM1"
- else:
- item2 = 0
- return "DROP_ITEM2"
- else:
- # not enough power to move, drop, pick
- return "STOP"
- # 2 power and both empty
- if item1 == 0 and item2 == 0:
- # if sum of current items is greater than best item in next row
- if belta_current + beltb_current > belts[0][1] and belts[0][0][1] == 1:
- if belta_current > beltb_current:
- hand = belta_current
- return "PICKUP_A"
- else:
- hand = beltb_current
- return "PICKUP_B"
- # 2 power and can only move one belt
- if (item1 == 0 or item2 == 0) and belts[0][0][1] == 1:
- return "ADVANCE_%s" % belts[0][0][0]
-
- elif power == 3:
- # pick up best current item if an opening exists
- if max(belta_current, beltb_current) > items[0][1]:
- if item1 == 0 or item2 == 0:
- if belta_current > beltb_current:
- hand = belta_current
- return "PICKUP_A"
- else:
- hand = beltb_current
- return "PICKUP_B"
-
- elif power == 4:
- # 4+1 power to get 2 items and move, consider both current items
- if min(belta_current, beltb_current) > max(item1, item2):
- # if no empty slot
- if item1 != 0 and item2 != 0:
- if items[0][0] == 1:
- item1 = 0
- return "DROP_ITEM1"
- if items[0][0] == 2:
- item2 = 0
- return "DROP_ITEM2"
-
- # Pick the second most desirable if:
- # ===========================
- # = second_want is current
- # = most_want is next in the same row
- # = second_want is also a better item
- # = the same item is not available in another row
- if belts[1][0][1] == 0 and belts[0][0][1] == 1 and \
- belts[0][0][0] == belts[1][0][0] and belts[1][1] > items[0][1] and \
- belts[1][1] > belts[2][1]:
- # make space if necessary
- if items[0][1] != 0:
- if items[0][0] == 1:
- item1 = 0
- return "DROP_ITEM1"
- elif items[0][0] == 2:
- item2 = 0
- return "DROP_ITEM2"
- else:
- # else pickup second most desirable
- hand = belts[1][1]
- return "PICKUP_%s" % belts[1][0][0]
- # Move a belt if:
- # ===========================
- # = current is empty
- # = next is not end
- if belta_current == 0 and belta_next != -1:
- return "ADVANCE_A"
- if beltb_current == 0 and beltb_next != -1:
- return "ADVANCE_B"
- # Best Item Handling
- # ===========================
- # best item is a better item if:
- # = best belt item > least held item
- if belts[0][1] > items[0][1]:
- # Two best items edge cases
- # -------------------------
- if belts[0][1] == belts[1][1]:
- print "!!!1"
- # if both on same row, advance that row
- if belts[0][0][0] == belts[1][0][0]:
- return "ADVANCE_%s" % belts[0][0][0]
- # if one is next, advance to make it current
- elif belts[0][0][1] != belts[1][0][1]:
- if belts[0][0][1] == 1:
- return "ADVANCE_%s" % belts[0][0][0]
- else:
- return "ADVANCE_%s" % belts[1][0][0]
- # if both are current, try to advance a belt
- elif belts[0][0][1] == belts[1][0][1] == 0:
- if belta_current != -1:
- return "ADVANCE_A"
- elif beltb_current != -1:
- return "ADVANCE_B"
- # try to get the best item if it is current and better
- # - drop the lowest item if no slot is available
- # - pick up
- if belts[0][0][1] == 0:
- # if no empty slot, drop lowest item
- if not (item1 == 0 or item2 == 0):
- if items[0][0] == 1:
- item1 = 0
- return "DROP_ITEM1"
- else:
- item2 = 0
- return "DROP_ITEM2"
- else:
- hand = belts[0][1]
- return "PICKUP_%s" % belts[0][0][0]
- # else best and better item is next; move that belt
- else:
- return "ADVANCE_%s" % belts[0][0][0]
-
- # best belt item is not at least as good as least held item
- # current visible state is optimal
- # try new state by moving belta, then beltb
- if belta_next > 0:
- return "ADVANCE_A"
- elif beltb_next > 0:
- return "ADVANCE_B"
- elif belta_next == 0:
- return "ADVANCE_A"
- elif beltb_next == 0:
- return "ADVANCE_B"
- # optimal configuration, and both belts are near end
- elif belta_next == beltb_next == -1:
- return "STOP"
- def main(args=None):
- if args is None:
- args = sys.argv
- try:
- with open(args[1]) as f:
- belt_a = map(int, f.readlines())
- with open(args[2]) as f:
- belt_b = map(int, f.readlines())
- except Exception, e:
- print "Usage: cmd filename_a filename_b"
- raise
- # fix belts so that both have at least two appending -1
- belt_a.extend([-1, -1])
- belt_b.extend([-1, -1])
- print "Belts are:"
- print "A: ", belt_a
- print "B: ", belt_b
- print
-
- # RUN AGENT
- a = 0
- b = 0
- run = True
- power = 20
- belt_a = [4, 21, -1, -1]
- belt_b = [4, 20, -1, -1]
-
- while (run):
- perceptions = (belt_a[a], belt_a[a+1], belt_b[b], belt_b[b+1], power)
- states = (item1, item2, hand)
- print "INPUT PERCEPTION: %d %d %d %d %d" % perceptions
- print "AGENT STATE: %d, %d, %d" % states
- action = ReflexAgentWithState(*perceptions)
- print "OUTPUT ACTION: %s" % action
- print
- if action == "ADVANCE_A":
- a += 1
- power -= 1
- elif action == "ADVANCE_B":
- b += 1
- power -= 1
- elif action == "PICKUP_A":
- belt_a[a] = 0
- power -= 1
- elif action == "PICKUP_B":
- belt_b[b] = 0
- power -= 1
- elif "DROP_ITEM" in action:
- power -= 1
- elif "FILL_ITEM" in action:
- pass
- elif action == "STOP":
- run = False
- print "======"
- print "FINAL STATE: %d, %d, %d" % states
- print "FINAL SUM: %s" % (item1 + item2)
-
- if __name__ == '__main__':
- main(sys.argv)