Skip to content

Commit 035b111

Browse files
committed
Improve boolean args and enable ruff checks for it
1 parent 51b344b commit 035b111

File tree

8 files changed

+124
-75
lines changed

8 files changed

+124
-75
lines changed

adventofcode/tooling/map.py

+22-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import enum
34
from typing import TYPE_CHECKING, Literal, assert_never, overload
45

56
from .coordinates import X, Y
@@ -19,6 +20,11 @@ def __init__(self) -> None:
1920
super().__init__("data must be rectangular")
2021

2122

23+
class IterDirection(enum.Enum):
24+
Rows = enum.auto()
25+
Columns = enum.auto()
26+
27+
2228
class Map2d[Map2dDataType]:
2329
__slots__ = ("_sequence_data", "_width", "_height", "_br_y", "_br_x")
2430

@@ -158,23 +164,23 @@ def iter_data_by_columns(
158164

159165
@overload
160166
def iter_data(
161-
self,
162-
*,
163-
columns_first: bool,
167+
self, *, direction: IterDirection
164168
) -> Iterable[tuple[X, Iterable[tuple[Y, Map2dDataType]]]]: ...
165169
@overload
166170
def iter_data(
167-
self,
168-
*,
169-
columns_first: Literal[False] = False,
171+
self, *, direction: Literal[IterDirection.Rows] = IterDirection.Rows
170172
) -> Iterable[tuple[Y, Iterable[tuple[X, Map2dDataType]]]]: ...
171173
@overload
172174
def iter_data(
173-
self, first_y: Y, first_x: X, *, columns_first: bool
175+
self, first_y: Y, first_x: X, *, direction: IterDirection
174176
) -> Iterable[tuple[X, Iterable[tuple[Y, Map2dDataType]]]]: ...
175177
@overload
176178
def iter_data(
177-
self, first_y: Y, first_x: X, *, columns_first: Literal[False] = False
179+
self,
180+
first_y: Y,
181+
first_x: X,
182+
*,
183+
direction: Literal[IterDirection.Rows] = IterDirection.Rows,
178184
) -> Iterable[tuple[Y, Iterable[tuple[X, Map2dDataType]]]]: ...
179185
@overload
180186
def iter_data(
@@ -184,7 +190,7 @@ def iter_data(
184190
last_y: Y,
185191
last_x: X,
186192
*,
187-
columns_first: bool,
193+
direction: IterDirection,
188194
) -> Iterable[tuple[X, Iterable[tuple[Y, Map2dDataType]]]]: ...
189195
@overload
190196
def iter_data(
@@ -194,7 +200,7 @@ def iter_data(
194200
last_y: Y,
195201
last_x: X,
196202
*,
197-
columns_first: Literal[False] = False,
203+
direction: Literal[IterDirection.Rows] = IterDirection.Rows,
198204
) -> Iterable[tuple[Y, Iterable[tuple[X, Map2dDataType]]]]: ...
199205

200206
def iter_data(
@@ -204,7 +210,7 @@ def iter_data(
204210
last_y: Y | None = None,
205211
last_x: X | None = None,
206212
*,
207-
columns_first: bool = False,
213+
direction: IterDirection = IterDirection.Rows,
208214
) -> (
209215
Iterable[tuple[Y, Iterable[tuple[X, Map2dDataType]]]]
210216
| Iterable[tuple[X, Iterable[tuple[Y, Map2dDataType]]]]
@@ -232,10 +238,11 @@ def iter_data(
232238
if first_y > self._br_y and last_y >= self._br_y:
233239
return
234240

235-
if not columns_first:
236-
yield from self.iter_data_by_lines(first_y, first_x, last_y, last_x)
237-
else:
238-
yield from self.iter_data_by_columns(first_y, first_x, last_y, last_x)
241+
match direction:
242+
case IterDirection.Rows:
243+
yield from self.iter_data_by_lines(first_y, first_x, last_y, last_x)
244+
case IterDirection.Columns:
245+
yield from self.iter_data_by_columns(first_y, first_x, last_y, last_x)
239246

240247
def str_lines(
241248
self, get_symbol: Callable[[Map2dDataType], str] | None = None

adventofcode/y2023/d1.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
_STR_DIGITS = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
55

66

7-
def _find_first_and_last_int(input_str: str, use_texts: bool) -> tuple[str, str]:
7+
def _find_first_and_last_int(input_str: str, *, use_texts: bool) -> tuple[str, str]:
88
first: str | None = None
99
last: str | None = None
1010
for ind, c in enumerate(input_str):
@@ -33,17 +33,17 @@ def _int_chars_to_int(s1: str, s2: str) -> int:
3333
return int(s1 + s2)
3434

3535

36-
def _p1_ints(lines: Iterable[str], use_texts: bool) -> Iterable[int]:
36+
def _p1_ints(lines: Iterable[str], *, use_texts: bool) -> Iterable[int]:
3737
for line in lines:
3838
logging.debug("line=%s", line)
39-
value = _int_chars_to_int(*_find_first_and_last_int(line, use_texts))
39+
value = _int_chars_to_int(*_find_first_and_last_int(line, use_texts=use_texts))
4040
logging.debug("value=%s", value)
4141
yield value
4242

4343

4444
def p1(input_str: str) -> int:
45-
return sum(_p1_ints(input_str.splitlines(), False))
45+
return sum(_p1_ints(input_str.splitlines(), use_texts=False))
4646

4747

4848
def p2(input_str: str) -> int:
49-
return sum(_p1_ints(input_str.splitlines(), True))
49+
return sum(_p1_ints(input_str.splitlines(), use_texts=True))

adventofcode/y2023/d13.py

+38-31
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from collections.abc import Iterable
44

55
from adventofcode.tooling.coordinates import X, Y
6-
from adventofcode.tooling.map import Map2d
6+
from adventofcode.tooling.map import IterDirection, Map2d
77

88

99
def _parse_maps(input_str: str) -> Iterable[Map2d[str]]:
@@ -31,19 +31,21 @@ def _compare_datas(
3131

3232

3333
def _find_consecutive_rows_or_columns(
34-
map_: Map2d[str], start_pos: int, find_column_not_row: bool, allowed_mismatches: int
34+
map_: Map2d[str],
35+
start_pos: int,
36+
direction: IterDirection,
37+
allowed_mismatches: int,
3538
) -> tuple[int, int] | None:
36-
if find_column_not_row:
37-
first_y = Y(0)
38-
first_x = X(start_pos)
39-
else:
40-
first_y = Y(start_pos)
41-
first_x = X(0)
39+
match direction:
40+
case IterDirection.Rows:
41+
first_y = Y(start_pos)
42+
first_x = X(0)
43+
case IterDirection.Columns:
44+
first_y = Y(0)
45+
first_x = X(start_pos)
4246
for (i1, data1), (_, data2) in itertools.pairwise(
4347
(i, [sym for _, sym in sym_iter])
44-
for i, sym_iter in map_.iter_data(
45-
first_y, first_x, columns_first=find_column_not_row
46-
)
48+
for i, sym_iter in map_.iter_data(first_y, first_x, direction=direction)
4749
):
4850
match_res = _compare_datas(data1, data2, allowed_mismatches)
4951
if match_res is None:
@@ -59,23 +61,24 @@ def _map_data_iter_to_data(d: tuple[int, str]) -> str:
5961
def _check_if_datas_around_reflection_match(
6062
map_: Map2d[str],
6163
pos_before_reflection: int,
62-
find_column_not_row: bool,
64+
direction: IterDirection,
6365
allowed_mismatches: int,
6466
) -> int | None:
65-
if find_column_not_row:
66-
before_first_y = Y(0)
67-
before_first_x = X(pos_before_reflection - 1)
68-
before_last_y = map_.br_y
69-
before_last_x = X(-1)
70-
after_first_y = Y(0)
71-
after_first_x = X(pos_before_reflection + 2)
72-
else:
73-
before_first_y = Y(pos_before_reflection - 1)
74-
before_first_x = X(0)
75-
before_last_y = Y(-1)
76-
before_last_x = map_.br_x
77-
after_first_y = Y(pos_before_reflection + 2)
78-
after_first_x = X(0)
67+
match direction:
68+
case IterDirection.Rows:
69+
before_first_y = Y(pos_before_reflection - 1)
70+
before_first_x = X(0)
71+
before_last_y = Y(-1)
72+
before_last_x = map_.br_x
73+
after_first_y = Y(pos_before_reflection + 2)
74+
after_first_x = X(0)
75+
case IterDirection.Columns:
76+
before_first_y = Y(0)
77+
before_first_x = X(pos_before_reflection - 1)
78+
before_last_y = map_.br_y
79+
before_last_x = X(-1)
80+
after_first_y = Y(0)
81+
after_first_x = X(pos_before_reflection + 2)
7982

8083
mismatches = 0
8184

@@ -102,7 +105,7 @@ def _check_if_datas_around_reflection_match(
102105

103106

104107
def _find_reflection_line(
105-
map_: Map2d[str], find_column_not_row: bool, required_mismatches: int = 0
108+
map_: Map2d[str], direction: IterDirection, required_mismatches: int = 0
106109
) -> int | None:
107110
logging.debug(
108111
"Searching for reflection with %d required mismatches", required_mismatches
@@ -111,7 +114,7 @@ def _find_reflection_line(
111114
while True:
112115
remaining_mismatches = required_mismatches
113116
found_data_info = _find_consecutive_rows_or_columns(
114-
map_, search_start_pos, find_column_not_row, remaining_mismatches
117+
map_, search_start_pos, direction, remaining_mismatches
115118
)
116119
if found_data_info is None:
117120
logging.debug(
@@ -131,7 +134,7 @@ def _find_reflection_line(
131134
)
132135

133136
check_res = _check_if_datas_around_reflection_match(
134-
map_, first_pos, find_column_not_row, remaining_mismatches
137+
map_, first_pos, direction, remaining_mismatches
135138
)
136139
if check_res is None:
137140
logging.debug(
@@ -159,12 +162,16 @@ def _resolve(input_str: str, required_mismatches_per_map: int) -> int:
159162
map_.width,
160163
map_,
161164
)
162-
match_index = _find_reflection_line(map_, False, required_mismatches_per_map)
165+
match_index = _find_reflection_line(
166+
map_, IterDirection.Rows, required_mismatches_per_map
167+
)
163168
if match_index is not None:
164169
line_or_column = "L"
165170
match_multiplier = 100
166171
else:
167-
match_index = _find_reflection_line(map_, True, required_mismatches_per_map)
172+
match_index = _find_reflection_line(
173+
map_, IterDirection.Columns, required_mismatches_per_map
174+
)
168175
assert match_index is not None
169176
line_or_column = "C"
170177
match_multiplier = 1

adventofcode/y2023/d14.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from adventofcode.tooling.coordinates import Coord2d, X, Y
55
from adventofcode.tooling.directions import CardinalDirection as Dir
6-
from adventofcode.tooling.map import Map2d
6+
from adventofcode.tooling.map import IterDirection, Map2d
77

88
if TYPE_CHECKING:
99
from collections.abc import Iterable
@@ -35,7 +35,7 @@ def _coord_columns_first(outer: Y | X, inner: Y | X) -> Coord2d:
3535
| Iterable[tuple[X, Iterable[tuple[Y, str]]]]
3636
)
3737
if direction == Dir.N:
38-
map_iter = map_.iter_data(columns_first=True)
38+
map_iter = map_.iter_data(direction=IterDirection.Columns)
3939
coord_func = _coord_columns_first
4040

4141
def set_rock(

adventofcode/y2023/d20.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717

1818
_PulseValue = NewType("_PulseValue", bool)
19-
_PulseLow = _PulseValue(False)
20-
_PulseHigh = _PulseValue(True)
19+
_PulseLow = _PulseValue(False) # noqa: FBT003
20+
_PulseHigh = _PulseValue(True) # noqa: FBT003
2121

2222
_ModuleName = NewType("_ModuleName", str)
2323

adventofcode/y2023/d6.py

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import enum
12
from collections.abc import Iterable
23
from functools import reduce
34

@@ -38,15 +39,27 @@ def p2(input_str: str) -> int:
3839
time = int(reduce(lambda t1, t2: t1 + t2, (str(t) for t, _ in d)))
3940
distance = int(reduce(lambda d1, d2: d1 + d2, (str(d) for _, d in d)))
4041

42+
class ScenarioOrdering(enum.Enum):
43+
FASTEST = enum.auto()
44+
SLOWEST = enum.auto()
45+
4146
def first_possible_button_press_time(
42-
max_time: int, distance_to_beat: int, forward: bool
47+
max_time: int, distance_to_beat: int, ordering: ScenarioOrdering
4348
) -> int:
44-
r = range(1, max_time) if forward else range(max_time - 1, 0, -1)
49+
match ordering:
50+
case ScenarioOrdering.FASTEST:
51+
r = range(1, max_time)
52+
case ScenarioOrdering.SLOWEST:
53+
r = range(max_time - 1, 0, -1)
4554
for button_press_time in r:
4655
if _is_winning_scenario(button_press_time, max_time, distance_to_beat):
4756
return button_press_time
4857
raise AssertionError
4958

50-
first_button_press_time = first_possible_button_press_time(time, distance, True)
51-
last_button_press_time = first_possible_button_press_time(time, distance, False)
59+
first_button_press_time = first_possible_button_press_time(
60+
time, distance, ScenarioOrdering.FASTEST
61+
)
62+
last_button_press_time = first_possible_button_press_time(
63+
time, distance, ScenarioOrdering.SLOWEST
64+
)
5265
return len(range(first_button_press_time, last_button_press_time)) + 1

pyproject.toml

-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ ignore = [
6363
"C901",
6464
"COM812",
6565
"D10",
66-
"FBT001",
67-
"FBT003",
6866
"FIX",
6967
"ISC001",
7068
"PLR2004",

0 commit comments

Comments
 (0)