Skip to content

Instantly share code, notes, and snippets.

@8
Last active May 12, 2024 14:07
Show Gist options
  • Save 8/eb60ec14ccebffcd58530d94fddd2921 to your computer and use it in GitHub Desktop.
Save 8/eb60ec14ccebffcd58530d94fddd2921 to your computer and use it in GitHub Desktop.
const std = @import("std");
pub fn main() !void {
_ = try part1_example();
_ = try part1_file();
}
fn print(comptime format: []const u8, args: anytype) !void {
_ = try std.io.getStdOut().writer().print(format, args);
}
const example =
\\Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
\\Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
\\Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
\\Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
\\Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
;
fn part1_example() !void {
var fbs = std.io.fixedBufferStream(example);
const reader = fbs.reader().any();
const result = try part1(reader, 12, 13, 14);
_ = try print("part1_example: {}\n", .{result});
}
fn part1_file() !void {
var file = try std.fs.cwd().openFile("day2.txt", .{});
const reader = file.reader().any();
const result = try part1(reader, 12, 13, 14);
_ = try print("part1_file: {}\n", .{result});
}
fn part1(reader: std.io.AnyReader, r: u32, g: u32, b: u32) !u32 {
var buf: [1024]u8 = undefined;
var sum : u32 = 0;
while (reader.readUntilDelimiterOrEof(&buf, '\n')) |line_or_null| {
if (line_or_null) |line| {
// _ = try print("{s}\n", .{line});
// parse a game
const game = try Game(20).from_line(line);
if (game.is_valid(r, g, b)) {
sum += game.number;
}
// _ = try print("Game {}\n", .{game.number});
} else {
break;
}
} else |err| {
return err;
}
return sum;
}
const ColorType = enum {
Red, Green, Blue
};
const Color = struct {
count: u32,
color_type: ColorType,
pub fn from(text: []u8) !Color {
var fbs = std.io.fixedBufferStream(text);
var reader = fbs.reader();
var buf: [256]u8 = undefined;
const text_count = reader.readUntilDelimiter(&buf, ' ') catch |e| { return e; };
// _ = try print("text_count: {s}\n", .{text_count});
const i = std.fmt.parseInt(u32, text_count, 10) catch |e| {return e;};
const text_color_type = text[text_count.len+1..text.len];
// _ = try print("text_color_type: {s}", .{text_color_type});
const color_type =
if (std.mem.eql(u8, text_color_type, "red"))
ColorType.Red
else if(std.mem.eql(u8, text_color_type, "green"))
ColorType.Green
else
ColorType.Blue;
return Color {
.count = i,
.color_type = color_type,
};
}
};
const Set = struct {
red: u32,
green: u32,
blue: u32,
pub fn from(text: []u8) !Set {
var fbs = std.io.fixedBufferStream(text);
var reader = fbs.reader();
var buf: [1024]u8 = undefined;
var red: u32 = 0;
var green: u32 = 0;
var blue: u32 = 0;
while (reader.readUntilDelimiterOrEof(&buf, ',')) |r| {
if (r) |text_color| {
// _ = try print("text_color: {s}\n", .{text_color});
const color = try Color.from(text_color[1..]);
// _ = try print("color: count={}, type={}\n", .{color.count, color.color_type});
if (color.color_type == ColorType.Red) {
red = color.count;
} else if (color.color_type == ColorType.Green) {
green = color.count;
} else if (color.color_type == ColorType.Blue) {
blue = color.count;
}
} else { // eof
break;
}
} else |e| { return e;}
return Set {
.red = red,
.green = green,
.blue = blue,
};
}
};
fn Game(comptime max_sets: usize) type {
return struct {
number: u32,
sets: [max_sets]Set,
sets_used: usize,
// example line: "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green"
pub fn from_line(line: []u8) !Game(max_sets) {
var fbs = std.io.fixedBufferStream(line);
var reader = fbs.reader();
// parse the game number
var game_num : u32 = undefined;
var buf_game: [1024]u8 = undefined;
if (reader.readUntilDelimiter(&buf_game, ':')) |game| {
if (std.fmt.parseInt(u32, game[("Game ".len)..game.len], 10)) |i| {
game_num = i;
} else |e| {
return e;
}
// _ = try print("game: {}\n", .{game_num});
// parse the sets
var buf_set: [1024]u8 = undefined;
var sets: [max_sets]Set = undefined;
var set_index : usize = 0;
while (reader.readUntilDelimiterOrEof(&buf_set, ';')) |set_or_null| {
if (set_or_null) |set_slice| {
// _ = try print("slice: {s}\n", .{set_slice});
const set = try Set.from(set_slice);
sets[set_index] = set;
set_index=set_index+1;
} else {
break;
}
} else |err| { return err; }
return Game(max_sets) {
.number = game_num,
.sets = sets,
.sets_used = set_index,
};
} else |e| {
return e;
}
}
pub fn is_valid(self: Game(max_sets), r: u32, g: u32, b: u32) bool {
var all_valid = true;
for (0..self.sets_used) |i| {
const s = self.sets[i];
// print("r:{},g:{},b:{}\n", .{s.red, s.green, s.blue}) catch {};
all_valid = s.red <= r and s.green <= g and s.blue <= b;
if (!all_valid) {
break;
}
}
return all_valid;
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment