},
"outputs": [],
"source": [
- "def extend(chain):\n",
- " return [chain + [s] for s in neighbours[chain[-1]]\n",
+ "def extend(chain, closed=None):\n",
+ " if closed:\n",
+ " nbrs = set(neighbours[chain[-1]]) - closed\n",
+ " else:\n",
+ " nbrs = neighbours[chain[-1]]\n",
+ " return [chain + [s] for s in nbrs\n",
" if s not in chain]"
]
},
},
"outputs": [],
"source": [
- "def bfs_search(start, target, debug=False):\n",
- " return bfs([[start]], target, debug=debug)"
+ "def bfs_search(start, goal, debug=False):\n",
+ " agenda = [[start]]\n",
+ " finished = False\n",
+ " while not finished and agenda:\n",
+ " current = agenda[0]\n",
+ " if debug:\n",
+ " print(current)\n",
+ " if current[-1] == goal:\n",
+ " finished = True\n",
+ " else:\n",
+ " successors = extend(current)\n",
+ " agenda = agenda[1:] + successors\n",
+ " if agenda:\n",
+ " return current\n",
+ " else:\n",
+ " return None "
]
},
{
},
"outputs": [],
"source": [
- "def bfs(agenda, goal, debug=False):\n",
+ "def bfs_search_closed(start, goal, debug=False):\n",
+ " agenda = [[start]]\n",
+ " closed = set()\n",
" finished = False\n",
" while not finished and agenda:\n",
" current = agenda[0]\n",
" if current[-1] == goal:\n",
" finished = True\n",
" else:\n",
- " successors = extend(current)\n",
+ " closed.add(current[-1])\n",
+ " successors = extend(current, closed)\n",
" agenda = agenda[1:] + successors\n",
" if agenda:\n",
" return current\n",
},
"outputs": [],
"source": [
- "def dfs_search(start, target, debug=False):\n",
- " return dfs([[start]], target, debug=debug)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def dfs(agenda, goal, debug=False):\n",
+ "def dfs_search(start, goal, debug=False):\n",
+ " agenda = [[start]]\n",
" finished = False\n",
" while not finished and agenda:\n",
" current = agenda[0]\n",
},
{
"cell_type": "code",
- "execution_count": 20,
+ "execution_count": 19,
"metadata": {},
"outputs": [
{
"['abbe', 'able', 'ably', 'ally']"
]
},
- "execution_count": 20,
+ "execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": 20,
"metadata": {},
"outputs": [
{
"['cart', 'mart', 'tart', 'wart']\n",
"['cart', 'mart', 'tart', 'tort']\n",
"['cart', 'mart', 'tart', 'tact']\n",
- "['cart', 'mart', 'tart', 'taut']\n",
+ "['cart', 'mart', 'tart', 'taut']\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
"['cart', 'mart', 'tart', 'tare']\n",
"['cart', 'mart', 'tart', 'taro']\n",
"['cart', 'mart', 'tart', 'tarp']\n",
"['cart', 'mart', 'wart', 'waft']\n",
"['cart', 'mart', 'wart', 'wait']\n",
"['cart', 'mart', 'wart', 'want']\n",
- "['cart', 'mart', 'wart', 'watt']\n"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
+ "['cart', 'mart', 'wart', 'watt']\n",
"['cart', 'mart', 'wart', 'ward']\n",
"['cart', 'mart', 'wart', 'ware']\n",
"['cart', 'mart', 'wart', 'warm']\n",
"['cart', 'wart', 'ware', 'wire']\n",
"['cart', 'wart', 'ware', 'wore']\n",
"['cart', 'wart', 'ware', 'wade']\n",
- "['cart', 'wart', 'ware', 'wage']\n",
+ "['cart', 'wart', 'ware', 'wage']\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
"['cart', 'wart', 'ware', 'wake']\n",
"['cart', 'wart', 'ware', 'wale']\n",
"['cart', 'wart', 'ware', 'wane']\n",
"['cart', 'cant', 'cans', 'vans']"
]
},
- "execution_count": 21,
+ "execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": 21,
"metadata": {},
"outputs": [
{
"['cart', 'cant', 'cane', 'vane']"
]
},
- "execution_count": 22,
+ "execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": 22,
"metadata": {},
"outputs": [
{
" 'vane']"
]
},
- "execution_count": 23,
+ "execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": 23,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
- "def astar_search(start, target, debug=False):\n",
- " return astar([(distance(start, target), [start])], target, debug=debug)"
+ "def astar_search(start, goal, debug=False):\n",
+ " agenda = [(distance(start, goal), [start])]\n",
+ " heapq.heapify(agenda)\n",
+ " finished = False\n",
+ " while not finished and agenda:\n",
+ " _, current = heapq.heappop(agenda)\n",
+ " if debug:\n",
+ " print(current)\n",
+ " if current[-1] == goal:\n",
+ " finished = True\n",
+ " else:\n",
+ " successors = extend(current)\n",
+ " for s in successors:\n",
+ " heapq.heappush(agenda, (len(current) + distance(s[-1], goal) - 1, s))\n",
+ " if agenda:\n",
+ " return current\n",
+ " else:\n",
+ " return None "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "['cart']\n",
+ "['cart', 'cant']\n",
+ "['cart', 'cant', 'cane']\n",
+ "['cart', 'cant', 'cane', 'vane']\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "['cart', 'cant', 'cane', 'vane']"
+ ]
+ },
+ "execution_count": 24,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "astar_search('cart', 'vane', debug=True)"
]
},
{
},
"outputs": [],
"source": [
- "def astar(agenda, goal, debug=False):\n",
+ "def astar_search_closed(start, goal, debug=False):\n",
+ " agenda = [(distance(start, goal), [start])]\n",
+ " heapq.heapify(agenda)\n",
+ " closed = set()\n",
" finished = False\n",
" while not finished and agenda:\n",
" _, current = heapq.heappop(agenda)\n",
" if current[-1] == goal:\n",
" finished = True\n",
" else:\n",
- " successors = extend(current)\n",
+ " closed.add(current[-1])\n",
+ " successors = extend(current, closed)\n",
" for s in successors:\n",
" heapq.heappush(agenda, (len(current) + distance(s[-1], goal) - 1, s))\n",
" if agenda:\n",
}
],
"source": [
- "astar_search('cart', 'vane', debug=True)"
+ "astar_search_closed('cart', 'vane', debug=True)"
]
},
{
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": 77,
"metadata": {},
"outputs": [
{
"94"
]
},
- "execution_count": 27,
+ "execution_count": 77,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 28,
+ "execution_count": 78,
"metadata": {},
"outputs": [
{
"2204"
]
},
- "execution_count": 28,
+ "execution_count": 78,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 29,
+ "execution_count": 79,
"metadata": {},
"outputs": [
{
"1"
]
},
- "execution_count": 29,
+ "execution_count": 79,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": 80,
"metadata": {
"scrolled": true
},
"Counter({1: 75, 2: 6, 3: 7, 4: 2, 5: 2, 6: 1, 2204: 1})"
]
},
- "execution_count": 30,
+ "execution_count": 80,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": 81,
"metadata": {},
"outputs": [
{
"[5]"
]
},
- "execution_count": 31,
+ "execution_count": 81,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 32,
+ "execution_count": 82,
"metadata": {},
"outputs": [
{
"[{'abbe', 'able', 'ably', 'ally', 'axle'}]"
]
},
- "execution_count": 32,
+ "execution_count": 82,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 33,
+ "execution_count": 83,
"metadata": {},
"outputs": [
{
"['buns', 'bunk', 'punk']"
]
},
- "execution_count": 33,
+ "execution_count": 83,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 34,
- "metadata": {},
+ "execution_count": 84,
+ "metadata": {
+ "collapsed": true
+ },
"outputs": [],
"source": [
"for a in reachables:\n",
},
{
"cell_type": "code",
- "execution_count": 35,
- "metadata": {},
+ "execution_count": 85,
+ "metadata": {
+ "collapsed": true
+ },
"outputs": [],
"source": [
"# longest_chain = []\n",
},
{
"cell_type": "code",
- "execution_count": 36,
+ "execution_count": 86,
"metadata": {
"collapsed": true
},
},
{
"cell_type": "code",
- "execution_count": 37,
+ "execution_count": 87,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "['over', 'ever', 'eves', 'eyes', 'dyes', 'does', 'toes', 'tors', 'tars', 'taro', 'tyro']\n",
- "['aide', 'aids', 'bids', 'bits', 'bats', 'mats']\n",
- "['miff', 'riff', 'rife', 'rise', 'risk', 'rusk']\n",
- "['hims', 'hems', 'hens', 'lens', 'lent']\n",
- "['tipi', 'tips', 'tits', 'tots', 'cots', 'cote']\n",
- "['apex', 'aped', 'sped', 'sued', 'sues', 'subs', 'tubs', 'tabs', 'tabu']\n",
- "['wino', 'wind', 'wild', 'gild', 'gilt']\n",
- "['rasp', 'ramp', 'lamp', 'limp', 'limn']\n",
- "['paps', 'caps', 'cars', 'card', 'cord', 'lord', 'loud']\n",
- "['lava', 'lama', 'lamp', 'ramp']\n",
- "['ways', 'bays', 'boys', 'boos', 'coos', 'coop', 'coup']\n",
- "['boob', 'boor', 'boar', 'bear', 'beer', 'jeer', 'jeez']\n",
- "['troy', 'trod', 'prod', 'plod', 'pled', 'pied', 'died', 'diet']\n",
- "['vest', 'lest', 'less', 'loss', 'lows', 'rows']\n",
- "['shop', 'shot', 'soot', 'sort', 'sore', 'sire', 'dire', 'dike']\n",
- "['sing', 'zing']\n",
- "['beak', 'beat', 'belt', 'welt', 'wilt', 'wily', 'oily', 'only']\n",
- "['spry', 'spay', 'spas', 'seas', 'secs', 'sics', 'sirs', 'sire', 'tire', 'tiro']\n",
- "['gosh', 'bosh', 'boss', 'bogs', 'begs', 'bees', 'byes']\n",
- "['racy', 'race', 'rape', 'raps', 'saps', 'sops']\n"
+ "['late', 'lats', 'lets', 'leas', 'seas', 'seam', 'swam', 'sway']\n",
+ "['leap', 'heap', 'hear', 'dear', 'deer']\n",
+ "['peel', 'peek', 'perk', 'park', 'nark']\n",
+ "['sing', 'sang', 'sand', 'said', 'sail', 'hail', 'haul']\n",
+ "['vats', 'bats', 'bets', 'bees', 'been', 'teen', 'then', 'thin', 'this', 'thus', 'thud']\n",
+ "['sues', 'sees', 'seen', 'sewn', 'hewn']\n",
+ "['rash', 'bash', 'bast', 'bait', 'bail', 'hail', 'hair', 'heir']\n",
+ "['apex', 'aped', 'sped', 'seed', 'deed', 'dead', 'deal', 'veal']\n",
+ "['gulf', 'golf', 'gold', 'bold', 'bond', 'bony', 'tony']\n",
+ "['snag', 'shag', 'shat', 'seat', 'peat', 'pent', 'pint', 'mint']\n",
+ "['rife', 'rime', 'rims', 'rums', 'cums', 'cuss']\n",
+ "['diss', 'kiss', 'kits']\n",
+ "['gyps', 'gaps', 'gads', 'wads', 'wade', 'wide', 'tide']\n",
+ "['bilk', 'bill', 'bell', 'tell', 'teal', 'tear', 'tzar']\n",
+ "['logo', 'loge', 'lode', 'lade', 'jade', 'jape']\n",
+ "['hunt', 'bunt', 'buns', 'nuns', 'nubs']\n",
+ "['glow', 'glop', 'plop', 'prop', 'prep', 'peep', 'keep']\n",
+ "['iamb', 'lamb', 'lams', 'laps', 'lips', 'pips']\n",
+ "['pain', 'lain', 'laid', 'land', 'lend', 'vend', 'veld']\n",
+ "['fake', 'bake', 'bare', 'bars', 'ears', 'errs', 'ergs', 'eggs', 'egos']\n"
]
}
],
"source": [
"for _ in range(20):\n",
" start, goal = random.sample(bigset, 2)\n",
- " print(astar_search(start, goal))"
+ " print(astar_search_closed(start, goal))"
]
},
{
"astar_search('wars', 'love')"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 61,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 0 ns, sys: 0 ns, total: 0 ns\n",
+ "Wall time: 210 µs\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "5"
+ ]
+ },
+ "execution_count": 61,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(astar_search('wars', 'love'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 62,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 0 ns, sys: 0 ns, total: 0 ns\n",
+ "Wall time: 252 µs\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "5"
+ ]
+ },
+ "execution_count": 62,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(astar_search_closed('wars', 'love'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 63,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 24 ms, sys: 0 ns, total: 24 ms\n",
+ "Wall time: 24.2 ms\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "404"
+ ]
+ },
+ "execution_count": 63,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(dfs_search('wars', 'love'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 64,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 5min 20s, sys: 76 ms, total: 5min 20s\n",
+ "Wall time: 5min 20s\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "5"
+ ]
+ },
+ "execution_count": 64,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(bfs_search('wars', 'love'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 65,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 1.44 s, sys: 0 ns, total: 1.44 s\n",
+ "Wall time: 1.43 s\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "5"
+ ]
+ },
+ "execution_count": 65,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(bfs_search_closed('wars', 'love'))"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 42,
"[len(r) for r in reachables if 'star' in r if 'born' in r]"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 49,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "1 loop, best of 3: 7.9 s per loop\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%timeit\n",
+ "astar_search('bats', 'exit')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 50,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "10 loops, best of 3: 141 ms per loop\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%timeit\n",
+ "astar_search_closed('bats', 'exit')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['bats',\n",
+ " 'bans',\n",
+ " 'band',\n",
+ " 'sand',\n",
+ " 'said',\n",
+ " 'skid',\n",
+ " 'skit',\n",
+ " 'smit',\n",
+ " 'emit',\n",
+ " 'exit']"
+ ]
+ },
+ "execution_count": 51,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "astar_search_closed('bats', 'exit')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 88,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{2: [['heel', 'keel'], ['wane', 'wave'], ['cell', 'sell'], ['cons', 'cobs']],\n",
+ " 3: [['hank', 'haws'], ['bars', 'bets'], ['rats', 'paws'], ['lock', 'hack']],\n",
+ " 4: [['rule', 'sore'], ['wavy', 'rape'], ['peas', 'ping'], ['bond', 'toll']],\n",
+ " 5: [['cope', 'yowl'], ['lose', 'loci'], ['rump', 'dash'], ['four', 'dyes']],\n",
+ " 6: [['boon', 'sell'], ['lots', 'pomp'], ['cola', 'turn'], ['boos', 'laid']],\n",
+ " 7: [['eave', 'inns'], ['meek', 'mere'], ['keys', 'wily'], ['slam', 'yore']],\n",
+ " 8: [['hack', 'flip'], ['crag', 'huge'], ['flux', 'gill'], ['play', 'busy']],\n",
+ " 9: [['lacy', 'whey'], ['wren', 'rook'], ['lire', 'drip'], ['grab', 'lame']],\n",
+ " 10: [['over', 'turn'], ['worn', 'anew'], ['stow', 'elks'], ['ergo', 'rich']],\n",
+ " 11: [['bask', 'idea'], ['gabs', 'thud'], ['idea', 'clod'], ['mark', 'ibis']],\n",
+ " 12: [['umps', 'torn'], ['futz', 'shun'], ['abut', 'face'], ['slug', 'open']],\n",
+ " 13: [['umps', 'skin'], ['chum', 'rats'], ['fury', 'chum'], ['omen', 'zany']],\n",
+ " 14: [['chug', 'gaff'], ['atom', 'fizz']],\n",
+ " 15: [['chug', 'oxen']]}"
+ ]
+ },
+ "execution_count": 88,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "solutions = {}\n",
+ "for _ in range(10000):\n",
+ " start, goal = random.sample(bigset, 2)\n",
+ " solution = astar_search_closed(start, goal)\n",
+ " sl = len(solution)\n",
+ " if sl not in solutions:\n",
+ " solutions[sl] = []\n",
+ " if len(solutions[sl]) < 4:\n",
+ " solutions[sl].append([start, goal])\n",
+ " \n",
+ "# if len(solution) >= 10:\n",
+ "# solutions += [solution]\n",
+ " \n",
+ "solutions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 91,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "solutions = {2: [['heel', 'keel'], ['wane', 'wave'], ['cell', 'sell'], ['cons', 'cobs']],\n",
+ " 3: [['hank', 'haws'], ['bars', 'bets'], ['rats', 'paws'], ['lock', 'hack']],\n",
+ " 4: [['rule', 'sore'], ['wavy', 'rape'], ['peas', 'ping'], ['bond', 'toll']],\n",
+ " 5: [['cope', 'yowl'], ['lose', 'loci'], ['rump', 'dash'], ['four', 'dyes']],\n",
+ " 6: [['boon', 'sell'], ['lots', 'pomp'], ['cola', 'turn'], ['boos', 'laid']],\n",
+ " 7: [['eave', 'inns'], ['meek', 'mere'], ['keys', 'wily'], ['slam', 'yore']],\n",
+ " 8: [['hack', 'flip'], ['crag', 'huge'], ['flux', 'gill'], ['play', 'busy']],\n",
+ " 9: [['lacy', 'whey'], ['wren', 'rook'], ['lire', 'drip'], ['grab', 'lame']],\n",
+ " 10: [['over', 'turn'], ['worn', 'anew'], ['stow', 'elks'], ['ergo', 'rich']],\n",
+ " 11: [['bask', 'idea'], ['gabs', 'thud'], ['idea', 'clod'], ['mark', 'ibis']],\n",
+ " 12: [['umps', 'torn'], ['futz', 'shun'], ['abut', 'face'], ['slug', 'open']],\n",
+ " 13: [['umps', 'skin'], ['chum', 'rats'], ['fury', 'chum'], ['omen', 'zany']],\n",
+ " 14: [['chug', 'gaff'], ['atom', 'fizz'], ['chug', 'jinn'], ['amen', 'flog'],\n",
+ " ['buzz', 'grog'], ['imps', 'pros']],\n",
+ " 15: [['chug', 'oxen'], ['amen', 'doff']]}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 54,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[('amen', 'doff', 15), ('chug', 'jinn', 14), ('amen', 'flog', 14)]"
+ ]
+ },
+ "execution_count": 54,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "[(s[0], s[-1], len(s)) for s in solutions if len(s) >= 14]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 55,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "1 loop, best of 3: 360 ms per loop\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%timeit\n",
+ "astar_search_closed('blab', 'amen')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 56,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 384 ms, sys: 0 ns, total: 384 ms\n",
+ "Wall time: 385 ms\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "14"
+ ]
+ },
+ "execution_count": 56,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(astar_search_closed('blab', 'amen'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 57,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 124 ms, sys: 0 ns, total: 124 ms\n",
+ "Wall time: 121 ms\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "15"
+ ]
+ },
+ "execution_count": 57,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(astar_search_closed('amen', 'doff'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 58,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 32 ms, sys: 0 ns, total: 32 ms\n",
+ "Wall time: 32.4 ms\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "14"
+ ]
+ },
+ "execution_count": 58,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(astar_search_closed('chug', 'jinn'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 59,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 16 ms, sys: 0 ns, total: 16 ms\n",
+ "Wall time: 17.1 ms\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "14"
+ ]
+ },
+ "execution_count": 59,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(astar_search_closed('amen', 'flog'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 73,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 268 ms, sys: 4 ms, total: 272 ms\n",
+ "Wall time: 272 ms\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "14"
+ ]
+ },
+ "execution_count": 73,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(astar_search_closed('buzz', 'grog'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 74,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CPU times: user 64 ms, sys: 0 ns, total: 64 ms\n",
+ "Wall time: 64.1 ms\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "14"
+ ]
+ },
+ "execution_count": 74,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "%time len(astar_search_closed('imps', 'pros'))"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
},
"outputs": [],
"source": [
- "def extend(chain):\n",
- " return [chain + [s] for s in neighbours[chain[-1]]\n",
- " if s not in chain]"
+ "# def extend(chain):\n",
+ "# return [chain + [s] for s in neighbours[chain[-1]]\n",
+ "# if s not in chain]"
]
},
{
},
"outputs": [],
"source": [
- "def extend_raw(chain):\n",
- " nbrs = [w for w in adjacents(chain[-1]) if w in words]\n",
+ "def extend(chain, closed=None):\n",
+ " if closed:\n",
+ " nbrs = set(neighbours[chain[-1]]) - closed\n",
+ " else:\n",
+ " nbrs = neighbours[chain[-1]]\n",
" return [chain + [s] for s in nbrs\n",
" if s not in chain]"
]
},
"outputs": [],
"source": [
- "def bfs_search(start, target, debug=False):\n",
- " return bfs([[start]], target, debug=debug)"
+ "def extend_raw(chain):\n",
+ " nbrs = [w for w in adjacents(chain[-1]) if w in words]\n",
+ " return [chain + [s] for s in nbrs\n",
+ " if s not in chain]"
]
},
{
},
"outputs": [],
"source": [
- "def bfs(agenda, goal, debug=False):\n",
+ "def bfs_search(start, goal, debug=False):\n",
+ " agenda = [[start]]\n",
" finished = False\n",
" while not finished and agenda:\n",
" current = agenda[0]\n",
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 19,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
- "def dfs_search(start, target, debug=False):\n",
- " return dfs([[start]], target, debug=debug)"
+ "def bfs_search_closed(start, goal, debug=False):\n",
+ " agenda = [[start]]\n",
+ " closed = set()\n",
+ " finished = False\n",
+ " while not finished and agenda:\n",
+ " current = agenda[0]\n",
+ " if debug:\n",
+ " print(current)\n",
+ " if current[-1] == goal:\n",
+ " finished = True\n",
+ " else:\n",
+ " closed.add(current[-1])\n",
+ " successors = extend(current, closed)\n",
+ " agenda = agenda[1:] + successors\n",
+ " if agenda:\n",
+ " return current\n",
+ " else:\n",
+ " return None "
]
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 10,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
- "def dfs(agenda, goal, debug=False):\n",
+ "def dfs_search(start, goal, debug=False):\n",
+ " agenda = [[start]]\n",
" finished = False\n",
" while not finished and agenda:\n",
" current = agenda[0]\n",
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": 11,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
- "def astar_search(start, target, debug=False):\n",
- " agenda = [(distance(start, target), [start])]\n",
+ "def astar_search(start, goal, debug=False):\n",
+ " agenda = [(distance(start, goal), [start])]\n",
" heapq.heapify(agenda)\n",
- " return astar(agenda, target, debug=debug)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def astar(agenda, goal, debug=False):\n",
" finished = False\n",
" while not finished and agenda:\n",
" _, current = heapq.heappop(agenda)\n",
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": 12,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
- "def astar_search_raw(start, target, debug=False):\n",
- " agenda = [(distance(start, target), [start])]\n",
+ "# Uses direct lookup of successors, rather than using cached neighbours in the dict\n",
+ "def astar_search_raw(start, goal, debug=False):\n",
+ " agenda = [(distance(start, goal), [start])]\n",
" heapq.heapify(agenda)\n",
- " return astar_raw(agenda, target, debug=debug)"
+ " finished = False\n",
+ " while not finished and agenda:\n",
+ " _, current = heapq.heappop(agenda)\n",
+ " if debug:\n",
+ " print(current)\n",
+ " if current[-1] == goal:\n",
+ " finished = True\n",
+ " else:\n",
+ " successors = extend_raw(current) # Difference here\n",
+ " for s in successors:\n",
+ " heapq.heappush(agenda, (len(current) + distance(s[-1], goal) - 1, s))\n",
+ " if agenda:\n",
+ " return current\n",
+ " else:\n",
+ " return None "
]
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": 13,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
- "def astar_raw(agenda, goal, debug=False):\n",
+ "def astar_search_closed(start, goal, debug=False):\n",
+ " agenda = [(distance(start, goal), [start])]\n",
+ " heapq.heapify(agenda)\n",
+ " closed = set()\n",
" finished = False\n",
" while not finished and agenda:\n",
" _, current = heapq.heappop(agenda)\n",
" if current[-1] == goal:\n",
" finished = True\n",
" else:\n",
- " successors = extend_raw(current)\n",
+ " closed.add(current[-1])\n",
+ " successors = extend(current, closed)\n",
" for s in successors:\n",
" heapq.heappush(agenda, (len(current) + distance(s[-1], goal) - 1, s))\n",
" if agenda:\n",
" return current\n",
" else:\n",
- " return None "
+ " return None "
]
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": 14,
"metadata": {},
"outputs": [
{
"['vice', 'dice', 'dire', 'dare', 'ware', 'wars']"
]
},
- "execution_count": 16,
+ "execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": 15,
"metadata": {},
"outputs": [
{
"['vice', 'dice', 'dire', 'dare', 'ware', 'wars']"
]
},
- "execution_count": 17,
+ "execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": 16,
"metadata": {},
"outputs": [
{
"6"
]
},
- "execution_count": 18,
+ "execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 19,
+ "execution_count": 17,
"metadata": {},
"outputs": [
{
"6"
]
},
- "execution_count": 19,
+ "execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
{
"data": {
"text/plain": [
- "793"
+ "6"
]
},
"execution_count": 20,
}
],
"source": [
- "len(dfs_search('vice', 'wars'))"
+ "len(bfs_search_closed('vice', 'wars'))"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "793"
+ ]
+ },
+ "execution_count": 21,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "len(dfs_search('vice', 'wars'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "10000 loops, best of 3: 153 µs per loop\n"
+ "10000 loops, best of 3: 158 µs per loop\n"
]
}
],
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "100 loops, best of 3: 15.8 ms per loop\n"
+ "100 loops, best of 3: 15.6 ms per loop\n"
]
}
],
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "10000 loops, best of 3: 168 µs per loop\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%timeit\n",
+ "astar_search_closed('vice', 'wars')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "1 loop, best of 3: 1min 42s per loop\n"
+ "1 loop, best of 3: 1min 40s per loop\n"
]
}
],
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": 26,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "1 loop, best of 3: 597 ms per loop\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%timeit\n",
+ "bfs_search_closed('vice', 'wars')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "10 loops, best of 3: 88 ms per loop\n"
+ "10 loops, best of 3: 85.5 ms per loop\n"
]
}
],
},
{
"cell_type": "code",
- "execution_count": 25,
+ "execution_count": 28,
"metadata": {
"collapsed": true
},
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": 29,
"metadata": {
"scrolled": true
},
" '`bash`, `cash`, `dash`, `gash`, `hash`, `lash`, `mash`, `rasp`, `rush`, `sash`, `wash`')"
]
},
- "execution_count": 26,
+ "execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": 30,
"metadata": {
"scrolled": true
},
" '`base`, `bash`, `bask`, `bass`, `bast`, `bath`, `bosh`, `bush`, `case`, `cash`, `cask`, `cast`, `dash`, `dish`, `gash`, `gasp`, `gosh`, `gush`, `hash`, `hasp`, `hath`, `hush`, `lash`, `lass`, `last`, `lath`, `lush`, `mash`, `mask`, `mass`, `mast`, `math`, `mesh`, `mush`, `push`, `ramp`, `rasp`, `ruse`, `rush`, `rusk`, `rust`, `sash`, `sass`, `tush`, `wash`, `wasp`, `wish`')"
]
},
- "execution_count": 27,
+ "execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 28,
+ "execution_count": 31,
"metadata": {
"scrolled": true
},
"180"
]
},
- "execution_count": 28,
+ "execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 29,
+ "execution_count": 32,
"metadata": {
"scrolled": true
},
"2195"
]
},
- "execution_count": 29,
+ "execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": 33,
"metadata": {
"scrolled": true
},
"2192"
]
},
- "execution_count": 30,
+ "execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": 34,
"metadata": {
"scrolled": true
},
"name": "stdout",
"output_type": "stream",
"text": [
- "100 loops, best of 3: 5.96 ms per loop\n"
+ "100 loops, best of 3: 5.82 ms per loop\n"
]
}
],
},
{
"cell_type": "code",
- "execution_count": 32,
+ "execution_count": 35,
"metadata": {
"scrolled": true
},