Does Fwy usually speak of themselves in third person?
If I recall correctly they disappear after a while.
Oh, don’t get me wrong. Chrome and derivates are also terrible for spying on your every click. And unless it’s a de-Googled chromium fork it absolutely still phones home to Google. Not quite as much as chrome, but still quite a bit.
Except it kinda does. It reinforces the dominant position Chrome has. A browser mono-culture, if you will. Google doesn’t need to go through proper channels to establish a new standard if they can just set the de-facto-standard by supporting or, maybe more important, not supporting something in Chrome. And since Manifest v3 ad-blockers and other content filters are severely hampered, which only serves Google’s ad-revenue but also hinders accessibility extensions. Mono-cultures just aren’t healthy.
Also I think most people do change there default browser but they change it to Chrome ):
They don’t need to change it to chrome, they’re already using it. Every browser except for Firefox, with its derivatives, and Safari are Chrome. Plus a few more esoteric choices that are nowhere near daily-driver ready.
Yes, but I think we’re talking about a very small percentage. The vast majority will just go “man, that sucks” and continue using it because they’re too lazy to leave their comfort zone. Most users don’t even change the default browser, which is arguably one of the easiest things to change.
Shoot a ray to the right, if and when it collides, shoot a ray to the right, …
You know, recursion.
That’s what I meant with the second part of my reply. With a recursion depth of at least 4 it’ll detect the option for a loop at the location of the ^
.
I’m only casting a ray to detect where turning right now would lead. So to stick with your example:
.O..
-^+#
#++.
..#.
If the guard had come from the left and run this little loop I’d detect this location to place an obstacle.
Alternatively, if I switch back to recursive rays, I’d detect this location a little later:
.O..
.^.#
#|..
.|#.
Yes. For every step I check if turning would lead me back onto my previous path, either because I’m crossing it or because walking that direction will eventually bring me back onto it, passing the obstacle that cause me to turn.
But if you move onto a location+heading that you traversed before, that is a loop.
Which is the express goal of part 2.
Conversely walking in the opposite direction would lead me right past any obstacle that cause me to turn. So it’s not particularly useful.
It just keeps turning. See 3.2. Worst case is it has to turn twice and walk back where it came.
“Open source” is still commonly used to mean FOSS. Source available software isn’t common enough to have made its way into the broader vocabulary.
I just checked my KeePass and turns out I still have the entry in the recycle bin.
It was 5 digits. Admittedly, that was “back in 2012,” but still. For shame, Bank Austria!
Essentially I’m extracting strings from the word search and compare them to the desired value. For part one that means extracting from an X in eight directions. Because I’m reading from the central X outwards, I don’t need to reverse any of them.
Part two reads two strings in an X-shape around the coordinates of each X. The resulting strings are filtered down to include only “MAS” and “SAM”. If there are exactly two strings we found an X-MAS.
from pathlib import Path
def parse_input(input: str) -> list[str]:
return input.strip().splitlines()
def extract_strings_one(m: int, n: int, haystack: list[str], l: int = 4) -> list[str]:
result = []
# Right
if m + l <= len(haystack[n]):
result.append(haystack[n][m : m + l])
# Up-Right
if m + l <= len(haystack[n]) and n > l - 2:
result.append("".join([haystack[n - i][m + i] for i in range(l)]))
# Up
if n > l - 2:
result.append("".join([haystack[n - i][m] for i in range(l)]))
# Up-Left
if m > l - 2 and n > l - 2:
result.append("".join([haystack[n - i][m - i] for i in range(l)]))
# Left
if m > l - 2:
result.append("".join([haystack[n][m - i] for i in range(l)]))
# Down-Left
if m > l - 2 and n + l <= len(haystack):
result.append("".join([haystack[n + i][m - i] for i in range(l)]))
# Down
if n + l <= len(haystack):
result.append("".join([haystack[n + i][m] for i in range(l)]))
# Down-Right
if m + l <= len(haystack[n]) and n + l <= len(haystack):
result.append("".join([haystack[n + i][m + i] for i in range(l)]))
return result
def extract_strings_two(m: int, n: int, haystack: list[str], d: int = 1) -> list[str]:
result = []
if 0 <= m - d and m + d < len(haystack[n]) and 0 <= n - d and n + d < len(haystack):
result.append("".join([haystack[n + i][m + i] for i in range(-d, d + 1)]))
result.append("".join([haystack[n - i][m + i] for i in range(-d, d + 1)]))
return result
def part_one(input: str) -> int:
lines = parse_input(input)
xmas_count = 0
for i, line in enumerate(lines):
x = line.find("X", 0)
while x != -1:
xmas_count += len(
list(filter(lambda s: s == "XMAS", extract_strings_one(x, i, lines)))
)
x = line.find("X", x + 1)
return xmas_count
def part_two(input: str) -> int:
lines = parse_input(input)
x_mas_count = 0
for i, line in enumerate(lines[1:-1], 1):
a = line.find("A", 0)
while a != -1:
if (
len(
list(
filter(
lambda s: s in ("MAS", "SAM"),
extract_strings_two(a, i, lines),
)
)
)
== 2
):
x_mas_count += 1
a = line.find("A", a + 1)
return x_mas_count
if __name__ == "__main__":
input = Path("input").read_text("utf-8")
print(part_one(input))
print(part_two(input))
No need for floor
, you can just use len(pages) // 2
.
Also took advantage of cmp_to_key
.
from functools import cmp_to_key
from pathlib import Path
def parse_input(input: str) -> tuple[dict[int, list[int]], list[list[int]]]:
rules, updates = tuple(input.strip().split("\n\n")[:2])
order = {}
for entry in rules.splitlines():
values = entry.split("|")
order.setdefault(int(values[0]), []).append(int(values[1]))
updates = [[int(v) for v in u.split(",")] for u in updates.splitlines()]
return (order, updates)
def is_ordered(update: list[int], order: dict[int, list[int]]) -> bool:
return update == sorted(
update, key=cmp_to_key(lambda a, b: 1 if a in order.setdefault(b, []) else -1)
)
def part_one(input: str) -> int:
order, updates = parse_input(input)
return sum([u[len(u) // 2] for u in (u for u in updates if is_ordered(u, order))])
def part_two(input: str) -> int:
order, updates = parse_input(input)
return sum(
[
sorted(u, key=cmp_to_key(lambda a, b: 1 if a in order[b] else -1))[
len(u) // 2
]
for u in (u for u in updates if not is_ordered(u, order))
]
)
if __name__ == "__main__":
input = Path("input").read_text("utf-8")
print(part_one(input))
print(part_two(input))
So Pandoc but worse?