···11+import copy
22+import fileinput
33+from collections import Counter, defaultdict
44+55+66+graph = defaultdict(set)
77+smalls = set()
88+99+for line in fileinput.input():
1010+ a, b = line.strip().split('-')
1111+1212+ graph[a].add(b)
1313+ graph[b].add(a)
1414+1515+1616+def dfs(start, extra_time=False):
1717+ num_paths = [0]
1818+ def _dfs(node, seen=None, doubled=False):
1919+ if seen is None:
2020+ seen = Counter({'start': 1 if extra_time else 0})
2121+2222+ if node == 'end':
2323+ num_paths[0] += 1
2424+ return
2525+2626+ # If small cave, check if part 1/2 and skip accordingly.
2727+ if node == node.lower():
2828+ if (doubled or not extra_time) and seen[node] >= 1:
2929+ return
3030+ elif not doubled and seen[node] >= 2:
3131+ return
3232+3333+ seen[node] += 1
3434+ if node == node.lower() and node not in ('start', 'end') and seen[node] >= 2:
3535+ doubled = True
3636+3737+ for n in graph[node]:
3838+ _dfs(n, copy.deepcopy(seen), doubled=doubled)
3939+4040+ _dfs(start)
4141+ return num_paths[0]
4242+4343+4444+print "Part 1:", dfs('start')
4545+print "Part 2:", dfs('start', extra_time=True)