Add files via upload
This commit is contained in:
parent
76c97b7f00
commit
280cf9a8e4
4410
ipynb/Advent-2023.ipynb
Normal file
4410
ipynb/Advent-2023.ipynb
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,16 +4,18 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div style=\"text-align: right\" align=\"right\"><i>Peter Norvig<br>Decembers 2016–2021</i></div>\n",
|
||||
"<div style=\"text-align: right\" align=\"right\"><i>Peter Norvig<br>Decembers 2016–2023</i></div>\n",
|
||||
"\n",
|
||||
"# Advent of Code Utilities\n",
|
||||
"\n",
|
||||
"Stuff I might need for [Advent of Code](https://adventofcode.com). First, some imports that I have used in past AoC years:"
|
||||
"Stuff I might need for [Advent of Code](https://adventofcode.com). \n",
|
||||
"\n",
|
||||
"First, some imports that I have used in past AoC years:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -26,7 +28,6 @@
|
||||
"from math import ceil, floor, factorial, gcd, log, log2, log10, sqrt, inf\n",
|
||||
"\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"import ast\n",
|
||||
"import fractions\n",
|
||||
"import functools\n",
|
||||
@ -35,6 +36,7 @@
|
||||
"import pathlib\n",
|
||||
"import re\n",
|
||||
"import string\n",
|
||||
"import sys\n",
|
||||
"import time"
|
||||
]
|
||||
},
|
||||
@ -65,19 +67,21 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"current_year = 2022 # Subdirectory name for input files\n",
|
||||
"current_year = 2023 # Subdirectory name for input files\n",
|
||||
"\n",
|
||||
"lines = str.splitlines # By default, split input text into lines\n",
|
||||
"\n",
|
||||
"def paragraphs(text): \"Split text into paragraphs\"; return text.split('\\n\\n')\n",
|
||||
"\n",
|
||||
"def parse(day_or_text:Union[int, str], parser:Callable=str, sections:Callable=lines, show=8) -> tuple:\n",
|
||||
"def parse(day_or_text:Union[int, str], parser=str, sections=lines, show=8) -> tuple:\n",
|
||||
" \"\"\"Split the input text into `sections`, and apply `parser` to each.\n",
|
||||
" The first argument is either the text itself, or the day number of a text file.\"\"\"\n",
|
||||
" if isinstance(day_or_text, str) and show == 8: \n",
|
||||
" show = 0 # By default, don't show lines when parsing exampole text.\n",
|
||||
" show = 0 # By default, don't show lines when parsing example text.\n",
|
||||
" start = time.time()\n",
|
||||
" text = get_text(day_or_text)\n",
|
||||
" show_items('Puzzle input', text.splitlines(), show)\n",
|
||||
@ -116,7 +120,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -152,58 +156,6 @@
|
||||
" return text.strip()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Helper functions:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def truncate(object, width=100, ellipsis=' ...') -> str:\n",
|
||||
" \"\"\"Use elipsis to truncate `str(object)` to `width` characters, if necessary.\"\"\"\n",
|
||||
" string = str(object)\n",
|
||||
" return string if len(string) <= width else string[:width-len(ellipsis)] + ellipsis\n",
|
||||
"\n",
|
||||
"def mapt(function: Callable, *sequences) -> tuple:\n",
|
||||
" \"\"\"`map`, with the result as a tuple.\"\"\"\n",
|
||||
" return tuple(map(function, *sequences))\n",
|
||||
"\n",
|
||||
"def mapl(function: Callable, *sequences) -> list:\n",
|
||||
" \"\"\"`map`, with the result as a list.\"\"\"\n",
|
||||
" return list(map(function, *sequences))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Some tests for the functions above:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"assert parse(\"hello\\nworld\", show=0) == ('hello', 'world')\n",
|
||||
"assert parse(\"123\\nabc7\", digits, show=0) == ((1, 2, 3), (7,))\n",
|
||||
"assert truncate('hello world', 99) == 'hello world'\n",
|
||||
"assert truncate('hello world', 8) == 'hell ...'\n",
|
||||
"\n",
|
||||
"assert atoms('hello, cruel_world! 24-7') == ('hello', 'cruel_world', 24, -7)\n",
|
||||
"assert words('hello, cruel_world! 24-7') == ('hello', 'cruel', 'world')\n",
|
||||
"assert digits('hello, cruel_world! 24-7') == (2, 4, 7)\n",
|
||||
"assert ints('hello, cruel_world! 24-7') == (24, -7)\n",
|
||||
"assert positive_ints('hello, cruel_world! 24-7') == (24, 7)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
@ -215,32 +167,34 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 91,
|
||||
"execution_count": 105,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
" .0000 seconds, answer: 3 INCORRECT!!!! Expected 2"
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" 0.1: .0000 seconds, answer unknown \n",
|
||||
" 0.2: .0000 seconds, answer 549755813888 ok\n",
|
||||
" 0.3: .0000 seconds, answer 549755813889 WRONG; expected answer is 549755813888\n",
|
||||
"10.4: .0000 seconds, answer 4 WRONG; expected answer is unknown\n"
|
||||
]
|
||||
},
|
||||
"execution_count": 91,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"answers = {} # `answers` is a dict of {puzzle_number: answer}\n",
|
||||
"\n",
|
||||
"unknown = 'unknown'\n",
|
||||
"\n",
|
||||
"class answer:\n",
|
||||
" \"\"\"Verify that calling `code` computes the `solution` to `puzzle`. \n",
|
||||
" Record results in the dict `answers`.\"\"\"\n",
|
||||
" def __init__(self, puzzle, solution, code:callable):\n",
|
||||
" self.solution, self.code = solution, code\n",
|
||||
" def __init__(self, puzzle: float, solution, code:callable=lambda:unknown):\n",
|
||||
" self.puzzle, self.solution, self.code = puzzle, solution, code\n",
|
||||
" answers[puzzle] = self\n",
|
||||
" self.check()\n",
|
||||
" \n",
|
||||
" def check(self):\n",
|
||||
" def check(self) -> bool:\n",
|
||||
" \"\"\"Check if the code computes the correct solution; record run time.\"\"\"\n",
|
||||
" start = time.time()\n",
|
||||
" self.got = self.code()\n",
|
||||
@ -248,12 +202,19 @@
|
||||
" self.ok = (self.got == self.solution)\n",
|
||||
" return self.ok\n",
|
||||
" \n",
|
||||
" def __repr__(self):\n",
|
||||
" def __repr__(self) -> str:\n",
|
||||
" \"\"\"The repr of an answer shows what happened.\"\"\"\n",
|
||||
" def commas(x) -> str: return f'{x:,d}' if is_int(x) else f'{x}'\n",
|
||||
" secs = f'{self.secs:7.4f} seconds'.replace(' 0.', ' .')\n",
|
||||
" ok = '' if self.ok else f' !!!! INCORRECT !!!! Expected {commas(self.solution)}'\n",
|
||||
" return f'{secs}, answer: {commas(self.got)}{ok}'"
|
||||
" secs = f'{self.secs:7.4f}'.replace(' 0.', ' .')\n",
|
||||
" comment = (f'' if self.got == unknown else\n",
|
||||
" f' ok' if self.ok else \n",
|
||||
" f' WRONG; expected answer is {self.solution}')\n",
|
||||
" return f'Puzzle {self.puzzle:4.1f}: {secs} seconds, answer {self.got:<15}{comment}'\n",
|
||||
"\n",
|
||||
"def test_answer():\n",
|
||||
" print(answer(0.1, unknown))\n",
|
||||
" print(answer(0.2, 2**39, lambda: 2**39))\n",
|
||||
" print(answer(0.3, 2**39, lambda: 2**39+1))\n",
|
||||
" print(answer(10.4, unknown, lambda: 2 + 2))"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -267,7 +228,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -334,6 +295,10 @@
|
||||
" first, *rest = sets\n",
|
||||
" return set(first).intersection(*rest)\n",
|
||||
"\n",
|
||||
"def range_intersection(range1, range2) -> range:\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",
|
||||
" \n",
|
||||
"def naked_plot(points, marker='o', size=(10, 10), invert=True, square=False, **kwds):\n",
|
||||
" \"\"\"Plot `points` without any axis lines or tick marks.\n",
|
||||
" Optionally specify size, whether square or not, and whether to invery y axis.\"\"\"\n",
|
||||
@ -353,45 +318,32 @@
|
||||
" return {dic[x]: x for x in dic}\n",
|
||||
"\n",
|
||||
"def walrus(name, value):\n",
|
||||
" \"\"\"If you're not in 3.8, and you can't do `x := val`,\n",
|
||||
" then you can use `walrus('x', val)`.\"\"\"\n",
|
||||
" \"\"\"If you're not in 3.8 or more, and you can't do `x := val`,\n",
|
||||
" then you can use `walrus('x', val)`, if `x` is global.\"\"\"\n",
|
||||
" globals()[name] = value\n",
|
||||
" return value\n",
|
||||
"\n",
|
||||
"cat = ''.join\n",
|
||||
"def truncate(object, width=100, ellipsis=' ...') -> str:\n",
|
||||
" \"\"\"Use elipsis to truncate `str(object)` to `width` characters, if necessary.\"\"\"\n",
|
||||
" string = str(object)\n",
|
||||
" return string if len(string) <= width else string[:width-len(ellipsis)] + ellipsis\n",
|
||||
"\n",
|
||||
"def mapt(function: Callable, *sequences) -> tuple:\n",
|
||||
" \"\"\"`map`, with the result as a tuple.\"\"\"\n",
|
||||
" return tuple(map(function, *sequences))\n",
|
||||
"\n",
|
||||
"def mapl(function: Callable, *sequences) -> list:\n",
|
||||
" \"\"\"`map`, with the result as a list.\"\"\"\n",
|
||||
" return list(map(function, *sequences))\n",
|
||||
"\n",
|
||||
"def cat(things: Collection) -> str:\n",
|
||||
" \"\"\"Concatenate the things.\"\"\"\n",
|
||||
" return ''.join(map(str, things))\n",
|
||||
" \n",
|
||||
"cache = functools.lru_cache(None)\n",
|
||||
"Ø = frozenset() # empty set"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"More tests:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"assert multimap(((i % 3), i) for i in range(9)) == {0: [0, 3, 6], 1: [1, 4, 7], 2: [2, 5, 8]}\n",
|
||||
"assert prod([2, 3, 5]) == 30\n",
|
||||
"assert total(Counter('hello, world')) == 12\n",
|
||||
"assert cover(3, 1, 4, 1, 5) == range(1, 6)\n",
|
||||
"assert minmax([3, 1, 4, 1, 5, 9]) == (1, 9)\n",
|
||||
"assert T([(1, 2, 3), (4, 5, 6)]) == [(1, 4), (2, 5), (3, 6)]\n",
|
||||
"assert the({1}) == 1\n",
|
||||
"assert split_at('hello, world', 6) == ('hello,', ' world')\n",
|
||||
"assert is_int(-42) and not is_int('one')\n",
|
||||
"assert sign(-42) == -1 and sign(0) == 0 and sign(42) == +1\n",
|
||||
"assert union([{1, 2}, {3, 4}, {5, 6}]) == {1, 2, 3, 4, 5, 6}\n",
|
||||
"assert intersection([{1, 2, 3}, {2, 3, 4}, {2, 4, 6, 8}]) == {2}\n",
|
||||
"assert clock_mod(24, 12) == 12 and 24 % 12 == 0\n",
|
||||
"assert cat(['hello', 'world']) == 'helloworld'"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
@ -403,7 +355,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -459,32 +411,6 @@
|
||||
" return next((x for x in iterable if x), default)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"More tests:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"assert quantify(words('This is a test'), str.islower) == 3\n",
|
||||
"assert dotproduct([1, 2, 3, 4], [1000, 100, 10, 1]) == 1234\n",
|
||||
"assert list(flatten([{1, 2, 3}, (4, 5, 6), [7, 8, 9]])) == [1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
|
||||
"assert append(([1, 2], [3, 4], [5, 6])) == [1, 2, 3, 4, 5, 6]\n",
|
||||
"assert list(batched(range(11), 3)) == [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10)]\n",
|
||||
"assert list(sliding_window('abcdefghi', 3)) == ['abc', 'bcd', 'cde', 'def', 'efg', 'fgh', 'ghi']\n",
|
||||
"assert first('abc') == 'a'\n",
|
||||
"assert first('') == None\n",
|
||||
"assert last('abc') == 'c'\n",
|
||||
"assert first_true([0, None, False, 42, 99]) == 42\n",
|
||||
"assert first_true([0, None, '', 0.0]) == False"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
@ -496,7 +422,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 92,
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -571,22 +497,28 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 68,
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Grid(dict):\n",
|
||||
" \"\"\"A 2D grid, implemented as a mapping of {(x, y): cell_contents}.\"\"\"\n",
|
||||
" def __init__(self, grid=(), directions=directions4, skip=(), default=KeyError):\n",
|
||||
" \"\"\"Initialize with either (e.g.) `Grid({(0, 0): '#', (1, 0): '.', ...})`, or\n",
|
||||
" `Grid([\"#..\", \"..#\"]) or `Grid(\"#..\\n..#\")`.\"\"\"\n",
|
||||
" def __init__(self, grid=(), directions=directions4, skip=(), default=None):\n",
|
||||
" \"\"\"Initialize one of four ways: \n",
|
||||
" `Grid({(0, 0): '#', (1, 0): '.', ...})`\n",
|
||||
" `Grid(another_grid)\n",
|
||||
" `Grid([\"#..\", \"..#\"])\n",
|
||||
" `Grid(\"#..\\n..#\")`.\"\"\"\n",
|
||||
" self.directions = directions\n",
|
||||
" self.skip = skip\n",
|
||||
" self.default = default\n",
|
||||
" if isinstance(grid, abc.Mapping): \n",
|
||||
" self.update(grid) \n",
|
||||
" self.size = (len(cover(Xs(self))), len(cover(Ys(self))))\n",
|
||||
" else:\n",
|
||||
" if isinstance(grid, str): \n",
|
||||
" grid = grid.splitlines()\n",
|
||||
" self.size = (max(map(len, grid)), len(grid))\n",
|
||||
" self.update({(x, y): val \n",
|
||||
" for y, row in enumerate(grid) \n",
|
||||
" for x, val in enumerate(row)\n",
|
||||
@ -599,23 +531,33 @@
|
||||
" else:\n",
|
||||
" return self.default\n",
|
||||
"\n",
|
||||
" def copy(self): return Grid(self, directions=self.directions, default=self.default)\n",
|
||||
" def in_range(self, point) -> bool:\n",
|
||||
" \"\"\"Is the point within the range of the grid's size?\"\"\"\n",
|
||||
" return (0 <= X_(point) < X_(self.size) and\n",
|
||||
" 0 <= Y_(point) < Y_(self.size))\n",
|
||||
"\n",
|
||||
" def copy(self): \n",
|
||||
" return Grid(self, directions=self.directions, skip=self.skip, default=self.default)\n",
|
||||
" \n",
|
||||
" def neighbors(self, point) -> List[Point]:\n",
|
||||
" \"\"\"Points on the grid that neighbor `point`.\"\"\"\n",
|
||||
" return [add2(point, Δ) for Δ in self.directions \n",
|
||||
" if add2(point, Δ) in self or self.default != KeyError]\n",
|
||||
" if add2(point, Δ) in self or self.default not in (KeyError, None)]\n",
|
||||
" \n",
|
||||
" def neighbor_contents(self, point) -> Iterable:\n",
|
||||
" \"\"\"The contents of the neighboring points.\"\"\"\n",
|
||||
" return (self[p] for p in self.neighbors(point))\n",
|
||||
"\n",
|
||||
" def findall(self, contents: Collection) -> List[Point]:\n",
|
||||
" \"\"\"All points that contain one of the given contents, e.g. grid.findall('#').\"\"\"\n",
|
||||
" return [p for p in self if self[p] in contents]\n",
|
||||
" \n",
|
||||
" def to_rows(self, xrange=None, yrange=None) -> List[List[object]]:\n",
|
||||
" \"\"\"The contents of the grid, as a rectangular list of lists.\n",
|
||||
" You can define a window with an xrange and yrange; or they default to the whole grid.\"\"\"\n",
|
||||
" xrange = xrange or cover(Xs(self))\n",
|
||||
" yrange = yrange or cover(Ys(self))\n",
|
||||
" default = ' ' if self.default is KeyError else self.default\n",
|
||||
" default = ' ' if self.default in (KeyError, None) else self.default\n",
|
||||
" return [[self.get((x, y), default) for x in xrange] \n",
|
||||
" for y in yrange]\n",
|
||||
"\n",
|
||||
@ -637,28 +579,6 @@
|
||||
" return [add(point, Δ) for Δ in directions]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Here are some tests:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"p, q = (0, 3), (4, 0)\n",
|
||||
"assert Y_(p) == 3 and X_(q) == 4\n",
|
||||
"assert distance(p, q) == 5\n",
|
||||
"assert taxi_distance(p, q) == 7\n",
|
||||
"assert add(p, q) == (4, 3)\n",
|
||||
"assert sub(p, q) == (-4, 3)\n",
|
||||
"assert add(North, South) == (0, 0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
@ -676,7 +596,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -704,7 +624,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -781,7 +701,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -810,7 +730,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -825,7 +745,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 42,
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -839,7 +759,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -850,6 +770,79 @@
|
||||
" def __setattr__(self, attr, value):\n",
|
||||
" self[attr] = value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Tests"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def tests():\n",
|
||||
" \"\"\"Run tests on utility functions. Also serves as usage examples.\"\"\"\n",
|
||||
" \n",
|
||||
" # PARSER\n",
|
||||
"\n",
|
||||
" assert parse(\"hello\\nworld\", show=0) == ('hello', 'world')\n",
|
||||
" assert parse(\"123\\nabc7\", digits, show=0) == ((1, 2, 3), (7,))\n",
|
||||
" assert truncate('hello world', 99) == 'hello world'\n",
|
||||
" assert truncate('hello world', 8) == 'hell ...'\n",
|
||||
"\n",
|
||||
" assert atoms('hello, cruel_world! 24-7') == ('hello', 'cruel_world', 24, -7)\n",
|
||||
" assert words('hello, cruel_world! 24-7') == ('hello', 'cruel', 'world')\n",
|
||||
" assert digits('hello, cruel_world! 24-7') == (2, 4, 7)\n",
|
||||
" assert ints('hello, cruel_world! 24-7') == (24, -7)\n",
|
||||
" assert positive_ints('hello, cruel_world! 24-7') == (24, 7)\n",
|
||||
"\n",
|
||||
" # UTILITIES\n",
|
||||
"\n",
|
||||
" assert multimap(((i % 3), i) for i in range(9)) == {0: [0, 3, 6], 1: [1, 4, 7], 2: [2, 5, 8]}\n",
|
||||
" assert prod([2, 3, 5]) == 30\n",
|
||||
" assert total(Counter('hello, world')) == 12\n",
|
||||
" assert cover(3, 1, 4, 1, 5) == range(1, 6)\n",
|
||||
" assert minmax([3, 1, 4, 1, 5, 9]) == (1, 9)\n",
|
||||
" assert T([(1, 2, 3), (4, 5, 6)]) == [(1, 4), (2, 5), (3, 6)]\n",
|
||||
" assert the({1}) == 1\n",
|
||||
" assert split_at('hello, world', 6) == ('hello,', ' world')\n",
|
||||
" assert is_int(-42) and not is_int('one')\n",
|
||||
" assert sign(-42) == -1 and sign(0) == 0 and sign(42) == +1\n",
|
||||
" assert union([{1, 2}, {3, 4}, {5, 6}]) == {1, 2, 3, 4, 5, 6}\n",
|
||||
" assert intersection([{1, 2, 3}, {2, 3, 4}, {2, 4, 6, 8}]) == {2}\n",
|
||||
" assert clock_mod(24, 12) == 12 and 24 % 12 == 0\n",
|
||||
" assert cat(['hello', 'world']) == 'helloworld'\n",
|
||||
"\n",
|
||||
" # ITERTOOL RECIPES\n",
|
||||
"\n",
|
||||
" assert quantify(words('This is a test'), str.islower) == 3\n",
|
||||
" assert dotproduct([1, 2, 3, 4], [1000, 100, 10, 1]) == 1234\n",
|
||||
" assert list(flatten([{1, 2, 3}, (4, 5, 6), [7, 8, 9]])) == [1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
|
||||
" assert append(([1, 2], [3, 4], [5, 6])) == [1, 2, 3, 4, 5, 6]\n",
|
||||
" assert list(batched(range(11), 3)) == [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10)]\n",
|
||||
" assert list(sliding_window('abcdefghi', 3)) == ['abc', 'bcd', 'cde', 'def', 'efg', 'fgh', 'ghi']\n",
|
||||
" assert first('abc') == 'a'\n",
|
||||
" assert first('') == None\n",
|
||||
" assert last('abc') == 'c'\n",
|
||||
" assert first_true([0, None, False, 42, 99]) == 42\n",
|
||||
" assert first_true([0, None, '', 0.0]) == False\n",
|
||||
"\n",
|
||||
" # POINTS\n",
|
||||
"\n",
|
||||
" p, q = (0, 3), (4, 0)\n",
|
||||
" assert Y_(p) == 3 and X_(q) == 4\n",
|
||||
" assert distance(p, q) == 5\n",
|
||||
" assert taxi_distance(p, q) == 7\n",
|
||||
" assert add(p, q) == (4, 3)\n",
|
||||
" assert sub(p, q) == (-4, 3)\n",
|
||||
" assert add(North, South) == (0, 0)\n",
|
||||
" \n",
|
||||
"tests()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
Loading…
Reference in New Issue
Block a user