Skip to content

Commit

Permalink
2024 day 13: solve part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
yut23 committed Dec 14, 2024
1 parent b665f56 commit 8b2cabe
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
2 changes: 2 additions & 0 deletions 2024/answer_tests/day13/example1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Day 13:
480
15 changes: 15 additions & 0 deletions 2024/input/day13/example1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Button A: X+94, Y+34
Button B: X+22, Y+67
Prize: X=8400, Y=5400

Button A: X+26, Y+66
Button B: X+67, Y+21
Prize: X=12748, Y=12176

Button A: X+17, Y+86
Button B: X+84, Y+37
Prize: X=7870, Y=6450

Button A: X+69, Y+23
Button B: X+27, Y+71
Prize: X=18641, Y=10279
35 changes: 35 additions & 0 deletions 2024/src/day13.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/******************************************************************************
* File: day13.cpp
*
* Author: Eric T. Johnson (yut23)
* Created: 2024-12-13
*****************************************************************************/

#include "day13.hpp"
#include "lib.hpp"
#include <fstream> // for ifstream
#include <iostream> // for cout

int main(int argc, char **argv) {
std::ifstream infile = aoc::parse_args(argc, argv);

auto claw_machines = aoc::day13::read_input(infile);

int part_1 = 0;
for (const auto &claw : claw_machines) {
if constexpr (aoc::DEBUG) {
std::cerr << claw;
}
const auto &[a_presses, b_presses] = claw.min_presses();
if (a_presses > 0 && b_presses > 0) {
int tokens = a_presses * 3 + b_presses * 1;
if constexpr (aoc::DEBUG) {
std::cerr << " winnable with " << tokens << " tokens\n";
}
part_1 += tokens;
}
}
std::cout << part_1 << "\n";

return 0;
}
83 changes: 83 additions & 0 deletions 2024/src/day13.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/******************************************************************************
* File: day13.hpp
*
* Author: Eric T. Johnson (yut23)
* Created: 2024-12-13
*****************************************************************************/

#ifndef DAY13_HPP_WCDIDLRZ
#define DAY13_HPP_WCDIDLRZ

#include "lib.hpp" // for Pos, expect_input, DEBUG
#include <iostream> // for istream, ostream, cerr, noskipws, ws
#include <utility> // for pair
#include <vector> // for vector

namespace aoc::day13 {

struct ClawMachine {
Pos a{0, 0};
Pos b{0, 0};
Pos prize{0, 0};

std::pair<int, int> min_presses() const;
};

std::istream &operator>>(std::istream &is, ClawMachine &claw) {
ClawMachine tmp;
is >> std::noskipws;
is >> aoc::expect_input("Button A: X+") >> tmp.a.x >>
aoc::expect_input(", Y+") >> tmp.a.y >> aoc::expect_input('\n') >>
aoc::expect_input("Button B: X+") >> tmp.b.x >>
aoc::expect_input(", Y+") >> tmp.b.y >> aoc::expect_input('\n') >>
aoc::expect_input("Prize: X=") >> tmp.prize.x >>
aoc::expect_input(", Y=") >> tmp.prize.y >> aoc::expect_input('\n');

if (is) {
// only store if the entire stream was read correctly
claw = std::move(tmp);
}
return is;
}

std::ostream &operator<<(std::ostream &os, const ClawMachine &claw) {
os << "Button A: X+" << claw.a.x << ", Y+" << claw.b.x << "\n"
<< "Button B: X+" << claw.b.x << ", Y+" << claw.b.x << "\n"
<< "Prize: X=" << claw.prize.x << ", Y=" << claw.prize.y << "\n";
return os;
}

// this is just a 2x2 matrix solve, use Cramer's rule
std::pair<int, int> ClawMachine::min_presses() const {
const auto determinant = [](const Pos &p, const Pos &q) -> int {
return p.x * q.y - q.x * p.y;
};
int denom = determinant(a, b);
int a_numer = determinant(prize, b);
int b_numer = determinant(a, prize);
if constexpr (aoc::DEBUG) {
std::cerr << " a = " << a_numer << "/" << denom << " = "
<< static_cast<double>(a_numer) / denom << ", b = " << b_numer
<< "/" << denom << " = "
<< static_cast<double>(b_numer) / denom << "\n";
}
if (a_numer % denom == 0 && b_numer % denom == 0) {
return {a_numer / denom, b_numer / denom};
}
return {-1, -1};
}

auto read_input(std::istream &is) {
std::vector<ClawMachine> claw_machines;
ClawMachine claw;
while (is >> claw) {
claw_machines.push_back(std::move(claw));
// consume extra newline if present
is >> std::ws;
}
return claw_machines;
}

} // namespace aoc::day13

#endif /* end of include guard: DAY13_HPP_WCDIDLRZ */

0 comments on commit 8b2cabe

Please sign in to comment.