Here's my version in Python
def answer(X, probs):
# This dict holds the probabilities given as arguments
d = {"N": probs[0],
"S": probs[1],
"E": probs[2],
"W": probs[3]}
# A positive probability is the probability of a path that goes over
# a sing cell twice occurring.
# This generators yields all the possible ones
positive_probabilities = (prob(x, d) for x in gen_paths(X) if twicep(x))
s = 0
for i in positive_probabilities:
s += i
return s
def prob_value(path, pvalue):
s = 1
for i in path:
s *= pvalue[i]
return s
twicep_cache = {'': [(0, 0)]}
def is_twice(path):
last, rest = path[-1], path[:-1]
positions = twicep_cache[rest] # Retrieve previous data.
current = positions[-1]
if last == "N":
a = positions + [(current[0], current[1]+1)]
elif last == "S":
a = positions + [(current[0], current[1]-1)]
elif last == "E":
a = positions + [(current[0]+1, current[1])]
elif last == "W":
a = positions + [(current[0]-1, current[1])]
twicep_cache[path] = a
# test if each element is unique
return not len(a) == len(set(a))
def ptr_incr(ptr):
""" appends in turn "N", "S", "W", "E" to each element
that returns false for the is_twice() test.
"""
if ptr == "":
ptr = [""]
for i in ptr:
if i != "" and is_twice(i):
yield i
else:
yield i + "N"
yield i + "S"
yield i + "W"
yield i + "E"
I wrote an
explanation of the code here. (I really should look into some better presentation for my blog).
I ran the code inside
Python's C Profiler, like this:
import cProfile
import pstats
command = """reactor.run()"""
cProfile.runctx('print "value is %s" % prob_twice(10, [0.2, 0.2, 0.3, 0.3])',
globals(),
locals(),
filename="grid.profile")
# load profile from disk
stats = pstats.Stats("grid.profile")
stats.print_stats()
And here's the result I get:
value is 0.988116008291
Sat Nov 24 22:01:25 2012 grid.profile
11102675 function calls in 45.766 CPU seconds
Random listing order was used
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.339 0.339 10.096 10.096 /tmp/py10922tQ1:16(gen_tree)
2444068 41.276 0.000 41.725 0.000 /tmp/py10922tQ1:24(twicep)
2444081 0.777 0.000 9.757 0.000 /tmp/py10922tQ1:2(ptr_incr)
663193 0.868 0.000 35.457 0.000 /tmp/py10922tQ1:58()
1 0.212 0.212 45.766 45.766 /tmp/py10922tQ1:52(prob_twice)
4888136 0.450 0.000 0.450 0.000 {len}
663192 1.844 0.000 1.844 0.000 /tmp/py10922tQ1:42(prob_value)
1 0.000 0.000 45.766 45.766 :1()
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {range}
@Magtheridon96: I hadn't thought of a statistical approach like this. I suggest you run a higher number of tests if you want a better number. It's up to you to define what you mean by "better answer".
However I feel that a statistical approach like this can only approximate the results, which is not the goal of this exercise.