0

Two guns A and B need to be used to kill a monster(with N heads). When gun A is used it cuts 6 heads, but if the monster doesn't die(no of heads > 0), it will grow 3 heads. When gun B is used it cuts 4 heads but if the monster doesn't die it grows 2 heads. If N< (no. of heads the gun can cut), in that case the gun cannot be used. And if N=-1, both the monster and the hunter dies.

It is required by the problem to find out if it is possible to kill the monster, whether the hunter dies trying to kill the monster and the shortest path.

I've written the following Python program to solve the above problem:

def A(heads, path):
    if heads < -1:
        path = []
        return "Impossible to kill"    
    heads -= 6
    path.append("A")
    if heads == 0:
        print path
        path = []
        return "Monster dies"
    if heads == -1:
        return "Both monster and human die"
    heads += 3
    if A(heads, path)=="Monster dies" or B(heads, path) == "Monster dies":
        return "Monster dies"
def B(heads, path):
    if heads < -1:
        path = []
        return "Impossible to kill"
    #print "B", path, heads
    heads -= 4
    path.append("B")
    if heads == 0:
        print path
        path =[]
        return "Monster dies"
    if heads == -1:
        return "Both monster and human die"
    heads += 2
    if A(heads, path)=="Monster dies" or B(heads, path) == "Monster dies":
        return "Monster dies"

print A(10, [])  

Sample data(provided by question): For N=10, the shortest path is AAB.

Where in the program have I gone wrong and what is a better method to go through this problem?

bluish
  • 26,356
  • 27
  • 122
  • 180
  • 2
    Homework? Interview question? What problem are you experiencing with the solution you developed? – Tom Zych Sep 13 '11 at 14:51
  • Not homework or interview question :) Just something that caught my curiosity!! As for the problem I'm facing0 it's that the path displayed is not correct. –  Sep 13 '11 at 14:58
  • 1
    It's a good idea to show what incorrect output you're getting, so people can address the question without necessarily having to run the program themselves. – Tom Zych Sep 13 '11 at 15:08

2 Answers2

1

You are searching for a path that is not smallest. You need to save and check the length of the path like that:

def A(heads, path, path_len):
    if heads < -1:
        path = []
        return float('inf') #Impossible to kill
    heads -= 6
    if heads < 0:
        return float('inf')
    path_len = path_len + 1
    path.append("A")
    if heads == 0:
        print path
        return path_len
    heads += 3
    return min(A(heads, path, path_len), B(heads, path, path_len))

def B(heads, path, path_len):
    if heads < -1:
        path = []
        return float('inf') #Impossible to kill
    heads -= 4
    if heads < 0:
        return float('inf')
    path_len = path_len + 1
    path.append("B")
    if heads == 0:
        print path
        return path_len
    heads += 2
    return min(A(heads, path, path_len), B(heads, path, path_len))

A(10, [], 0)

this gives the right answer. You can have a global variable to store the path instead of simple printing it

pomel
  • 410
  • 2
  • 12
  • I didn't realise the original code actually worked! This is a better answer (although I would still structure it differently). – Adrian Mouat Sep 13 '11 at 15:18
0

You need to structure the program a bit better I think.

Perhaps create a function for A and B that takes the number of heads and returns the number of heads after applying the function (effect of gun + regeneration).

Keep the recursive calls in a separate control function; i.e. don't have A and B call themselves.

Use an enum (or whatever the python equivalent is) rather than strings for the end conditions.

It's not clear to me if the end conditions are handled correctly.

Update - as user695518's answer explains, you need to count the length of each path and return the minimum if you want an optimal solution.

Adrian Mouat
  • 44,585
  • 16
  • 110
  • 102