Re: Advent of Code
Verfasst: Dienstag 13. Dezember 2022, 11:28
Nachtrag: Zuerst ging es mir genau so
Seit 2002 Diskussionen rund um die Programmiersprache Python
https://www.python-forum.de/
Code: Alles auswählen
#!/usr/bin/python3
import fileinput
from itertools import cycle
from collections import UserDict
from P import P
DEBUG = 0
ROCKS = """####
.#.
###
.#.
..#
..#
###
#
#
#
#
##
##"""
ROCK = "#"
FALLING = "@"
EMPTY = "."
WALL = "|"
FLOOR = "-"
CORNER = "+"
class Rock(UserDict):
def __init__(self,pattern):
super().__init__()
for y,line in enumerate(reversed(pattern.split("\n"))):
for x,char in enumerate(line):
self[P(x,y)] = char == ROCK
self.width = max(key.x for key in self.keys())+1
self.height = max(key.y for key in self.keys())+1
def bottom(self,x):
return min(key.y for key in self.keys() if key.x == x)
def top(self,x):
return max(key.y for key in self.keys() if key.x == x)
def left(self,y):
return min(key.x for key in self.keys() if key.y == y)
def right(self,y):
return max(key.x for key in self.keys() if key.y == y)
def __repr__(self):
lines = []
for y in range(self.height):
lines.append("".join("#" if self[P(x,y)] else "." for x in range(self.width)))
return "\n".join(reversed(lines))
class Cave(UserDict):
def __init__(self,width=7):
super().__init__()
self.width = width
self.height = 0
self.falling_rock = None
self.position = None
def __getitem__(self,key):
try:
if self.falling_rock is not None and self.falling_rock[key-self.position]:
return FALLING
except KeyError:
pass
try:
return self.data[key]
except KeyError:
if key.x == -1 or key.x == self.width:
return CORNER if key.y == -1 else WALL
elif key.y == -1:
return FLOOR
else:
return EMPTY
def add_rock(self,rocks,jets):
if DEBUG: print("adding rock")
self.falling_rock = rock = next(rocks)
self.position = position = P(2,self.height+3)
if DEBUG: print(self)
while True:
jet = next(jets)
# move sidewards
if DEBUG >= 2: print("pushing","left" if jet == "<" else "right")
direction = -1 if jet == "<" else 1
edge = rock.left if jet == "<" else rock.right
if not any(self[P(position.x+edge(y)+direction,position.y+y)] != EMPTY for y in range(rock.height)):
self.position = position = P(position.x+direction,position.y)
if DEBUG >= 2: print(self)
# try to fall down
if not any(self[P(position.x+x,position.y+rock.bottom(x)-1)] != EMPTY for x in range(rock.width)):
if DEBUG >= 2: print("falling")
self.position = position = P(position.x,position.y-1)
if DEBUG >= 2: print(self)
else:
if DEBUG >= 2: print("landed")
for x in range(rock.width):
for y in range(rock.height):
if rock[P(x,y)]:
self[P(position.x+x,position.y+y)] = ROCK
self.height = max(self.height,position.y+rock.height)
self.falling_rock = None
if DEBUG >= 2: print(self)
break
def __repr__(self):
lines = []
maxy = self.height+3
if self.falling_rock is not None:
maxy += self.falling_rock.height
for y in range(-1,maxy):
lines.append("".join(self[P(x,y)] for x in range(-1,self.width+1)))
return "\n".join(reversed(lines))
def parse_rocks():
rocks = []
for pattern in ROCKS.split("\n\n"):
rocks.append(Rock(pattern))
return rocks
def part1(rocks,jets):
cave = Cave()
rocks = cycle(rocks)
jets = cycle(jets)
for _ in range(2022):
cave.add_rock(rocks,jets)
print(cave)
return cave.height
def main():
rocks = parse_rocks()
jets = fileinput.FileInput().readline().strip()
print(part1(rocks,jets))
if __name__ == "__main__":
main()
Code: Alles auswählen
class P(tuple):
def __new__(self,x,y):
return tuple.__new__(P,(x,y))
def __add__(self, other):
return P(self.x+other.x,self.y+other.y)
def __sub__(self, other):
return P(self.x-other.x,self.y-other.y)
def __mul__(self, integer):
return P(self.x*integer,self.y*integer)
__rmul__ = __mul__
@property
def x(self):
return self[0]
@property
def y(self):
return self[1]
Code: Alles auswählen
#!/usr/bin/python3
import fileinput
from more_itertools import pairwise
from collections import UserDict
from P import P
DEBUG = 0
ROCKS = """####
.#.
###
.#.
..#
..#
###
#
#
#
#
##
##"""
ROCK = "#"
FALLING = "@"
EMPTY = "."
WALL = "|"
FLOOR = "-"
CORNER = "+"
class Cycle:
def __init__(self,data):
self.position = -1
self.data = data
def __iter__(self):
return self
def __next__(self):
self.position = (self.position + 1) % len(self)
return self.data[self.position]
def __len__(self):
return len(self.data)
class Rock(UserDict):
def __init__(self,pattern):
super().__init__()
for y,line in enumerate(reversed(pattern.split("\n"))):
for x,char in enumerate(line):
self[P(x,y)] = char == ROCK
self.width = max(key.x for key in self.keys())+1
self.height = max(key.y for key in self.keys())+1
def bottom(self,x):
return min(key.y for key in self.keys() if self[key] and key.x == x)
def top(self,x):
return max(key.y for key in self.keys() if self[key] and key.x == x)
def left(self,y):
return min(key.x for key in self.keys() if self[key] and key.y == y)
def right(self,y):
return max(key.x for key in self.keys() if self[key] and key.y == y)
def __repr__(self):
lines = []
for y in range(self.height):
lines.append("".join("#" if self[P(x,y)] else "." for x in range(self.width)))
return "\n".join(reversed(lines))
class Cave(UserDict):
def __init__(self,width=7):
super().__init__()
self.width = width
self.height = 0
self.falling_rock = None
self.position = None
def __getitem__(self,key):
try:
if self.falling_rock is not None and self.falling_rock[key-self.position]:
return FALLING
except KeyError:
pass
try:
return self.data[key]
except KeyError:
if key.x == -1 or key.x == self.width:
return CORNER if key.y == -1 else WALL
elif key.y == -1:
return FLOOR
else:
return EMPTY
def top_shape(self):
tops = [max((key.y for key in self.keys() if key.x == x),default=0) for x in range(self.width)]
start = min(tops)
top_shape = set(key-P(0,start) for key in self.keys() if key.y >= start)
return top_shape
def add_rock(self,rocks,jets):
if DEBUG: print("adding rock")
self.falling_rock = rock = next(rocks)
self.position = position = P(2,self.height+3)
if DEBUG: print(self)
while True:
jet = next(jets)
# move sidewards
if DEBUG >= 2: print("pushing","left" if jet == "<" else "right")
direction = -1 if jet == "<" else 1
edge = rock.left if jet == "<" else rock.right
if not any(self[P(position.x+edge(y)+direction,position.y+y)] != EMPTY for y in range(rock.height)):
self.position = position = P(position.x+direction,position.y)
if DEBUG >= 2: print(self)
# try to fall down
if not any(self[P(position.x+x,position.y+rock.bottom(x)-1)] != EMPTY for x in range(rock.width)):
if DEBUG >= 2: print("falling")
self.position = position = P(position.x,position.y-1)
if DEBUG >= 2: print(self)
else:
if DEBUG >= 2: print("landed")
for x in range(rock.width):
for y in range(rock.height):
if rock[P(x,y)]:
self[P(position.x+x,position.y+y)] = ROCK
self.height = max(self.height,position.y+rock.height)
self.falling_rock = None
if DEBUG >= 2: print(self)
break
def __repr__(self):
lines = []
maxy = self.height+3
if self.falling_rock is not None:
maxy += self.falling_rock.height
for y in range(-1,maxy):
lines.append("".join(self[P(x,y)] for x in range(-1,self.width+1)))
return "\n".join(reversed(lines))
def parse_rocks():
rocks = []
for pattern in ROCKS.split("\n\n"):
rocks.append(Rock(pattern))
return rocks
def part1(rocks,jets):
cave = Cave()
rocks = Cycle(rocks)
jets = Cycle(jets)
for _ in range(2022):
cave.add_rock(rocks,jets)
print(cave)
return cave.height
def part2(rocks,jets):
cave = Cave()
rocks = Cycle(rocks)
jets = Cycle(jets)
top_shapes = {}
fallen = 0
while True:
cave.add_rock(rocks,jets)
fallen += 1
top_shape = cave.top_shape()
top_shape.add((rocks.position,jets.position))
top_shape = tuple(top_shape)
if top_shape in top_shapes.keys():
height_before,fallen_before = top_shapes[top_shape]
height_gain = cave.height - height_before
period = fallen - fallen_before
moves_left = 1000000000000 - fallen
periods = moves_left // period
for _ in range(moves_left % period):
cave.add_rock(rocks,jets)
print(cave)
return cave.height + periods * height_gain
else:
top_shapes[top_shape] = (cave.height,fallen)
return cave.height
def main():
rocks = parse_rocks()
jets = fileinput.FileInput().readline().strip()
print(part1(rocks,jets))
print(part2(rocks,jets))
if __name__ == "__main__":
main()
Code: Alles auswählen
use std::{
fs::File,
io::{prelude::*, BufReader},
path::Path,
};
fn read_lines(filepath: impl AsRef<Path>) -> Vec<String> {
let file_content = File::open(filepath).expect("File not found");
let buffer = BufReader::new(file_content);
buffer.lines()
.map(|l| l.expect("Can't read"))
.collect()
}
fn main() {
let lines = read_lines("/home/dennis/AoC/input.txt");
let mut privous_deep = 0;
let mut counter = 0;
for line in lines {
let line: i32 = line.parse().unwrap();
if privous_deep > 0 {
if line > privous_deep {
counter += 1;
};
};
privous_deep = line;
};
println!("{}", counter);
}
Code: Alles auswählen
from pathlib import Path
import re
INPUT = Path('/home/dennis/AoC/2023/Day1/input.txt')
STRING_TO_DIGIT = {
'one': '1',
'two': '2',
'three': '3',
'four': '4',
'five': '5',
'six': '6',
'seven': '7',
'eight': '8',
'nine': '9'
}
def replace_words(text):
for word, digit in STRING_TO_DIGIT.items():
text = re.sub(word, digit, text)
return text
def find_digit(text):
text = replace_words(text)
return "".join(digit for digit in text if digit.isdigit())
def split_digits(digits):
return int("".join([digits[0], digits[-1]]))
def main():
lines = INPUT.read_text(encoding='UTF-8').splitlines()
digits = list(map(find_digit, lines))
print(sum(list(map(split_digits, digits))))
if __name__ == '__main__':
main()
Falls wir beide die gleiche Falle meinen: Ich hatte den Hinweis bemerkt und die Falle umgangen, hatte aber gar nicht überprüft, ob sie in meinen Eingabedaten überhaupt vorkommt. Das habe ich auf Deinen Tip hin jetzt nachgeholt: Sie kommt auch bei mir sogar mehrfach vor. Also Obacht!__blackjack__ hat geschrieben: ↑Freitag 1. Dezember 2023, 11:05 Iiih, in Aufgabenteil zwei von Tag 1 2023 ist eine kleine Falle drin, in die ich getappt bin, die in den Testdaten nicht vorkam, in meinen persönlichen Eingabedaten aber schon. In den Testdaten ist aber trotzdem ein Hinweis.
Dann sorg doch beim Ersetzen einfach dafür, daß der Buchstabe nicht fehlt.
Code: Alles auswählen
from pathlib import Path
import regex as re
INPUT = Path('/home/dennis/AoC/2023/Day1/input.txt')
STRING_TO_DIGIT = {
'one': '1',
'two': '2',
'three': '3',
'four': '4',
'five': '5',
'six': '6',
'seven': '7',
'eight': '8',
'nine': '9'
}
PATTERN = '|'.join(STRING_TO_DIGIT.keys())
def replace_words(text):
text_and_digits = re.findall(f'\d|{PATTERN}', text, overlapped=True)
text_and_digits = "".join(text_and_digits)
for word, digit in STRING_TO_DIGIT.items():
text_and_digits = re.sub(word, digit, text_and_digits)
return text_and_digits
def find_digit(text):
text = replace_words(text)
return "".join(digit for digit in text if digit.isdigit())
def split_digits(digits):
return int("".join([digits[0], digits[-1]]))
def main():
lines = INPUT.read_text(encoding='UTF-8').splitlines()
digits = list(map(find_digit, lines))
print(sum(list(map(split_digits, digits))))
if __name__ == '__main__':
main()
Code: Alles auswählen
>>> digits = dict(one="1", two="2")
>>> pattern = re.compile(f"(?=({'|'.join(digits)}))")
>>> pattern.sub(lambda match: digits[match[1]], "twone")
'2tw1one'
Code: Alles auswählen
def get_numbers(text: str) -> list[str]:
line_with_numbers = list(text)
for pattern in NUMER_TRANSLATOR.keys():
match = text.find(pattern)
if match == -1:
continue
line_with_numbers[match] = NUMER_TRANSLATOR[pattern]
match = text.rfind(pattern)
line_with_numbers[match] = NUMER_TRANSLATOR[pattern]
calibration_regex = re.compile(r'\d')
numbers = re.findall(calibration_regex, "".join(line_with_numbers))
return numbers