advent-of-code-2020/day2/day2.cpp

145 lines
3.5 KiB
C++
Raw Normal View History

#include <folly/String.h>
2020-12-02 06:16:42 +00:00
#include <algorithm>
#include <exception>
#include <fstream>
#include <iostream>
#include <numeric>
2020-12-02 06:16:42 +00:00
#include <regex>
#include <string>
#include <vector>
const std::string POLICY_PATTERN = "([0-9]+)-([0-9]+) (.)";
const std::string DELIM = ": ";
/**
* Policy represents a password policy
*/
class Policy {
2020-12-02 06:36:13 +00:00
public:
2020-12-02 06:16:42 +00:00
Policy(int min, int max, char letter) : min(min), max(max), letter(letter) {
}
/**
* Parse a policy from an input string
* @param input The input to parse
* @return Policy The policy from the input
*/
static Policy parse(const std::string &input) {
std::regex expression(POLICY_PATTERN);
std::smatch matches;
if (!std::regex_search(input, matches, expression)) {
throw new std::invalid_argument("Invalid string");
}
2020-12-02 06:22:02 +00:00
return Policy(std::stoi(matches[1]), std::stoi(matches[2]), matches.str(3).at(0));
2020-12-02 06:16:42 +00:00
}
int getMin() const {
return this->min;
}
int getMax() const {
return this->max;
}
char getLetter() const {
return this->letter;
}
2020-12-02 06:36:13 +00:00
private:
2020-12-02 06:16:42 +00:00
int min;
int max;
char letter;
};
std::vector<std::string> readInput(const std::string &filename) {
2020-12-02 06:16:42 +00:00
std::vector<std::string> input;
std::string line;
std::ifstream file(filename);
while (std::getline(file, line)) {
input.push_back(line);
}
return input;
}
class Entry {
2020-12-02 06:36:13 +00:00
public:
2020-12-02 06:16:42 +00:00
Entry(Policy policy, std::string password) : policy(policy), password(password) {
}
/**
* Parse an input entry from an input string
* @param input The input to parse
* @return Entry the entry from the input
*/
static Entry parse(const std::string &input) {
int delimIndex = input.find(DELIM);
std::vector<std::string> components;
folly::split(DELIM, input, components);
std::string rawPolicy = components.at(0);
std::string password = components.at(1);
2020-12-02 06:16:42 +00:00
Policy policy = Policy::parse(rawPolicy);
return Entry(policy, password);
}
2020-12-02 06:50:31 +00:00
const Policy &getPolicy() const {
2020-12-02 06:16:42 +00:00
return this->policy;
}
2020-12-02 06:50:31 +00:00
const std::string &getPassword() const {
2020-12-02 06:16:42 +00:00
return this->password;
}
2020-12-02 06:36:13 +00:00
private:
2020-12-02 06:16:42 +00:00
Policy policy;
std::string password;
};
2020-12-02 06:33:05 +00:00
/**
* Get the number of valid passwords in the input
* @param input The input split into lines
* @param matches A function that checks whether or not the password matches the policy
* @return int The number ofm atching password
*/
int getNumValidPasswords(const std::vector<std::string> &input, const std::function<bool(const Entry &)> &valid) {
return std::accumulate(input.begin(), input.end(), 0, [&](int total, std::string rawEntry) {
2020-12-02 06:16:42 +00:00
Entry entry = Entry::parse(rawEntry);
return total + valid(entry);
});
2020-12-02 06:16:42 +00:00
}
2020-12-02 06:33:05 +00:00
int part1(const std::vector<std::string> &input) {
return getNumValidPasswords(input, [](const Entry &entry) {
const Policy &policy = entry.getPolicy();
const std::string &password = entry.getPassword();
int count = std::count_if(password.begin(), password.end(), [&](char c) { return c == policy.getLetter(); });
return (count >= policy.getMin() && count <= policy.getMax());
});
}
2020-12-02 06:16:42 +00:00
int part2(const std::vector<std::string> &input) {
2020-12-02 06:33:05 +00:00
return getNumValidPasswords(input, [](const Entry &entry) {
2020-12-02 06:16:42 +00:00
const Policy &policy = entry.getPolicy();
const std::string &password = entry.getPassword();
char letter = entry.getPolicy().getLetter();
2020-12-02 06:33:05 +00:00
return ((password.at(policy.getMin() - 1) == letter) ^ (password.at(policy.getMax() - 1) == letter));
});
2020-12-02 06:16:42 +00:00
}
int main(int argc, char *argv[]) {
if (argc != 2) {
2020-12-02 17:39:33 +00:00
std::cerr << "./day2 <input_file>" << std::endl;
2020-12-02 06:16:42 +00:00
return 1;
}
auto input = readInput(argv[1]);
2020-12-02 06:16:42 +00:00
std::cout << part1(input) << std::endl;
std::cout << part2(input) << std::endl;
}