aoc-2022/src/day2.zig

172 lines
4.2 KiB
Zig

const std = @import("std");
const Outcomes = enum(u16) {
Lost = 0,
Draw = 3,
Win = 6,
INVALID = 99,
pub fn from_guide(value: u8) Outcomes{
return switch(value) {
'X' => Outcomes.Lost,
'Y' => Outcomes.Draw,
'Z' => Outcomes.Win,
else => Outcomes.INVALID,
};
}
};
const RPSStates = enum(i8) {
Rock = 0,
Paper =1,
Scissors = 2,
INVALID = 99,
_,
pub fn from_opponent(value: u8) RPSStates {
return switch(value) {
'A' => RPSStates.Rock,
'B' => RPSStates.Paper,
'C' => RPSStates.Scissors,
else => RPSStates.INVALID
};
}
pub fn from_me(value: u8) RPSStates {
return switch(value) {
'X' => RPSStates.Rock,
'Y' => RPSStates.Paper,
'Z' => RPSStates.Scissors,
else => RPSStates.INVALID
};
}
pub fn get_move_needed(outcome_needed: Outcomes, opp_choice: RPSStates) RPSStates {
return switch(outcome_needed) {
.Lost => opp_choice.get_strong_to_move(),
.Draw => opp_choice,
.Win => opp_choice.get_weak_to_move(),
else => unreachable
};
}
pub fn outcome(self: RPSStates, opp_choice: RPSStates) Outcomes {
if (self == opp_choice) {
return Outcomes.Draw;
}
else {
if (self.get_strong_to_move() == opp_choice) {
return Outcomes.Win;
}
else {
return Outcomes.Lost;
}
}
}
pub fn score_round(self: RPSStates, opp_choice: RPSStates) u16 {
var score: u16 = switch(self) {
.Rock => 1,
.Paper => 2,
.Scissors => 3,
else => unreachable
};
score += @enumToInt(self.outcome(opp_choice));
return score;
}
pub fn get_weak_to_move(self: RPSStates) RPSStates {
return @intToEnum(RPSStates, @mod((@enumToInt(self) + 1), 3));
}
pub fn get_strong_to_move(self: RPSStates) RPSStates {
return @intToEnum(RPSStates, @mod((@enumToInt(self) - 1), 3));
}
};
pub fn part1(opp_letter: u8, my_letter: u8) u16 {
const opp_choice = RPSStates.from_opponent(opp_letter);
const my_choice = RPSStates.from_me(my_letter);
return my_choice.score_round(opp_choice);
}
pub fn part2(opp_letter: u8, my_letter: u8) u16 {
const opp_choice = RPSStates.from_opponent(opp_letter);
const win_cond = Outcomes.from_guide(my_letter);
const my_choice = RPSStates.get_move_needed(win_cond, opp_choice);
return my_choice.score_round(opp_choice);
}
pub fn main() !void {
var file = try std.fs.cwd().openFile("inputs/day2.txt", .{});
defer file.close();
var buf_reader = std.io.bufferedReader(file.reader());
var in_stream = buf_reader.reader();
var buf: [1024]u8 = undefined;
var score_part1: u16 = 0;
var score_part2: u16 = 0;
while (try in_stream.readUntilDelimiterOrEof(&buf, '\n')) |line| {
const opp_letter: u8 = line[0];
const my_letter: u8 = line[2];
score_part1 += part1(opp_letter, my_letter);
score_part2 += part2(opp_letter, my_letter);
}
std.debug.print("PART1: My total score: {}\n", .{score_part1});
std.debug.print("PART2: My total score: {}\n", .{score_part2});
}
test "Win Conditions" {
var opp = RPSStates.Paper;
var me = RPSStates.Rock;
var score = me.score_round(opp);
try std.testing.expect(score == 1);
opp = RPSStates.Scissors;
me = RPSStates.Paper;
score = me.score_round(opp);
try std.testing.expect(score == 2);
opp = RPSStates.Rock;
me = RPSStates.Scissors;
score = me.score_round(opp);
try std.testing.expect(score == 3);
opp = RPSStates.Rock;
me = RPSStates.Paper;
score = me.score_round(opp);
try std.testing.expect(me.outcome(opp) == Outcomes.Win);
try std.testing.expect(score == 8);
opp = RPSStates.Paper;
me = RPSStates.Scissors;
score = me.score_round(opp);
try std.testing.expect(score == 9);
opp = RPSStates.Scissors;
me = RPSStates.Rock;
score = me.score_round(opp);
try std.testing.expect(score == 7);
}