generated from public/aoc_template
Day 18 - remove additional perimeter calculation
This commit is contained in:
parent
7595fa8562
commit
55d885f416
279
day12.py
279
day12.py
@ -1,78 +1,13 @@
|
|||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
from tools.aoc import AOCDay
|
from tools.aoc import AOCDay
|
||||||
from tools.int_seq import triangular
|
from tools.itertools import combinations_of_sum, len_combinations_of_sum
|
||||||
from tools.tools import list_combinations_of_sum
|
from typing import Any, Iterator
|
||||||
from typing import Any
|
from tqdm.auto import tqdm
|
||||||
|
|
||||||
|
|
||||||
def _get_placement_options(open_groups: list[tuple[int, str]], groups: list[int], not_found: list[tuple[int, int, int]]) -> list:
|
def clean_springs(springs: str, groups: tuple[int, ...]) -> str:
|
||||||
to_determine = []
|
|
||||||
min_group_len = min(groups[x[2]] for x in not_found)
|
|
||||||
for x, group_str in open_groups.copy():
|
|
||||||
if len(group_str) < min_group_len:
|
|
||||||
open_groups.remove((x, group_str))
|
|
||||||
|
|
||||||
assert not not_found or open_groups, f"No open_groups left to fill with {not_found}"
|
|
||||||
# open_groups = list(sorted(open_groups))
|
|
||||||
# open_groups should always be sorted by default
|
|
||||||
for possible_combination in list_combinations_of_sum(len(not_found), len(open_groups)):
|
|
||||||
# try to put possible_combination[x] in open_groups[x]
|
|
||||||
nf_idx = 0
|
|
||||||
for i, to_place in enumerate(possible_combination):
|
|
||||||
# try to place to_place not_founds in open_groups[i]
|
|
||||||
pass
|
|
||||||
|
|
||||||
for start, group_str in open_groups:
|
|
||||||
print("look in", group_str, "for", [groups[x[2]] for x in not_found])
|
|
||||||
assigned = []
|
|
||||||
for min_x, max_x, idx_need in list(not_found):
|
|
||||||
print("check", min_x, "<", start, "<", max_x, idx_need, groups[idx_need])
|
|
||||||
if groups[idx_need] > len(group_str):
|
|
||||||
continue
|
|
||||||
elif (not assigned or sum(assigned) + len(assigned) + groups[idx_need] <= len(group_str)) and (
|
|
||||||
min_x <= start <= max_x
|
|
||||||
):
|
|
||||||
assigned.append(groups[idx_need])
|
|
||||||
not_found = not_found[1:]
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
print("append", assigned)
|
|
||||||
if assigned:
|
|
||||||
to_determine.append((group_str, assigned))
|
|
||||||
|
|
||||||
return to_determine
|
|
||||||
|
|
||||||
|
|
||||||
def _get_arrangements(springs: str, groups: list[int]):
|
|
||||||
springs, not_found = clean_springs(springs, groups)
|
|
||||||
print("not_found", not_found)
|
|
||||||
open_groups = get_open_groups(springs)
|
|
||||||
to_determine = get_placement_options(open_groups, groups, not_found)
|
|
||||||
arrangements = 1
|
|
||||||
for group_str, values in to_determine:
|
|
||||||
if len(values) == 1 and len(group_str) == values[0]:
|
|
||||||
continue
|
|
||||||
elif sum(values) + len(values) - 1 == len(group_str):
|
|
||||||
continue
|
|
||||||
elif len(values) == 1:
|
|
||||||
arrangements *= len(group_str) - values[0] + 1
|
|
||||||
else:
|
|
||||||
arrangements *= triangular(len(group_str) - (sum(values) + len(values) - 1) + 1)
|
|
||||||
# print(
|
|
||||||
# group_str,
|
|
||||||
# "with",
|
|
||||||
# values,
|
|
||||||
# "has multiple options:",
|
|
||||||
# triangular(len(group_str) - (sum(values) + len(values) - 1) + 1),
|
|
||||||
# )
|
|
||||||
|
|
||||||
if arrangements < 0:
|
|
||||||
print(springs, groups, to_determine)
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
return arrangements
|
|
||||||
|
|
||||||
|
|
||||||
def _clean_springs(springs: str, groups: list[int]) -> (str, list[tuple[int, int, int]]):
|
|
||||||
hashes = []
|
hashes = []
|
||||||
start = None
|
start = None
|
||||||
c_size = 0
|
c_size = 0
|
||||||
@ -90,87 +25,136 @@ def _clean_springs(springs: str, groups: list[int]) -> (str, list[tuple[int, int
|
|||||||
if start is not None:
|
if start is not None:
|
||||||
hashes.append((start, c_size))
|
hashes.append((start, c_size))
|
||||||
|
|
||||||
print("cleaning", springs, "with hashes", hashes, "and groups", groups)
|
# print("cleaning", springs, "with hashes", hashes, "and groups", groups)
|
||||||
found = {}
|
found = {}
|
||||||
for i, s in enumerate(groups):
|
for i, s in enumerate(groups):
|
||||||
for h in hashes:
|
for hash_start, hash_len in hashes:
|
||||||
if h[0] >= sum(groups[:i]) + i and h[0] <= len(springs) - (sum(groups[i:]) + len(groups) - i) + 1:
|
if sum(groups[: i + 1]) + i + 1 < hash_start < len(springs) - 1 - (sum(groups[i:]) + len(groups) - i):
|
||||||
# print(h[0], ">", sum(groups[:i]) + i)
|
if hash_len == s:
|
||||||
# print(h[0], "<", len(springs) - (sum(groups[i:]) + len(groups) - i) + 1)
|
# print(
|
||||||
if h[1] == s:
|
# f"PLACING HASH {i=} {groups[:i+1]} -> {sum(groups[:i + 1]) + i} <= {hash_start} <= {len(springs)=} - ({groups[i:]} -> {sum(groups[i:]) + len(groups) - i})"
|
||||||
found[i] = (h[0], s)
|
# )
|
||||||
if h[0] == 0:
|
found[i] = (hash_start, s)
|
||||||
springs = "#" * h[1] + "." + springs[h[0] + h[1] + 1 :]
|
if hash_start == 0:
|
||||||
elif h[0] + h[1] == len(springs):
|
if len(springs) > hash_len:
|
||||||
springs = springs[: -(h[1] + 1)] + "." + "#" * h[1]
|
springs = "#" * hash_len + "." + springs[hash_start + hash_len + 1 :]
|
||||||
|
else:
|
||||||
|
springs = "#" * hash_len
|
||||||
|
elif hash_start + hash_len == len(springs) - 1:
|
||||||
|
springs = springs[: -(hash_len + 1)] + "." + "#" * hash_len
|
||||||
else:
|
else:
|
||||||
springs = springs[: h[0] - 1] + "." + "#" * h[1] + "." + springs[h[0] + h[1] + 1 :]
|
springs = (
|
||||||
print(
|
springs[: hash_start - 1]
|
||||||
"found index",
|
+ "."
|
||||||
i,
|
+ "#" * hash_len
|
||||||
"value",
|
+ "."
|
||||||
groups[i],
|
+ springs[hash_start + hash_len + 1 :]
|
||||||
"at",
|
)
|
||||||
h[0],
|
# print("found index", i, "value", groups[i], "at", hash_start, "new springs", springs,)
|
||||||
"new springs",
|
|
||||||
springs,
|
|
||||||
)
|
|
||||||
break
|
break
|
||||||
|
|
||||||
print("cleaned springs", springs, "found", found)
|
# print("cleaned springs:", springs)
|
||||||
not_found = []
|
return springs
|
||||||
# not_found entry = (min_x, max_x, index)
|
|
||||||
nf = []
|
|
||||||
last_min = 0
|
|
||||||
for i in range(len(groups)):
|
|
||||||
if i in found:
|
|
||||||
if nf:
|
|
||||||
for x in nf:
|
|
||||||
not_found.append((last_min, found[i][0], x))
|
|
||||||
nf = []
|
|
||||||
last_min = sum(found[i])
|
|
||||||
else:
|
|
||||||
nf.append(i)
|
|
||||||
if nf:
|
|
||||||
for x in nf:
|
|
||||||
not_found.append((last_min, len(springs), x))
|
|
||||||
|
|
||||||
return springs, not_found
|
|
||||||
|
|
||||||
|
|
||||||
def get_open_groups(springs: str) -> list[tuple[int, str]]:
|
def get_open_groups(springs: str) -> list[str]:
|
||||||
open_groups = []
|
open_groups = re.split(r"\.+", springs)
|
||||||
start = None
|
while "" in open_groups:
|
||||||
group_str = ""
|
open_groups.remove("")
|
||||||
for i, c in enumerate(springs):
|
|
||||||
if c == ".":
|
|
||||||
if start is not None:
|
|
||||||
open_groups.append((start, group_str))
|
|
||||||
start = None
|
|
||||||
group_str = ""
|
|
||||||
else:
|
|
||||||
if start is None:
|
|
||||||
start = i
|
|
||||||
group_str += c
|
|
||||||
|
|
||||||
if start is not None:
|
|
||||||
open_groups.append((start, group_str))
|
|
||||||
|
|
||||||
return open_groups
|
return open_groups
|
||||||
|
|
||||||
|
|
||||||
def get_arrangements(springs: str, groups: list[int]) -> int:
|
def get_placement_options(groups: tuple[int, ...], open_groups: list[str]) -> Iterator[tuple]:
|
||||||
|
print(
|
||||||
|
f"get_placement_options({len(groups)}, {len(open_groups)}) returns",
|
||||||
|
len_combinations_of_sum(len(groups), len(open_groups)),
|
||||||
|
)
|
||||||
|
t = tqdm(total=len_combinations_of_sum(len(groups), len(open_groups)), leave=False, file=sys.stdout)
|
||||||
|
for options in combinations_of_sum(total_sum=len(groups), length=len(open_groups)):
|
||||||
|
t.update(1)
|
||||||
|
idx = 0
|
||||||
|
possible = True
|
||||||
|
for i, x in enumerate(options):
|
||||||
|
group_str = open_groups[i]
|
||||||
|
if sum(groups[idx : idx + x]) + x - 1 > len(group_str) or ("#" in group_str and x == 0):
|
||||||
|
possible = False
|
||||||
|
break # not possible
|
||||||
|
idx += x
|
||||||
|
|
||||||
|
if possible:
|
||||||
|
yield options
|
||||||
|
|
||||||
|
t.close()
|
||||||
|
|
||||||
|
|
||||||
|
def brute_force_group(group_str: str, groups: tuple[int, ...]) -> int:
|
||||||
|
count = 0
|
||||||
|
p = re.compile(group_str.replace("?", "."))
|
||||||
|
g_len = len(groups)
|
||||||
|
t = tqdm(
|
||||||
|
total=len_combinations_of_sum(len(group_str) - sum(groups), len(groups)),
|
||||||
|
leave=False,
|
||||||
|
file=sys.stdout,
|
||||||
|
postfix="brute_force",
|
||||||
|
)
|
||||||
|
for x in combinations_of_sum(total_sum=len(group_str) - sum(groups), length=len(groups) + 1):
|
||||||
|
t.update()
|
||||||
|
test_str = ""
|
||||||
|
valid = True
|
||||||
|
for i, c in enumerate(x):
|
||||||
|
test_str += " " * c
|
||||||
|
if 0 < i < g_len and c == 0:
|
||||||
|
valid = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if i < len(groups):
|
||||||
|
test_str += groups[i] * "#"
|
||||||
|
|
||||||
|
if valid and p.match(test_str):
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
t.close()
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
def get_arrangements(springs: str, groups: tuple[int, ...]) -> int:
|
||||||
if sum(groups) + len(groups) - 1 == len(springs):
|
if sum(groups) + len(groups) - 1 == len(springs):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
open_groups = get_open_groups(springs)
|
open_groups = get_open_groups(springs)
|
||||||
print(f"{groups} => {springs} => {open_groups}")
|
# print(f"{groups} => {springs} =>", list((x, len(x)) for x in open_groups))
|
||||||
|
|
||||||
|
arrangements = 0
|
||||||
|
for placement_option in get_placement_options(groups, open_groups):
|
||||||
|
# print("PLACEMENT OPTION", placement_option)
|
||||||
|
sub_arrangements = 1
|
||||||
|
group_idx = 0
|
||||||
|
for i, x in enumerate(placement_option):
|
||||||
|
if x == 0:
|
||||||
|
continue
|
||||||
|
numbers_to_place = groups[group_idx : group_idx + x]
|
||||||
|
group_idx += x
|
||||||
|
group_str = open_groups[i]
|
||||||
|
cleaned_group_str = clean_springs(group_str, numbers_to_place)
|
||||||
|
# print(f"CLEAN ({i}, {x}, {group_idx})", group_str, "=>", cleaned_group_str, "from", numbers_to_place)
|
||||||
|
if cleaned_group_str != group_str:
|
||||||
|
f = get_arrangements(cleaned_group_str, numbers_to_place)
|
||||||
|
# print("RECURSE CALL", cleaned_group_str, numbers_to_place, "=>", f)
|
||||||
|
sub_arrangements *= f
|
||||||
|
else:
|
||||||
|
f = brute_force_group(group_str, numbers_to_place)
|
||||||
|
# print("MISSING CASE:", group_str, numbers_to_place, "=>", f)
|
||||||
|
sub_arrangements *= f
|
||||||
|
# print("SUB", placement_option, "=>", sub_arrangements)
|
||||||
|
arrangements += sub_arrangements
|
||||||
|
|
||||||
|
return arrangements
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
class Day(AOCDay):
|
class Day(AOCDay):
|
||||||
inputs = [
|
inputs = [
|
||||||
[
|
[
|
||||||
|
(101, "input12_debug"),
|
||||||
(21, "input12_test"),
|
(21, "input12_test"),
|
||||||
(6981, "input12"),
|
(6981, "input12"),
|
||||||
],
|
],
|
||||||
@ -180,28 +164,31 @@ class Day(AOCDay):
|
|||||||
],
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def parse_input(self, part2: bool = False) -> list[tuple[str, tuple[int, ...]]]:
|
||||||
|
records = []
|
||||||
|
for line in self.getInput():
|
||||||
|
springs, groupd = line.split()
|
||||||
|
groups = tuple(map(int, groupd.split(",")))
|
||||||
|
if part2:
|
||||||
|
springs = "?".join([springs] * 5)
|
||||||
|
groups *= 5
|
||||||
|
records.append((springs, groups))
|
||||||
|
|
||||||
|
return records
|
||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
ans = 0
|
ans = 0
|
||||||
for line in self.getInput():
|
for springs, groups in self.parse_input():
|
||||||
springs, groups = line.split()
|
|
||||||
groups = list(map(int, groups.split(",")))
|
|
||||||
f = get_arrangements(springs, groups)
|
f = get_arrangements(springs, groups)
|
||||||
print("RESULT", springs, "=>", f)
|
print("RESULT", springs, "=>", f)
|
||||||
ans += f
|
ans += f
|
||||||
|
|
||||||
print("Final result:", ans, "=>", self._current_test_solution)
|
|
||||||
exit(0)
|
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def part2(self) -> Any:
|
def part2(self) -> Any:
|
||||||
if not self.is_test():
|
|
||||||
return ""
|
|
||||||
ans = 0
|
ans = 0
|
||||||
for i, line in enumerate(self.getInput()):
|
# explore moving windows; or some other way to make use of DP
|
||||||
springs, groups = line.split()
|
for i, (springs, groups) in enumerate(self.parse_input(part2=True)):
|
||||||
groups = list(map(int, groups.split(",")))
|
|
||||||
springs = "?".join([springs] * 5)
|
|
||||||
groups = groups * 5
|
|
||||||
f = get_arrangements(springs, groups)
|
f = get_arrangements(springs, groups)
|
||||||
print(i + 1, "/", len(self.input), "=>", f)
|
print(i + 1, "/", len(self.input), "=>", f)
|
||||||
ans += f
|
ans += f
|
||||||
|
|||||||
212
day12_bf.py
Normal file
212
day12_bf.py
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
import re
|
||||||
|
from tools.aoc import AOCDay
|
||||||
|
from tools.int_seq import triangular
|
||||||
|
from typing import Any, Iterable
|
||||||
|
|
||||||
|
|
||||||
|
def is_Valid(springs: str, groups: list[int]) -> bool:
|
||||||
|
foo = []
|
||||||
|
h_count = 0
|
||||||
|
for c in springs:
|
||||||
|
if c == "#":
|
||||||
|
h_count += 1
|
||||||
|
elif h_count > 0:
|
||||||
|
foo.append(h_count)
|
||||||
|
h_count = 0
|
||||||
|
|
||||||
|
if h_count > 0:
|
||||||
|
foo.append(h_count)
|
||||||
|
|
||||||
|
return foo == groups
|
||||||
|
|
||||||
|
|
||||||
|
def sums(length: int, total_sum: int) -> Iterable[tuple]:
|
||||||
|
if length == 1:
|
||||||
|
yield (total_sum,)
|
||||||
|
else:
|
||||||
|
for v in range(total_sum + 1):
|
||||||
|
for p in sums(length - 1, total_sum - v):
|
||||||
|
yield (v,) + p
|
||||||
|
|
||||||
|
|
||||||
|
def get_options(groups: list[int], fill: list[int]) -> Iterable[str]:
|
||||||
|
missing_len = sum(fill)
|
||||||
|
# print("fill_len", len(fill), "miss_len", missing_len)
|
||||||
|
for opt in sums(len(fill), missing_len):
|
||||||
|
ret = ""
|
||||||
|
for i, c in enumerate(opt):
|
||||||
|
if 0 < i < len(fill) - 1 and c == 0:
|
||||||
|
break
|
||||||
|
ret += " " * c
|
||||||
|
if i < len(groups):
|
||||||
|
ret += "#" * groups[i]
|
||||||
|
else:
|
||||||
|
yield ret
|
||||||
|
|
||||||
|
|
||||||
|
def get_arrangements(springs: str, groups: list[int]) -> int:
|
||||||
|
arrangements = 0
|
||||||
|
springs = springs.replace(".", " ")
|
||||||
|
|
||||||
|
after_fill = len(springs) - sum(groups) - len(groups) + 1
|
||||||
|
if after_fill == 0:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fill = [0] + [1] * (len(groups) - 1) + [after_fill]
|
||||||
|
p = re.compile(springs.replace("?", "."))
|
||||||
|
for s in get_options(groups, fill):
|
||||||
|
if p.match(s):
|
||||||
|
arrangements += 1
|
||||||
|
|
||||||
|
return arrangements
|
||||||
|
|
||||||
|
|
||||||
|
def _get_arrangements(springs: str, groups: list[int]):
|
||||||
|
springs, not_found = clean_springs(springs, groups)
|
||||||
|
# print("not_found", not_found)
|
||||||
|
open_groups = get_open_groups(springs)
|
||||||
|
to_determine = []
|
||||||
|
for start, group_str in open_groups:
|
||||||
|
# print("look in", group_str, "for", [groups[x] for x in not_found])
|
||||||
|
assigned = []
|
||||||
|
for need in list(not_found):
|
||||||
|
# print("check", need, groups[need])
|
||||||
|
if groups[need] > len(group_str):
|
||||||
|
continue
|
||||||
|
elif not assigned or sum(assigned) + len(assigned) + groups[need] <= len(group_str):
|
||||||
|
assigned.append(groups[need])
|
||||||
|
not_found = not_found[1:]
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
# print("append", assigned)
|
||||||
|
if assigned:
|
||||||
|
to_determine.append((group_str, assigned))
|
||||||
|
|
||||||
|
arrangements = 1
|
||||||
|
for group_str, values in to_determine:
|
||||||
|
if len(values) == 1 and len(group_str) == values[0]:
|
||||||
|
continue
|
||||||
|
elif sum(values) + len(values) - 1 == len(group_str):
|
||||||
|
continue
|
||||||
|
elif len(values) == 1:
|
||||||
|
arrangements *= len(group_str) - values[0] + 1
|
||||||
|
else:
|
||||||
|
arrangements *= triangular(len(group_str) - (sum(values) + len(values) - 1) + 1)
|
||||||
|
# print(
|
||||||
|
# group_str,
|
||||||
|
# "with",
|
||||||
|
# values,
|
||||||
|
# "has multiple options:",
|
||||||
|
# triangular(len(group_str) - (sum(values) + len(values) - 1) + 1),
|
||||||
|
# )
|
||||||
|
|
||||||
|
if arrangements < 0:
|
||||||
|
# print(springs, groups, to_determine)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
return arrangements
|
||||||
|
|
||||||
|
|
||||||
|
def clean_springs(springs: str, groups: list[int]) -> (str, list[int]):
|
||||||
|
hashes = []
|
||||||
|
start = None
|
||||||
|
c_size = 0
|
||||||
|
for i, c in enumerate(springs):
|
||||||
|
if c == "#":
|
||||||
|
if start is None:
|
||||||
|
start = i
|
||||||
|
c_size += 1
|
||||||
|
else:
|
||||||
|
if start is not None:
|
||||||
|
hashes.append((start, c_size))
|
||||||
|
start = None
|
||||||
|
c_size = 0
|
||||||
|
|
||||||
|
if start is not None:
|
||||||
|
hashes.append((start, c_size))
|
||||||
|
|
||||||
|
# print("cleaning", springs, "with hashes", hashes, "and groups", groups)
|
||||||
|
found = []
|
||||||
|
for i, s in enumerate(groups):
|
||||||
|
for h in hashes:
|
||||||
|
if h[0] >= sum(groups[:i]) + i and h[0] <= len(springs) - (sum(groups[i:]) + len(groups) - i) + 1:
|
||||||
|
# print(h[0], ">", sum(groups[:i]) + i)
|
||||||
|
# print(h[0], "<", len(springs) - (sum(groups[i:]) + len(groups) - i) + 1)
|
||||||
|
if h[1] == s:
|
||||||
|
found.append(i)
|
||||||
|
if i == 0:
|
||||||
|
springs = "#" * h[1] + "." + springs[h[0] + h[1] + 1 :]
|
||||||
|
elif i == len(springs) - 1:
|
||||||
|
springs = springs[: -(h[0] + h[1] + 1)] + "." + "#" * h[1]
|
||||||
|
else:
|
||||||
|
springs = springs[: h[0] - 1] + "." + "#" * h[1] + "." + springs[h[0] + h[1] + 1 :]
|
||||||
|
# print("found index", i, "value", groups[i], "at", h[0], "new springs", springs)
|
||||||
|
break
|
||||||
|
|
||||||
|
# print("cleaned springs", springs, "found", found)
|
||||||
|
|
||||||
|
return springs, [x for x in range(len(groups)) if x not in found]
|
||||||
|
|
||||||
|
|
||||||
|
def get_open_groups(springs: str) -> list[tuple[int, str]]:
|
||||||
|
open_groups = []
|
||||||
|
start = None
|
||||||
|
group_str = ""
|
||||||
|
for i, c in enumerate(springs):
|
||||||
|
if c == ".":
|
||||||
|
if "?" in group_str:
|
||||||
|
open_groups.append((start, group_str))
|
||||||
|
start = None
|
||||||
|
group_str = ""
|
||||||
|
else:
|
||||||
|
if start is None:
|
||||||
|
start = i
|
||||||
|
group_str += c
|
||||||
|
|
||||||
|
if "?" in group_str:
|
||||||
|
open_groups.append((start, group_str))
|
||||||
|
|
||||||
|
return open_groups
|
||||||
|
|
||||||
|
|
||||||
|
class Day(AOCDay):
|
||||||
|
inputs = [
|
||||||
|
[
|
||||||
|
(21, "input12_test"),
|
||||||
|
(6981, "input12"),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
(525152, "input12_test"),
|
||||||
|
(None, "input12"),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
def part1(self) -> Any:
|
||||||
|
ans = 0
|
||||||
|
for line in self.getInput():
|
||||||
|
springs, groups = line.split()
|
||||||
|
groups = list(map(int, groups.split(",")))
|
||||||
|
f = get_arrangements(springs, groups)
|
||||||
|
print("RESULT", springs, "=>", f)
|
||||||
|
ans += f
|
||||||
|
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def part2(self) -> Any:
|
||||||
|
return ""
|
||||||
|
ans = 0
|
||||||
|
for i, line in enumerate(self.getInput()):
|
||||||
|
springs, groups = line.split()
|
||||||
|
groups = list(map(int, groups.split(",")))
|
||||||
|
springs = "?".join([springs] * 5)
|
||||||
|
groups = groups * 5
|
||||||
|
f = get_arrangements(springs, groups)
|
||||||
|
print(i + 1, "/", len(self.input), "=>", f)
|
||||||
|
ans += f
|
||||||
|
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
day = Day(2023, 12)
|
||||||
|
day.run(verbose=True)
|
||||||
5
day18.py
5
day18.py
@ -33,16 +33,13 @@ class Day(AOCDay):
|
|||||||
def get_lagoon_area(self, part2: bool = False) -> int:
|
def get_lagoon_area(self, part2: bool = False) -> int:
|
||||||
start = Coordinate(0, 0)
|
start = Coordinate(0, 0)
|
||||||
points = []
|
points = []
|
||||||
perimeter = 0
|
|
||||||
for d, l in self.parse_input(part2):
|
for d, l in self.parse_input(part2):
|
||||||
perimeter += l
|
|
||||||
end = start + DIRECTIONS[d] * l
|
end = start + DIRECTIONS[d] * l
|
||||||
points.append(end)
|
points.append(end)
|
||||||
start = end
|
start = end
|
||||||
|
|
||||||
p = Polygon(points)
|
p = Polygon(points)
|
||||||
a = abs(p.get_area())
|
return int(p.get_area()) + int(p.get_circumference()) // 2 + 1
|
||||||
return int(p.get_area()) + perimeter // 2 + 1
|
|
||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
return self.get_lagoon_area()
|
return self.get_lagoon_area()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user