Add files via upload
This commit is contained in:
@@ -2439,43 +2439,75 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"With 250,000 points in the full map, I think it will take several minutes (not hours, not seconds), to find the optimal path with the `search_grid` algorithm. I really wish I had used A* search; I think it would run in just a few seconds."
|
||||
"With 250,000 points in the full map, I estimated it would take several minutes to run the `search_grid` algorithm. I tested it, and it was 5 minutes. I wasn't satisfied with that, so I copied over the [A* search](https://en.wikipedia.org/wiki/A*_search_algorithm) from my [AoC 2017](https://github.com/norvig/pytudes/blob/main/ipynb/Advent%202017.ipynb) notebook, and supplied ity with the proper functions to make a move, compute the cost of a move, and estimate the distance to the goal (the `h_func` or \"heuristic function\"). A* is guaranteed to find an optimal path if the heuristic function never overestimates the cost from a state to the goal, so I use as an estimate the cost if every grid point along the way had a risk level of 1."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 65,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"CPU times: user 4min 21s, sys: 271 ms, total: 4min 22s\n",
|
||||
"Wall time: 4min 22s\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"True"
|
||||
]
|
||||
},
|
||||
"execution_count": 65,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%time answer(15.2, search_grid(repeat_grid(in15, 5)), 2957)"
|
||||
"from heapq import heappop, heappush\n",
|
||||
"\n",
|
||||
"def Astar(start, moves_func, h_func, cost_func) -> Tuple[int, list]:\n",
|
||||
" \"\"\"Find a (cost, path) tuple for the lowest-cost path from start to goal.\n",
|
||||
" A goal is any state where h_func(s) == 0.\"\"\"\n",
|
||||
" frontier = [(h_func(start), start)] # A priority queue, ordered by path_cost(s) + h(s)\n",
|
||||
" previous = {start: None} # start state has no previous state; other states will\n",
|
||||
" path_cost = {start: 0} # The cost of the best path to a state.\n",
|
||||
" Path = lambda s: ([] if (s is None) else Path(previous[s]) + [s])\n",
|
||||
" while frontier:\n",
|
||||
" (f, s) = heappop(frontier)\n",
|
||||
" if h_func(s) == 0:\n",
|
||||
" return path_cost[s], Path(s)\n",
|
||||
" for s2 in moves_func(s):\n",
|
||||
" g = path_cost[s] + cost_func(s, s2)\n",
|
||||
" if s2 not in path_cost or g < path_cost[s2]:\n",
|
||||
" heappush(frontier, (g + h_func(s2), s2))\n",
|
||||
" path_cost[s2] = g\n",
|
||||
" previous[s2] = s\n",
|
||||
" \n",
|
||||
"def Astar_search_grid(grid):\n",
|
||||
" \"\"\"The total cost of the best path from (0, 0) to bottom-right on grid.\"\"\"\n",
|
||||
" start, goal = (0, 0), max(grid)\n",
|
||||
" def moves_func(s): return grid.neighbors(s)\n",
|
||||
" def h_func(s): return sum(goal) - sum(s)\n",
|
||||
" def cost_func(s, s2): return grid[s2]\n",
|
||||
" return Astar(start, moves_func, h_func, cost_func)[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"With A* search the run time is greatly improved, from 5 minutes down to about 1 second."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 66,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"True"
|
||||
]
|
||||
},
|
||||
"execution_count": 66,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"answer(15.2, Astar_search_grid(repeat_grid(in15, 5)), 2957)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"OK, 5 minutes wasn't so bad. I may come back and improve on this later (or maybe not).\n",
|
||||
"\n",
|
||||
"Gary Grady's drawing represents the risk involved in finding a path that avoids bumping into the ceiling above or the chitons below.\n",
|
||||
"\n",
|
||||
"<img src=\"https://pbs.twimg.com/media/FGrU-PKXIAQ6sa8?format=jpg&name=medium\" width=400 title=\"@GaryJGrady\">"
|
||||
@@ -2492,7 +2524,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 66,
|
||||
"execution_count": 67,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@@ -2513,14 +2545,14 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"- **Part 1:** The puzzle is to parse this hexadecimal transmission into data packets, according to the rules contained in [the instructions](https://adventofcode.com/2021/day/16), and add up all of the version numbers.\n",
|
||||
"- **Part 1:** The puzzle is to parse this hexadecimal transmission into data packets, according to the rules contained in [the instructions](https://adventofcode.com/2021/day/16), and add up all of the version numbers of the packets.\n",
|
||||
"\n",
|
||||
"The gist of [the instructions](https://adventofcode.com/2021/day/16) is to consider the hexadecimal sequence as a bit string, parse the bit string into bit fields, and construct nested packets based on the values of the fields. Here are basic types for `Bits` (bit string) and `Packet`, along with functions to convert from a hexadecimal string to a bit string, and from there to an int: "
|
||||
"The gist of [the instructions](https://adventofcode.com/2021/day/16) is to consider the hexadecimal sequence as a bit string, divide the bit string into bit fields, and construct nested packets based on the values of the fields. Here are basic types for `Bits` (a bit string) and `Packet` (which contains a version umber `V`, a type ID `T`, and a `contents` field which can be either a number or a list of packets), along with functions to convert from a hexadecimal string to a bit string, and from there to an int: "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 67,
|
||||
"execution_count": 68,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -2529,6 +2561,7 @@
|
||||
"\n",
|
||||
"def bits_from_hex(hex) -> Bits: \n",
|
||||
" \"\"\"Convert a hexadecimal string into a bit string, making sure each hex digit is 4 bits.\"\"\"\n",
|
||||
" # I could have used just `bin(int(hex, 16))`, except that wouldn't left-zero-pad when needed.\n",
|
||||
" return cat(f'{int(x, 16):04b}' for x in hex)\n",
|
||||
"\n",
|
||||
"def int2(bits: Bits) -> int: \n",
|
||||
@@ -2536,6 +2569,26 @@
|
||||
" return int(bits, 2)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 69,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'0b11111111'"
|
||||
]
|
||||
},
|
||||
"execution_count": 69,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"bin(int('ff', 16))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
@@ -2545,7 +2598,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 68,
|
||||
"execution_count": 70,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -2595,7 +2648,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 69,
|
||||
"execution_count": 71,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@@ -2604,7 +2657,7 @@
|
||||
"True"
|
||||
]
|
||||
},
|
||||
"execution_count": 69,
|
||||
"execution_count": 71,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -2631,7 +2684,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 70,
|
||||
"execution_count": 72,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -2667,7 +2720,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 71,
|
||||
"execution_count": 73,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@@ -2676,7 +2729,7 @@
|
||||
"True"
|
||||
]
|
||||
},
|
||||
"execution_count": 71,
|
||||
"execution_count": 73,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user