2024 Day 2 Part 2
This commit is contained in:
parent
5d7a821496
commit
26bdbeab99
2 changed files with 119 additions and 20 deletions
59
2024/src/day02.py
Normal file
59
2024/src/day02.py
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def relpath(path: str) -> str:
|
||||||
|
return os.path.join(os.path.dirname(__file__), path)
|
||||||
|
|
||||||
|
|
||||||
|
reports = []
|
||||||
|
with open(relpath("../input/day02.txt")) as f:
|
||||||
|
for line in f.readlines():
|
||||||
|
report = [int(i) for i in line.strip().split()]
|
||||||
|
reports.append(report)
|
||||||
|
|
||||||
|
Report = list[int]
|
||||||
|
|
||||||
|
|
||||||
|
def sign(x: int) -> int:
|
||||||
|
if x > 0:
|
||||||
|
return +1
|
||||||
|
if x < 0:
|
||||||
|
return -1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def is_safe(report: Report) -> bool:
|
||||||
|
return first_problem(report) is None
|
||||||
|
|
||||||
|
|
||||||
|
def first_problem(report: Report) -> int | None:
|
||||||
|
direction = sign(report[1] - report[0])
|
||||||
|
for i, (prev, next) in enumerate(zip(report[:-1], report[1:])):
|
||||||
|
diff = next - prev
|
||||||
|
if direction != sign(diff) or abs(diff) < 1 or abs(diff) > 3:
|
||||||
|
return i
|
||||||
|
|
||||||
|
|
||||||
|
def is_safe_tolerant(report: Report) -> bool:
|
||||||
|
if is_safe(report):
|
||||||
|
return True
|
||||||
|
|
||||||
|
for i in range(len(report)):
|
||||||
|
if is_safe(report[:i] + report[i+1:]):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
n = 0
|
||||||
|
m = 0
|
||||||
|
for report in reports:
|
||||||
|
if is_safe(report):
|
||||||
|
n += 1
|
||||||
|
if is_safe_tolerant(report):
|
||||||
|
m += 1
|
||||||
|
|
||||||
|
print(n)
|
||||||
|
print(m)
|
||||||
|
|
@ -6,6 +6,7 @@ pub fn main() !void {
|
||||||
defer _ = gpa.deinit();
|
defer _ = gpa.deinit();
|
||||||
const allocator = gpa.allocator();
|
const allocator = gpa.allocator();
|
||||||
|
|
||||||
|
// const file = try std.fs.cwd().openFile("input/test.txt", .{});
|
||||||
const file = try std.fs.cwd().openFile("input/day02.txt", .{});
|
const file = try std.fs.cwd().openFile("input/day02.txt", .{});
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
|
|
@ -25,6 +26,7 @@ pub fn main() !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
try stdout.print("{d}\n", .{part1(reports)});
|
try stdout.print("{d}\n", .{part1(reports)});
|
||||||
|
try stdout.print("{d}\n", .{try part2(allocator, reports)});
|
||||||
try bw.flush();
|
try bw.flush();
|
||||||
|
|
||||||
for (reports.items) |r| {
|
for (reports.items) |r| {
|
||||||
|
|
@ -33,14 +35,14 @@ pub fn main() !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Report = struct {
|
const Report = struct {
|
||||||
levels: std.ArrayList(u32),
|
levels: std.ArrayList(i32),
|
||||||
|
|
||||||
fn parse(allocator: std.mem.Allocator, line: std.ArrayList(u8)) !Report {
|
fn parse(allocator: std.mem.Allocator, line: std.ArrayList(u8)) !Report {
|
||||||
var levels = std.ArrayList(u32).init(allocator);
|
var levels = std.ArrayList(i32).init(allocator);
|
||||||
|
|
||||||
var it = std.mem.tokenizeScalar(u8, line.items, ' ');
|
var it = std.mem.tokenizeScalar(u8, line.items, ' ');
|
||||||
while (it.next()) |level| {
|
while (it.next()) |level| {
|
||||||
const i = try std.fmt.parseInt(u32, level, 10);
|
const i = try std.fmt.parseInt(i32, level, 10);
|
||||||
try levels.append(i);
|
try levels.append(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,41 +54,69 @@ const Report = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_safe(self: Report) bool {
|
fn is_safe(self: Report) bool {
|
||||||
|
return self.first_problem() == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn first_problem(self: Report) ?usize {
|
||||||
var prev = self.levels.items[0];
|
var prev = self.levels.items[0];
|
||||||
|
|
||||||
const sign = self.levels.items[1] > self.levels.items[0];
|
const sign = Sign.of(self.levels.items[1] - self.levels.items[0]);
|
||||||
|
|
||||||
var i: usize = 1;
|
var i: usize = 1;
|
||||||
while (i < self.levels.items.len) {
|
while (i < self.levels.items.len) {
|
||||||
const next = self.levels.items[i];
|
const next = self.levels.items[i];
|
||||||
const diff = abs_diff(next, prev);
|
const diff = next - prev;
|
||||||
|
|
||||||
if ((next > prev) != sign) {
|
if (Sign.of(diff) != sign or @abs(diff) < 1 or @abs(diff) > 3) {
|
||||||
return false;
|
return i;
|
||||||
}
|
|
||||||
|
|
||||||
if (diff < 1 or diff > 3) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = next;
|
prev = next;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_safe_tolerant(self: Report, allocator: std.mem.Allocator) !bool {
|
||||||
|
if (self.is_safe()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (0..self.levels.items.len) |i| {
|
||||||
|
var fixed = std.ArrayList(i32).init(allocator);
|
||||||
|
defer fixed.deinit();
|
||||||
|
|
||||||
|
try fixed.appendSlice(self.levels.items[0..i]);
|
||||||
|
try fixed.appendSlice(self.levels.items[i + 1 ..]);
|
||||||
|
|
||||||
|
if (is_safe(Report{ .levels = fixed })) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn abs_diff(a: u32, b: u32) u32 {
|
const Sign = enum {
|
||||||
if (a > b) {
|
pos,
|
||||||
return a - b;
|
neg,
|
||||||
} else {
|
zero,
|
||||||
return b - a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part1(reports: std.ArrayList(Report)) u32 {
|
fn of(i: i32) Sign {
|
||||||
var n: u32 = 0;
|
if (i > 0) {
|
||||||
|
return .pos;
|
||||||
|
}
|
||||||
|
if (i < 0) {
|
||||||
|
return .neg;
|
||||||
|
}
|
||||||
|
return .zero;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn part1(reports: std.ArrayList(Report)) i32 {
|
||||||
|
var n: i32 = 0;
|
||||||
for (reports.items) |report| {
|
for (reports.items) |report| {
|
||||||
if (report.is_safe()) {
|
if (report.is_safe()) {
|
||||||
n += 1;
|
n += 1;
|
||||||
|
|
@ -95,3 +125,13 @@ fn part1(reports: std.ArrayList(Report)) u32 {
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn part2(allocator: std.mem.Allocator, reports: std.ArrayList(Report)) !i32 {
|
||||||
|
var n: i32 = 0;
|
||||||
|
for (reports.items) |report| {
|
||||||
|
if (report.is_safe() or try report.is_safe_tolerant(allocator)) {
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue