···11+import os # NOQA
22+import sys # NOQA
33+import heapq
44+import fileinput
55+from collections import Counter, defaultdict, deque, namedtuple # NOQA
66+77+from utils import memoize
88+from utils import Point, DIRS, DIRS_4, DIRS_8 # NOQA
99+1010+1111+MOD = 20183
1212+1313+1414+@memoize
1515+def geo_index(x, y):
1616+ if x == 0 and y == 0:
1717+ return 0
1818+ elif x == TX and y == TY:
1919+ return 0
2020+ elif y == 0:
2121+ return (x * 16807) % MOD
2222+ elif x == 0:
2323+ return (y * 48271) % MOD
2424+ else:
2525+ return (ero_level(x - 1, y) * ero_level(x, y - 1)) % MOD
2626+2727+2828+@memoize
2929+def ero_level(x, y):
3030+ return (geo_index(x, y) + DEPTH) % MOD
3131+3232+3333+@memoize
3434+def risk_level(x, y):
3535+ return ero_level(x, y) % 3
3636+3737+3838+lines = fileinput.input()
3939+DEPTH = int(lines[0].split()[1])
4040+TX, TY = (int(x) for x in lines[1].split()[1].split(','))
4141+4242+print "Total risk level for rectangle:", sum(risk_level(x, y) for x in range(TX + 1) for y in range(TY + 1))
4343+4444+4545+# In rocky regions (0), can use torch (1) or gear (2)
4646+# In wet regions (1), can use gear (2) or neither (0)
4747+# In narrow regions (2), can use neither (0) or torch (1)
4848+#
4949+# Start at (0, 0) with the torch equipped.
5050+ROCKY = 0
5151+WET = 1
5252+NARROW = 2
5353+5454+NEITHER = 0
5555+TORCH = 1
5656+GEAR = 2
5757+5858+items = [NEITHER, TORCH, GEAR]
5959+6060+allowed = {
6161+ ROCKY: [TORCH, GEAR],
6262+ WET: [GEAR, NEITHER],
6363+ NARROW: [NEITHER, TORCH],
6464+}
6565+6666+State = namedtuple('State', 'time x y item')
6767+6868+state = State(0, 0, 0, TORCH)
6969+horizon = [state]
7070+seen = {}
7171+7272+while horizon:
7373+ time, x, y, item = heapq.heappop(horizon)
7474+7575+ if x == TX and y == TY and item == TORCH:
7676+ print "Minutes to reach the target:", time
7777+ break
7878+7979+ # Hand-wavy upper bound on horizontal search limit (technically should be TX + TY)
8080+ if x > TX * 3:
8181+ continue
8282+8383+ if seen.get((x, y, item), 1e10) <= time:
8484+ continue
8585+8686+ next_entry = (time, x, y, item)
8787+8888+ seen[(x, y, item)] = min(seen.get((x, y, item), 1e10), time)
8989+ region = risk_level(x, y)
9090+9191+ for next_item in items:
9292+ if next_item in allowed[risk_level(x, y)] and next_item != item:
9393+ heapq.heappush(horizon, State(time + 7, x, y, next_item))
9494+9595+ for n in Point(x, y).neighbours_4():
9696+ if n.x >= 0 and n.y >= 0 and risk_level(n.x, n.y) != item:
9797+ heapq.heappush(horizon, State(time + 1, n.x, n.y, item))