Add files via upload

This commit is contained in:
Peter Norvig 2025-12-24 11:16:41 -08:00 committed by GitHub
parent 45562b6690
commit 67e6fe4291
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 2039 additions and 1267 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,14 +15,14 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 16, "execution_count": 2,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"from collections import Counter, defaultdict, namedtuple, deque, abc\n", "from collections import Counter, defaultdict, namedtuple, deque, abc\n",
"from dataclasses import dataclass, field\n", "from dataclasses import dataclass, field\n",
"from itertools import permutations, combinations, cycle, chain, islice, accumulate\n", "from itertools import permutations, combinations, cycle, chain, islice, accumulate\n",
"from itertools import count as count_from, product as cross_product\n", "from itertools import takewhile, count as count_from, product as cross_product\n",
"from typing import Iterable, Iterator, Sequence, Collection, Callable\n", "from typing import Iterable, Iterator, Sequence, Collection, Callable\n",
"from statistics import mean, median\n", "from statistics import mean, median\n",
"from math import ceil, floor, factorial, gcd, log, log2, log10, sqrt, inf, atan2\n", "from math import ceil, floor, factorial, gcd, log, log2, log10, sqrt, inf, atan2\n",
@ -67,7 +67,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 17, "execution_count": 3,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -82,6 +82,8 @@
" The first argument is either the text itself, or the day number of a text file.\"\"\"\n", " The first argument is either the text itself, or the day number of a text file.\"\"\"\n",
" if isinstance(day, str) and show == 8: \n", " if isinstance(day, str) and show == 8: \n",
" show = 0 # By default, don't show lines when parsing example text.\n", " show = 0 # By default, don't show lines when parsing example text.\n",
" if sections == None:\n",
" sections = lambda text: [text]\n",
" text = get_text(day)\n", " text = get_text(day)\n",
" show_items('Puzzle input', text.splitlines(), show)\n", " show_items('Puzzle input', text.splitlines(), show)\n",
" records = mapt(parser, sections(text.rstrip()))\n", " records = mapt(parser, sections(text.rstrip()))\n",
@ -133,7 +135,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 18, "execution_count": 4,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -181,7 +183,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 19, "execution_count": 5,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -209,12 +211,12 @@
" \"\"\"The repr of an answer shows what happened.\"\"\"\n", " \"\"\"The repr of an answer shows what happened.\"\"\"\n",
" correct = 'correct' if self.ok else 'WRONG!!'\n", " correct = 'correct' if self.ok else 'WRONG!!'\n",
" expected = '' if self.ok else f'; EXPECTED: {self.solution}'\n", " expected = '' if self.ok else f'; EXPECTED: {self.solution}'\n",
" return f'Puzzle {self.puzzle:4.1f}: {self.msecs:6.1f} msec, {correct} answer: {self.got:<15}{expected}'\n", " return f'Puzzle {self.puzzle:4.1f}: {self.msecs:7,.1f} msec, {correct} answer: {self.got:<15}{expected}'\n",
"\n", "\n",
"def summary(answers: dict):\n", "def summary(answers: dict):\n",
" \"\"\"Summary report on the answers.\"\"\"\n", " \"\"\"Summary report on the answers.\"\"\"\n",
" times = [answer.msecs for answer in answers.values()]\n", " times = [answer.msecs for answer in answers.values()]\n",
" def stat(fn, times): return f'{fn.__name__} = {fn(times):.1f}'\n", " def stat(fn, times): return f'{fn.__name__} = {fn(times):,.1f}'\n",
" stats = [stat(fn, times) for fn in (sum, mean, median, max)]\n", " stats = [stat(fn, times) for fn in (sum, mean, median, max)]\n",
" print(f'Time in milliseconds: {\", \".join(stats)}\\n')\n", " print(f'Time in milliseconds: {\", \".join(stats)}\\n')\n",
" for day in sorted(answers):\n", " for day in sorted(answers):\n",
@ -232,7 +234,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 33, "execution_count": 7,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
@ -241,7 +243,7 @@
"'+20 -30'" "'+20 -30'"
] ]
}, },
"execution_count": 33, "execution_count": 7,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
@ -319,6 +321,13 @@
" counter[item] += count\n", " counter[item] += count\n",
" return counter\n", " return counter\n",
"\n", "\n",
"def accumulate_lists(key_value_pairs: Iterable[tuple[object, object]]) -> defaultdict:\n",
" \"\"\"Add up all the (item, count) pairs into a Counter.\"\"\"\n",
" dic = defaultdict(list)\n",
" for (key, value) in key_value_pairs:\n",
" dic[key].append(value)\n",
" return dic\n",
"\n",
"def range_intersection(range1, range2) -> range:\n", "def range_intersection(range1, range2) -> range:\n",
" \"\"\"Return a range that is the intersection of these two ranges.\"\"\"\n", " \"\"\"Return a range that is the intersection of these two ranges.\"\"\"\n",
" return range(max(range1.start, range2.start), min(range1.stop, range2.stop))\n", " return range(max(range1.start, range2.start), min(range1.stop, range2.stop))\n",
@ -358,9 +367,9 @@
" \"\"\"`map`, with the result as a list.\"\"\"\n", " \"\"\"`map`, with the result as a list.\"\"\"\n",
" return list(map(function, *sequences))\n", " return list(map(function, *sequences))\n",
"\n", "\n",
"def cat(things: Collection) -> str:\n", "def cat(things: Collection, sep='') -> str:\n",
" \"\"\"Concatenate the things.\"\"\"\n", " \"\"\"Concatenate the things.\"\"\"\n",
" return ''.join(map(str, things))\n", " return sep.join(map(str, things))\n",
" \n", " \n",
"cache = functools.lru_cache(None)\n", "cache = functools.lru_cache(None)\n",
"Ø = frozenset() # empty set\n", "Ø = frozenset() # empty set\n",
@ -379,7 +388,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 21, "execution_count": 8,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -446,7 +455,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 22, "execution_count": 9,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -524,13 +533,24 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 12,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"data": {
"text/plain": [
"{}"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [ "source": [
"class Grid(dict):\n", "class Grid(dict):\n",
" \"\"\"A 2D grid, implemented as a mapping of {(x, y): cell_contents}.\"\"\"\n", " \"\"\"A 2D grid, implemented as a mapping of {(x, y): cell_contents}.\"\"\"\n",
" def __init__(self, grid=(), directions=directions4, skip=(), default=None):\n", " def __init__(self, grid=(), directions=directions4, skip=(), default=None, size=None):\n",
" \"\"\"Initialize one of four ways: \n", " \"\"\"Initialize one of four ways: \n",
" `Grid({(0, 0): '#', (1, 0): '.', ...})`\n", " `Grid({(0, 0): '#', (1, 0): '.', ...})`\n",
" `Grid(another_grid)\n", " `Grid(another_grid)\n",
@ -539,13 +559,15 @@
" self.directions = directions\n", " self.directions = directions\n",
" self.skip = skip\n", " self.skip = skip\n",
" self.default = default\n", " self.default = default\n",
" if isinstance(grid, abc.Mapping): \n", " if not grid:\n",
" pass\n",
" elif isinstance(grid, abc.Mapping): \n",
" self.update(grid) \n", " self.update(grid) \n",
" self.size = (len(cover(Xs(self))), len(cover(Ys(self))))\n", " self.size = size or (len(cover(Xs(self))), len(cover(Ys(self))))\n",
" else:\n", " else:\n",
" if isinstance(grid, str): \n", " if isinstance(grid, str): \n",
" grid = grid.splitlines()\n", " grid = grid.splitlines()\n",
" self.size = (max(map(len, grid)), len(grid))\n", " self.size = size or (max(map(len, grid)), len(grid))\n",
" self.update({(x, y): val \n", " self.update({(x, y): val \n",
" for y, row in enumerate(grid) \n", " for y, row in enumerate(grid) \n",
" for x, val in enumerate(row)\n", " for x, val in enumerate(row)\n",
@ -628,7 +650,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 24, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -656,7 +678,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 25, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -733,7 +755,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 26, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -762,7 +784,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 27, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -777,7 +799,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 28, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -792,7 +814,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 29, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -813,7 +835,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 30, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [