[ create a new paste ] login | about

Link: http://codepad.org/qUiOCHT3    [ raw code | output | fork ]

k4st - Python, pasted on Oct 3:
LEFT, RIGHT = 0, 1

def states():
    """Generate all possible states for the missionaries and cannibals 
    problem. This is an ugly way to do it :P"""
    r = range(0, 4)
    for a in r:
        for b in r:
            for c in r:
                for d in r:
                    if is_legal_state(a, b, c, d, LEFT):
                        yield a, b, c, d, LEFT
                    if is_legal_state(a, b, c, d, RIGHT):
                        yield a, b, c, d, RIGHT

def is_legal_state(m1, c1, m2, c2, side):
    """Check if a state appears to be legal."""
    if (c1 + c2) != 3 or (m1 + m2) != 3:
        return False
    elif m1 < 0 or m2 < 0 or c1 < 0 or c2 < 0:
        return False
    elif (m1 > 0 and m1 < c1) or (m2 > 0 and m2 < c2):
        return False
    elif (m1 + c1 == 6 and side == RIGHT) or (m2 + c2 == 6 and side == LEFT):
        return False
    return True

def gen_successor_states(m1, c1, m2, c2, side):
    """Generate all moves from a given state."""    
    if side is LEFT:
        yield m1-1, c1-1, m2+1, c2+1, RIGHT # 1 of both over
        yield m1-1, c1, m2+1, c2, RIGHT # 1 missionary over
        yield m1, c1-1, m2, c2+1, RIGHT # 1 cannibal over
        yield m1, c1-2, m2, c2+2, RIGHT # 2 cannibals over
        yield m1-2, c1, m2+2, c2, RIGHT # 2 missionaries over
    else:
        yield m1+1, c1+1, m2-1, c2-1, LEFT
        yield m1+1, c1, m2-1, c2, LEFT
        yield m1, c1+1, m2, c2-1, LEFT
        yield m1, c1+2, m2, c2-2, LEFT
        yield m1+2, c1, m2-2, c2, LEFT

def successors(state, legal_states):
    """Return all legal successor states."""
    states = set()
    for succ in gen_successor_states(*state):
        if is_legal_state(*succ):
            states.add(succ)
    return states

def state_label(state):
    """Create the label for each state."""
    
    return "(%3s%3s,%3s%3s,%s)" % (
        "M" * state[0], 
        "C" * state[1], 
        "M" * state[2], 
        "C" * state[3], 
        state[4] == LEFT and "<-" or "->"
    )

def print_state_space():
    "Generate the state space."
    
    reachable, legal_states = set(), set()
    prev_reached, next_reached = set(), set()
    initial, goal = (3, 3, 0, 0, LEFT), (0, 0, 3, 3, RIGHT)
    space = { }
    
    # generate the set of legal-looking states
    for state in states():
        legal_states.add(state)
    
    prev_reached.add(initial)
    prev_reached.add(goal)
    
    # generate all successors
    while len(prev_reached):
        next_reached.clear()
        for state in prev_reached:
            space[state] = successors(state, legal_states)
            reachable.add(state)
            
            # record newly reached
            next_reached.update(space[state])
        
        # update the various sets
        next_reached.difference_update(reachable)
        next_reached, prev_reached = prev_reached, next_reached
        reachable.update(prev_reached)
    
    # make it easier to print out the graph
    key = 1
    keys = { }
    for state in space:
        keys[state] = key
        key += 1
    
    # print out the DOT language version of the state space
    colors = {goal:" color=blue", initial:" color=green"}
    for state in space:
        print keys[state], "[label=\"%s\"%s]" \
            % (state_label(state), state in colors and colors[state] or "")
        
        for succ in space[state]:
            print keys[state], "->", keys[succ]
        print
        
print_state_space()


Output:
1 [label="(MMM  C,    CC,<-)"]
1 -> 2
1 -> 14

2 [label="(MMM   ,   CCC,->)"]
2 -> 1
2 -> 3

3 [label="(MMM CC,     C,<-)"]
3 -> 11
3 -> 2
3 -> 16

4 [label="(  M  C, MM CC,<-)"]
4 -> 9
4 -> 13

5 [label="(    CC,MMM  C,->)"]
5 -> 10
5 -> 6

6 [label="( MM CC,  M  C,<-)"]
6 -> 14
6 -> 5

7 [label="(MMMCCC,      ,<-)" color=green]
7 -> 11
7 -> 15
7 -> 16

8 [label="(    CC,MMM  C,<-)"]
8 -> 9
8 -> 13

9 [label="(     C,MMM CC,->)"]
9 -> 10
9 -> 4
9 -> 8

10 [label="(   CCC,MMM   ,<-)"]
10 -> 9
10 -> 5

11 [label="(MMM  C,    CC,->)"]
11 -> 3
11 -> 7

12 [label="(     C,MMM CC,<-)"]
12 -> 13

13 [label="(      ,MMMCCC,->)" color=blue]
13 -> 12
13 -> 4
13 -> 8

14 [label="(  M  C, MM CC,->)"]
14 -> 1
14 -> 6

15 [label="(MMM CC,     C,->)"]
15 -> 7

16 [label="( MM CC,  M  C,->)"]
16 -> 3
16 -> 7



Create a new paste based on this one


Comments: