Add .clang-format and apply it
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::vector<int> vals;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
int val = std::stoi(line, nullptr, 10);
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::vector<int> vals;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
int val = std::stoi(line, nullptr, 10);
|
||||
@@ -12,8 +13,8 @@ int main(int argc, char **argv) {
|
||||
for (std::size_t j = 0; j < i; ++j) {
|
||||
int64_t v2 = vals[j];
|
||||
if (v1 + v2 + val == 2020) {
|
||||
std::cout << v1 << " * " << v2 << " * " << val << " = "
|
||||
<< v1 * v2 * std::int64_t(val) << "\n";
|
||||
std::cout << v1 << " * " << v2 << " * " << val << " = " << v1 * v2 * std::int64_t(val)
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct PasswordChecker {
|
||||
PasswordChecker(std::string const &s) {
|
||||
struct PasswordChecker
|
||||
{
|
||||
PasswordChecker(std::string const& s)
|
||||
{
|
||||
std::size_t pos = 0;
|
||||
min_ = std::stoul(s, &pos, 10);
|
||||
assert(s[pos] == '-');
|
||||
@@ -17,7 +19,8 @@ struct PasswordChecker {
|
||||
password_ = s2.substr(pos + 4);
|
||||
}
|
||||
|
||||
bool is_valid() const {
|
||||
bool is_valid() const
|
||||
{
|
||||
std::string::size_type count = 0;
|
||||
for (auto c : password_) {
|
||||
if (c == c_) {
|
||||
@@ -34,13 +37,15 @@ struct PasswordChecker {
|
||||
std::string password_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
PasswordChecker check(line);
|
||||
if (check.is_valid()) {
|
||||
++count;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << "IN";
|
||||
}
|
||||
std::cout << "VALID: " << line << "\n";
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct PasswordChecker {
|
||||
PasswordChecker(std::string const &s) {
|
||||
struct PasswordChecker
|
||||
{
|
||||
PasswordChecker(std::string const& s)
|
||||
{
|
||||
std::size_t pos = 0;
|
||||
pos1_ = std::stoul(s, &pos, 10);
|
||||
assert(s[pos] == '-');
|
||||
@@ -17,7 +19,8 @@ struct PasswordChecker {
|
||||
password_ = s2.substr(pos + 4);
|
||||
}
|
||||
|
||||
bool is_valid() const {
|
||||
bool is_valid() const
|
||||
{
|
||||
std::string::size_type count = 0;
|
||||
if (password_.at(pos1_ - 1) == c_) {
|
||||
++count;
|
||||
@@ -28,19 +31,21 @@ struct PasswordChecker {
|
||||
return count == 1;
|
||||
}
|
||||
|
||||
std::string::size_type pos1_; // 1 based
|
||||
std::string::size_type pos2_; // 1 based
|
||||
std::string::size_type pos1_; // 1 based
|
||||
std::string::size_type pos2_; // 1 based
|
||||
std::string::value_type c_;
|
||||
std::string password_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
PasswordChecker check(line);
|
||||
if (check.is_valid()) {
|
||||
++count;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << "IN";
|
||||
}
|
||||
std::cout << "VALID: " << line << "\n";
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
std::string rotate(std::string const &s, std::string::size_type amount) {
|
||||
std::string rotate(std::string const& s, std::string::size_type amount)
|
||||
{
|
||||
auto length = s.length();
|
||||
return (s + s).substr(amount % length, length);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned count = 0;
|
||||
std::string::size_type rotation = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
std::string rotate(std::string const &s, std::string::size_type amount) {
|
||||
std::string rotate(std::string const& s, std::string::size_type amount)
|
||||
{
|
||||
auto length = s.length();
|
||||
return (s + s).substr(amount % length, length);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " <right> <down>\n";
|
||||
return 1;
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
using StringSet = std::set<std::string>;
|
||||
|
||||
namespace {
|
||||
StringSet parse_line(std::string const &str) {
|
||||
StringSet parse_line(std::string const& str)
|
||||
{
|
||||
StringSet result;
|
||||
std::string::size_type pos = 0;
|
||||
|
||||
@@ -28,20 +29,21 @@ StringSet parse_line(std::string const &str) {
|
||||
const StringSet mandatory{"byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"};
|
||||
const StringSet optional{"cid"};
|
||||
|
||||
bool is_valid_passport(StringSet const &mandatory_found) {
|
||||
bool is_valid_passport(StringSet const& mandatory_found)
|
||||
{
|
||||
return mandatory_found.size() == mandatory.size();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
StringSet mandatory_found;
|
||||
StringSet optional_found;
|
||||
unsigned valid = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
if (!line.empty()) {
|
||||
auto keys = parse_line(line);
|
||||
for (auto const &key : keys) {
|
||||
for (auto const& key : keys) {
|
||||
std::cout << "Key " << key << " is ";
|
||||
if (mandatory.find(key) != mandatory.end()) {
|
||||
auto [it, success] = mandatory_found.insert(key);
|
||||
@@ -49,18 +51,21 @@ int main(int argc, char **argv) {
|
||||
if (!success) {
|
||||
std::cout << " (duplicate)";
|
||||
}
|
||||
} else if (optional.find(key) != optional.end()) {
|
||||
}
|
||||
else if (optional.find(key) != optional.end()) {
|
||||
auto [it, success] = optional_found.insert(key);
|
||||
std::cout << "optional";
|
||||
if (!success) {
|
||||
std::cout << " (duplicate)";
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << "unexpected";
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
valid += is_valid_passport(mandatory_found);
|
||||
mandatory_found.clear();
|
||||
optional_found.clear();
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
// Various types that are useful
|
||||
using StringSet = std::set<std::string>;
|
||||
using StringMap = std::map<std::string, std::string>;
|
||||
using ValidateFn = std::function<bool(std::string const &)>;
|
||||
using ValidateFn = std::function<bool(std::string const&)>;
|
||||
using ValidateMap = std::map<std::string, ValidateFn>;
|
||||
|
||||
namespace {
|
||||
@@ -19,7 +19,8 @@ namespace {
|
||||
* \a str is expected to look like a space separated list of pairs where each
|
||||
* pair is of the form 'key:value'.
|
||||
*/
|
||||
StringMap parse_line(std::string const &str) {
|
||||
StringMap parse_line(std::string const& str)
|
||||
{
|
||||
StringMap result;
|
||||
std::string::size_type pos = 0;
|
||||
|
||||
@@ -32,9 +33,8 @@ StringMap parse_line(std::string const &str) {
|
||||
assert(colon_pos != std::string::npos);
|
||||
assert(colon_pos < end_pos);
|
||||
auto key_len = colon_pos - pos;
|
||||
auto value_len = (end_pos == std::string::npos)
|
||||
? std::string::npos
|
||||
: (end_pos - (colon_pos + 1));
|
||||
auto value_len =
|
||||
(end_pos == std::string::npos) ? std::string::npos : (end_pos - (colon_pos + 1));
|
||||
auto key = str.substr(pos, key_len);
|
||||
auto value = str.substr(colon_pos + 1, value_len);
|
||||
result.insert({key, value});
|
||||
@@ -50,7 +50,8 @@ StringMap parse_line(std::string const &str) {
|
||||
* \param max Maximum year to accept
|
||||
* \return True if \a s is in range [min, max]
|
||||
*/
|
||||
bool validate_year(std::string const &s, unsigned min, unsigned max) {
|
||||
bool validate_year(std::string const& s, unsigned min, unsigned max)
|
||||
{
|
||||
if (s.length() != 4) {
|
||||
return false;
|
||||
}
|
||||
@@ -63,16 +64,17 @@ bool validate_year(std::string const &s, unsigned min, unsigned max) {
|
||||
}
|
||||
|
||||
/// Validate byr field
|
||||
bool validate_byr(std::string const &s) { return validate_year(s, 1920, 2002); }
|
||||
bool validate_byr(std::string const& s) { return validate_year(s, 1920, 2002); }
|
||||
|
||||
/// Validate iyr field
|
||||
bool validate_iyr(std::string const &s) { return validate_year(s, 2010, 2020); }
|
||||
bool validate_iyr(std::string const& s) { return validate_year(s, 2010, 2020); }
|
||||
|
||||
/// Validate eyr field
|
||||
bool validate_eyr(std::string const &s) { return validate_year(s, 2020, 2030); }
|
||||
bool validate_eyr(std::string const& s) { return validate_year(s, 2020, 2030); }
|
||||
|
||||
/// Validate hgt field
|
||||
bool validate_hgt(std::string const &s) {
|
||||
bool validate_hgt(std::string const& s)
|
||||
{
|
||||
std::size_t pos = 0;
|
||||
auto hgt = std::stoul(s, &pos, 10);
|
||||
if (pos != s.length() - 2) {
|
||||
@@ -80,7 +82,8 @@ bool validate_hgt(std::string const &s) {
|
||||
}
|
||||
if (s[pos] == 'c' && s[pos + 1] == 'm') {
|
||||
return hgt >= 150 && hgt <= 193;
|
||||
} else if (s[pos] == 'i' && s[pos + 1] == 'n') {
|
||||
}
|
||||
else if (s[pos] == 'i' && s[pos + 1] == 'n') {
|
||||
return hgt >= 59 && hgt <= 76;
|
||||
}
|
||||
return false;
|
||||
@@ -92,8 +95,8 @@ bool validate_hgt(std::string const &s) {
|
||||
* \param cs Valid characters
|
||||
* \return True iff we pass validation
|
||||
*/
|
||||
bool validate_chars(std::string const &s, std::string::size_type len,
|
||||
std::string const &cs) {
|
||||
bool validate_chars(std::string const& s, std::string::size_type len, std::string const& cs)
|
||||
{
|
||||
if (s.length() != len) {
|
||||
return false;
|
||||
}
|
||||
@@ -107,7 +110,8 @@ bool validate_chars(std::string const &s, std::string::size_type len,
|
||||
}
|
||||
|
||||
/// Validate hcl field
|
||||
bool validate_hcl(std::string const &s) {
|
||||
bool validate_hcl(std::string const& s)
|
||||
{
|
||||
if (s.length() != 7) {
|
||||
return false;
|
||||
}
|
||||
@@ -118,46 +122,43 @@ bool validate_hcl(std::string const &s) {
|
||||
}
|
||||
|
||||
/// Validate ecl field
|
||||
bool validate_ecl(std::string const &s) {
|
||||
static const StringSet valid = {"amb", "blu", "brn", "gry",
|
||||
"grn", "hzl", "oth"};
|
||||
bool validate_ecl(std::string const& s)
|
||||
{
|
||||
static const StringSet valid = {"amb", "blu", "brn", "gry", "grn", "hzl", "oth"};
|
||||
return valid.find(s) != valid.end();
|
||||
}
|
||||
|
||||
/// Validate pid field
|
||||
bool validate_pid(std::string const &s) {
|
||||
return validate_chars(s, 9, "0123456789");
|
||||
}
|
||||
bool validate_pid(std::string const& s) { return validate_chars(s, 9, "0123456789"); }
|
||||
|
||||
/// Validate cid field
|
||||
bool validate_cid(std::string const &s) { return true; }
|
||||
bool validate_cid(std::string const& s) { return true; }
|
||||
|
||||
/// Check if a passport is valid
|
||||
///
|
||||
/// A passport is valid if it contains all mandatory fields, and passes
|
||||
/// validation on all fields.
|
||||
bool is_valid_passport(StringMap const &found) {
|
||||
static const StringSet mandatory{"byr", "iyr", "eyr", "hgt",
|
||||
"hcl", "ecl", "pid"};
|
||||
bool is_valid_passport(StringMap const& found)
|
||||
{
|
||||
static const StringSet mandatory{"byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"};
|
||||
static const ValidateMap validators{
|
||||
{"byr", validate_byr}, {"iyr", validate_iyr}, {"eyr", validate_eyr},
|
||||
{"hgt", validate_hgt}, {"hcl", validate_hcl}, {"ecl", validate_ecl},
|
||||
{"pid", validate_pid}, {"cid", validate_cid},
|
||||
{"byr", validate_byr}, {"iyr", validate_iyr}, {"eyr", validate_eyr}, {"hgt", validate_hgt},
|
||||
{"hcl", validate_hcl}, {"ecl", validate_ecl}, {"pid", validate_pid}, {"cid", validate_cid},
|
||||
};
|
||||
|
||||
unsigned mandatory_found = 0;
|
||||
for (auto const &kv : found) {
|
||||
for (auto const& kv : found) {
|
||||
if (mandatory.find(kv.first) != mandatory.end()) {
|
||||
++mandatory_found;
|
||||
}
|
||||
auto validator = validators.find(kv.first);
|
||||
if (validator == validators.end()) {
|
||||
std::cout << "Found invalid key: " << kv.first << "\n";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto valid = validator->second(kv.second);
|
||||
if (!valid) {
|
||||
std::cout << "Invalid value for key: " << kv.first << ": " << kv.second
|
||||
<< "\n";
|
||||
std::cout << "Invalid value for key: " << kv.first << ": " << kv.second << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -165,17 +166,18 @@ bool is_valid_passport(StringMap const &found) {
|
||||
|
||||
return mandatory_found == mandatory.size();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
StringMap found;
|
||||
unsigned valid = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
if (!line.empty()) {
|
||||
auto keys = parse_line(line);
|
||||
found.insert(keys.begin(), keys.end());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
valid += is_valid_passport(found);
|
||||
found.clear();
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
* \param s String to parse, must be L2 characters long
|
||||
* \return Position described by s.
|
||||
*/
|
||||
template <unsigned L2, char LOWER, char UPPER>
|
||||
unsigned find_pos(std::string const &s) {
|
||||
template<unsigned L2, char LOWER, char UPPER>
|
||||
unsigned find_pos(std::string const& s)
|
||||
{
|
||||
assert(s.length() == L2);
|
||||
unsigned low = 0;
|
||||
unsigned high = 1 << L2;
|
||||
@@ -20,9 +21,11 @@ unsigned find_pos(std::string const &s) {
|
||||
assert(width != 0);
|
||||
if (c == LOWER) {
|
||||
high = low + width;
|
||||
} else if (c == UPPER) {
|
||||
}
|
||||
else if (c == UPPER) {
|
||||
low = low + width;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
width >>= 1;
|
||||
@@ -32,13 +35,15 @@ unsigned find_pos(std::string const &s) {
|
||||
return low;
|
||||
}
|
||||
|
||||
template <unsigned L2R, unsigned L2C> struct Seat {
|
||||
Seat(std::string const &s) {
|
||||
template<unsigned L2R, unsigned L2C>
|
||||
struct Seat
|
||||
{
|
||||
Seat(std::string const& s)
|
||||
{
|
||||
assert(s.length() == L2R + L2C);
|
||||
row_ = find_pos<L2R, 'F', 'B'>(s.substr(0, L2R));
|
||||
col_ = find_pos<L2C, 'L', 'R'>(s.substr(L2R, L2C));
|
||||
std::cout << s << ": row " << row_ << ", column " << col_ << ", seat ID "
|
||||
<< id() << ".\n";
|
||||
std::cout << s << ": row " << row_ << ", column " << col_ << ", seat ID " << id() << ".\n";
|
||||
}
|
||||
|
||||
unsigned id() const noexcept { return row_ * (1 << L2C) + col_; }
|
||||
@@ -47,7 +52,8 @@ template <unsigned L2R, unsigned L2C> struct Seat {
|
||||
unsigned col_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned max_id = 0;
|
||||
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
* We don't need to keep a record of high at all so the original solution
|
||||
* was over enthusiastic.
|
||||
*/
|
||||
template <unsigned L2, char LOWER, char UPPER>
|
||||
unsigned find_pos(std::string const &s) {
|
||||
template<unsigned L2, char LOWER, char UPPER>
|
||||
unsigned find_pos(std::string const& s)
|
||||
{
|
||||
assert(s.length() == L2);
|
||||
unsigned low = 0;
|
||||
unsigned width = 1 << (L2 - 1);
|
||||
@@ -25,7 +26,8 @@ unsigned find_pos(std::string const &s) {
|
||||
assert(width != 0);
|
||||
if (c == UPPER) {
|
||||
low = low + width;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(c == LOWER);
|
||||
}
|
||||
|
||||
@@ -40,8 +42,9 @@ unsigned find_pos(std::string const &s) {
|
||||
* \tparam L2R log 2 number of rows
|
||||
* \tparam L2C log 2 number of columns
|
||||
*/
|
||||
template <unsigned L2R, unsigned L2C> struct Seat {
|
||||
|
||||
template<unsigned L2R, unsigned L2C>
|
||||
struct Seat
|
||||
{
|
||||
/** \brief Construct the seat.
|
||||
* \param s String representing seat location, must be L2R + L2C chars.
|
||||
*
|
||||
@@ -52,19 +55,19 @@ template <unsigned L2R, unsigned L2C> struct Seat {
|
||||
*
|
||||
* Should have used initialiser lists.
|
||||
*/
|
||||
Seat(std::string const &s)
|
||||
Seat(std::string const& s)
|
||||
: row_(find_pos<L2R, 'F', 'B'>(s.substr(0, L2R))),
|
||||
col_(find_pos<L2C, 'L', 'R'>(s.substr(L2R, L2C))) {
|
||||
col_(find_pos<L2C, 'L', 'R'>(s.substr(L2R, L2C)))
|
||||
{
|
||||
assert(s.length() == L2R + L2C);
|
||||
std::cout << s << ": row " << row_ << ", column " << col_ << ", seat ID "
|
||||
<< id() << ".\n";
|
||||
std::cout << s << ": row " << row_ << ", column " << col_ << ", seat ID " << id() << ".\n";
|
||||
}
|
||||
|
||||
/** Get seat ID. */
|
||||
unsigned id() const noexcept { return row_ * (1 << L2C) + col_; }
|
||||
|
||||
unsigned row_; ///< Seat row
|
||||
unsigned col_; ///< Seat column
|
||||
unsigned row_; ///< Seat row
|
||||
unsigned col_; ///< Seat column
|
||||
};
|
||||
|
||||
/** \brief main
|
||||
@@ -73,11 +76,12 @@ template <unsigned L2R, unsigned L2C> struct Seat {
|
||||
*
|
||||
* Could have initialised the array better.
|
||||
*/
|
||||
int main(int argc, char **argv) {
|
||||
constexpr unsigned l2r = 7; ///< Log 2 number of rows
|
||||
constexpr unsigned l2c = 3; ///< Log 2 number of columns
|
||||
constexpr unsigned max_id = 1 << (l2r + l2c); ///< Max ID.
|
||||
std::array<bool, max_id> id_present = {}; ///< Is the ID present?
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
constexpr unsigned l2r = 7; ///< Log 2 number of rows
|
||||
constexpr unsigned l2c = 3; ///< Log 2 number of columns
|
||||
constexpr unsigned max_id = 1 << (l2r + l2c); ///< Max ID.
|
||||
std::array<bool, max_id> id_present = {}; ///< Is the ID present?
|
||||
|
||||
// Read the lines in marking IDs that are present
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
// Merge two strings of answers, preserving order and ensuring uniqueness of
|
||||
// each answer.
|
||||
std::string merge_answers(std::string const &a, std::string const &b) {
|
||||
std::string merge_answers(std::string const& a, std::string const& b)
|
||||
{
|
||||
std::string result;
|
||||
std::string::size_type pos_a = 0;
|
||||
std::string::size_type pos_b = 0;
|
||||
@@ -13,10 +14,12 @@ std::string merge_answers(std::string const &a, std::string const &b) {
|
||||
if (a[pos_a] < b[pos_b]) {
|
||||
result += a[pos_a];
|
||||
++pos_a;
|
||||
} else if (b[pos_b] < a[pos_a]) {
|
||||
}
|
||||
else if (b[pos_b] < a[pos_a]) {
|
||||
result += b[pos_b];
|
||||
++pos_b;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(a[pos_a] == b[pos_b]);
|
||||
result += a[pos_a];
|
||||
++pos_a;
|
||||
@@ -29,23 +32,22 @@ std::string merge_answers(std::string const &a, std::string const &b) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string current_answers;
|
||||
unsigned count = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
if (!line.empty()) {
|
||||
std::sort(line.begin(), line.end());
|
||||
current_answers = merge_answers(current_answers, line);
|
||||
} else {
|
||||
std::cout << "Length of " << current_answers << " = "
|
||||
<< current_answers.length() << "\n";
|
||||
}
|
||||
else {
|
||||
std::cout << "Length of " << current_answers << " = " << current_answers.length() << "\n";
|
||||
count += current_answers.length();
|
||||
current_answers.clear();
|
||||
}
|
||||
}
|
||||
std::cout << "Length of " << current_answers << " = "
|
||||
<< current_answers.length() << "\n";
|
||||
std::cout << "Length of " << current_answers << " = " << current_answers.length() << "\n";
|
||||
count += current_answers.length();
|
||||
|
||||
std::cout << "Total length = " << count << "\n";
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
|
||||
using OccuranceMap = std::map<char, unsigned>;
|
||||
|
||||
struct GroupAnswers {
|
||||
void add_answers(std::string const &a) {
|
||||
struct GroupAnswers
|
||||
{
|
||||
void add_answers(std::string const& a)
|
||||
{
|
||||
// Increase group size
|
||||
++group_size_;
|
||||
|
||||
@@ -16,14 +18,16 @@ struct GroupAnswers {
|
||||
auto it = map_.find(c);
|
||||
if (it == map_.end()) {
|
||||
map_.insert({c, 1});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
++(it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Count the number of answered questions answered by everyone.
|
||||
unsigned all_answer_count() const noexcept {
|
||||
unsigned all_answer_count() const noexcept
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (auto kv : map_) {
|
||||
if (kv.second == group_size_) {
|
||||
@@ -34,7 +38,8 @@ struct GroupAnswers {
|
||||
return count;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
void clear()
|
||||
{
|
||||
map_.clear();
|
||||
group_size_ = 0;
|
||||
}
|
||||
@@ -43,13 +48,15 @@ struct GroupAnswers {
|
||||
unsigned group_size_ = 0;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
GroupAnswers answers;
|
||||
unsigned count = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
if (!line.empty()) {
|
||||
answers.add_answers(line);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
count += answers.all_answer_count();
|
||||
answers.clear();
|
||||
}
|
||||
|
||||
@@ -15,10 +15,11 @@ using Weight = unsigned;
|
||||
using EdgeWeights = std::map<Edge, Weight>;
|
||||
using NodeQueue = std::list<Node>;
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, NodeQueue const &q) {
|
||||
std::ostream& operator<<(std::ostream& os, NodeQueue const& q)
|
||||
{
|
||||
std::string p = "";
|
||||
os << "[";
|
||||
for (auto const &n : q) {
|
||||
for (auto const& n : q) {
|
||||
os << p << n;
|
||||
p = ", ";
|
||||
}
|
||||
@@ -26,10 +27,12 @@ std::ostream &operator<<(std::ostream &os, NodeQueue const &q) {
|
||||
return os;
|
||||
}
|
||||
|
||||
struct BagGraph {
|
||||
struct BagGraph
|
||||
{
|
||||
BagGraph() { nodes_.insert({"", false}); }
|
||||
|
||||
void add_edges(std::string const &s) {
|
||||
void add_edges(std::string const& s)
|
||||
{
|
||||
static const auto prefix_re = std::regex("([a-z ]+) bags? contain ");
|
||||
static const auto suffix_re = std::regex("(\\d)+ ([a-z ]+) bags?[,.]\\s*");
|
||||
static const auto empty_str = std::string("no other bags.");
|
||||
@@ -49,7 +52,8 @@ struct BagGraph {
|
||||
Edge e = std::make_pair("", n2);
|
||||
edges_.insert({e, 0});
|
||||
std::cout << "<none> -> " << n2 << ": 0\n";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::smatch suffix_m;
|
||||
if (!std::regex_search(suffix, suffix_m, suffix_re)) {
|
||||
std::cout << "Failed to match: " << suffix << "\n";
|
||||
@@ -67,7 +71,8 @@ struct BagGraph {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned num_containers(Node const &n) {
|
||||
unsigned num_containers(Node const& n)
|
||||
{
|
||||
NodeQueue queue;
|
||||
// Initial population of queue:
|
||||
populate_queue(queue, n);
|
||||
@@ -84,7 +89,8 @@ struct BagGraph {
|
||||
populate_queue(queue, n1);
|
||||
++visited;
|
||||
std::cout << "Updated queue: " << queue << "\n";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << "Already visited\n";
|
||||
}
|
||||
}
|
||||
@@ -93,8 +99,9 @@ struct BagGraph {
|
||||
}
|
||||
|
||||
private:
|
||||
void populate_queue(NodeQueue &queue, Node const &n) {
|
||||
for (auto const &kv : edges_) {
|
||||
void populate_queue(NodeQueue& queue, Node const& n)
|
||||
{
|
||||
for (auto const& kv : edges_) {
|
||||
if (kv.first.first == n && !nodes_[kv.first.second]) {
|
||||
queue.push_back(kv.first.second);
|
||||
}
|
||||
@@ -105,7 +112,8 @@ private:
|
||||
Nodes nodes_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
BagGraph bg;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
bg.add_edges(line);
|
||||
|
||||
@@ -13,8 +13,10 @@ using Edge = std::pair<Node, Node>;
|
||||
using Weight = unsigned;
|
||||
using EdgeWeights = std::map<Edge, Weight>;
|
||||
|
||||
struct BagGraph {
|
||||
void add_edges(std::string const &s) {
|
||||
struct BagGraph
|
||||
{
|
||||
void add_edges(std::string const& s)
|
||||
{
|
||||
static const auto prefix_re = std::regex("([a-z ]+) bags? contain ");
|
||||
static const auto suffix_re = std::regex("(\\d)+ ([a-z ]+) bags?[,.]\\s*");
|
||||
static const auto empty_str = std::string("no other bags.");
|
||||
@@ -31,7 +33,8 @@ struct BagGraph {
|
||||
if (suffix == empty_str) {
|
||||
std::cout << n1 << " -> none: <empty>\n";
|
||||
suffix.clear();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::smatch suffix_m;
|
||||
if (!std::regex_search(suffix, suffix_m, suffix_re)) {
|
||||
std::cout << "Failed to match: " << suffix << "\n";
|
||||
@@ -48,17 +51,19 @@ struct BagGraph {
|
||||
}
|
||||
}
|
||||
|
||||
Weight num_contained(Node const &n) {
|
||||
Weight num_contained(Node const& n)
|
||||
{
|
||||
// Get the number of bags including the node we've been asked for so the
|
||||
// result is 1 less than the internal result
|
||||
return num_contained1(n) - 1;
|
||||
}
|
||||
|
||||
private:
|
||||
Weight num_contained1(Node const &n) {
|
||||
Weight num_contained1(Node const& n)
|
||||
{
|
||||
Weight w = 0;
|
||||
bool contains_something = false;
|
||||
for (auto const &kv : edges_) {
|
||||
for (auto const& kv : edges_) {
|
||||
if (kv.first.first == n) {
|
||||
w += kv.second * num_contained1(kv.first.second);
|
||||
contains_something = true;
|
||||
@@ -70,7 +75,8 @@ private:
|
||||
EdgeWeights edges_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
BagGraph bg;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
bg.add_edges(line);
|
||||
|
||||
@@ -9,36 +9,43 @@
|
||||
enum class Opcode { Acc, Jmp, Nop };
|
||||
using Value = int;
|
||||
|
||||
struct Instruction {
|
||||
Instruction(std::string const &s)
|
||||
: op_(to_opcode(s.substr(0, 3))), v_(to_value(s.substr(4))) {}
|
||||
struct Instruction
|
||||
{
|
||||
Instruction(std::string const& s) : op_(to_opcode(s.substr(0, 3))), v_(to_value(s.substr(4))) {}
|
||||
|
||||
Opcode opcode() const noexcept { return op_; }
|
||||
Value value() const noexcept { return v_; }
|
||||
|
||||
private:
|
||||
Opcode to_opcode(std::string const &s) {
|
||||
Opcode to_opcode(std::string const& s)
|
||||
{
|
||||
if (s == "acc") {
|
||||
return Opcode::Acc;
|
||||
} else if (s == "jmp") {
|
||||
}
|
||||
else if (s == "jmp") {
|
||||
return Opcode::Jmp;
|
||||
} else if (s == "nop") {
|
||||
}
|
||||
else if (s == "nop") {
|
||||
return Opcode::Nop;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
return Opcode::Nop;
|
||||
}
|
||||
}
|
||||
|
||||
Value to_value(std::string const &s) {
|
||||
Value to_value(std::string const& s)
|
||||
{
|
||||
int sign = 0;
|
||||
int v = 0;
|
||||
std::size_t pos = 0;
|
||||
if (s[0] == '+') {
|
||||
sign = 1;
|
||||
} else if (s[0] == '-') {
|
||||
}
|
||||
else if (s[0] == '-') {
|
||||
sign = -1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
v = std::stoi(s.substr(1), &pos);
|
||||
@@ -50,7 +57,8 @@ private:
|
||||
Value v_;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, Instruction const &i) {
|
||||
std::ostream& operator<<(std::ostream& os, Instruction const& i)
|
||||
{
|
||||
switch (i.opcode()) {
|
||||
case Opcode::Acc:
|
||||
os << "acc";
|
||||
@@ -74,15 +82,18 @@ std::ostream &operator<<(std::ostream &os, Instruction const &i) {
|
||||
}
|
||||
using Instructions = std::vector<Instruction>;
|
||||
|
||||
struct VM {
|
||||
struct VM
|
||||
{
|
||||
VM() : pc_(0), acc_(0) {}
|
||||
|
||||
void add_instruction(Instruction const &i) {
|
||||
void add_instruction(Instruction const& i)
|
||||
{
|
||||
std::cout << i << "\n";
|
||||
instrs_.push_back(i);
|
||||
}
|
||||
|
||||
void execute() {
|
||||
void execute()
|
||||
{
|
||||
std::vector<bool> seen(instrs_.size(), false);
|
||||
while (!seen[pc_]) {
|
||||
assert(pc_ < instrs_.size());
|
||||
@@ -96,7 +107,8 @@ struct VM {
|
||||
Value acc() const noexcept { return acc_; }
|
||||
|
||||
private:
|
||||
void execute(Instruction const &i) {
|
||||
void execute(Instruction const& i)
|
||||
{
|
||||
std::cout << pc_ << ": " << i;
|
||||
switch (i.opcode()) {
|
||||
case Opcode::Acc:
|
||||
@@ -120,7 +132,8 @@ private:
|
||||
Value acc_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
VM vm;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
vm.add_instruction(Instruction(line));
|
||||
|
||||
@@ -9,13 +9,14 @@
|
||||
enum class Opcode { Acc, Jmp, Nop };
|
||||
using Value = int;
|
||||
|
||||
struct Instruction {
|
||||
Instruction(std::string const &s)
|
||||
: op_(to_opcode(s.substr(0, 3))), v_(to_value(s.substr(4))) {}
|
||||
struct Instruction
|
||||
{
|
||||
Instruction(std::string const& s) : op_(to_opcode(s.substr(0, 3))), v_(to_value(s.substr(4))) {}
|
||||
|
||||
Opcode opcode() const noexcept { return op_; }
|
||||
Value value() const noexcept { return v_; }
|
||||
bool flip_jmp() {
|
||||
bool flip_jmp()
|
||||
{
|
||||
switch (op_) {
|
||||
case Opcode::Acc:
|
||||
return false;
|
||||
@@ -31,28 +32,35 @@ struct Instruction {
|
||||
}
|
||||
|
||||
private:
|
||||
Opcode to_opcode(std::string const &s) {
|
||||
Opcode to_opcode(std::string const& s)
|
||||
{
|
||||
if (s == "acc") {
|
||||
return Opcode::Acc;
|
||||
} else if (s == "jmp") {
|
||||
}
|
||||
else if (s == "jmp") {
|
||||
return Opcode::Jmp;
|
||||
} else if (s == "nop") {
|
||||
}
|
||||
else if (s == "nop") {
|
||||
return Opcode::Nop;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
return Opcode::Nop;
|
||||
}
|
||||
}
|
||||
|
||||
Value to_value(std::string const &s) {
|
||||
Value to_value(std::string const& s)
|
||||
{
|
||||
int sign = 0;
|
||||
int v = 0;
|
||||
std::size_t pos = 0;
|
||||
if (s[0] == '+') {
|
||||
sign = 1;
|
||||
} else if (s[0] == '-') {
|
||||
}
|
||||
else if (s[0] == '-') {
|
||||
sign = -1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
v = std::stoi(s.substr(1), &pos);
|
||||
@@ -64,7 +72,8 @@ private:
|
||||
Value v_;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, Instruction const &i) {
|
||||
std::ostream& operator<<(std::ostream& os, Instruction const& i)
|
||||
{
|
||||
switch (i.opcode()) {
|
||||
case Opcode::Acc:
|
||||
os << "acc";
|
||||
@@ -88,15 +97,18 @@ std::ostream &operator<<(std::ostream &os, Instruction const &i) {
|
||||
}
|
||||
using Instructions = std::vector<Instruction>;
|
||||
|
||||
struct VM {
|
||||
struct VM
|
||||
{
|
||||
VM() : pc_(0), acc_(0) {}
|
||||
|
||||
void add_instruction(Instruction const &i) {
|
||||
void add_instruction(Instruction const& i)
|
||||
{
|
||||
std::cout << i << "\n";
|
||||
instrs_.push_back(i);
|
||||
}
|
||||
|
||||
bool execute() {
|
||||
bool execute()
|
||||
{
|
||||
std::vector<bool> seen(instrs_.size(), false);
|
||||
acc_ = 0;
|
||||
pc_ = 0;
|
||||
@@ -114,12 +126,12 @@ struct VM {
|
||||
return false;
|
||||
}
|
||||
|
||||
void find_fix() {
|
||||
void find_fix()
|
||||
{
|
||||
for (std::size_t pos = 0; pos < instrs_.size(); ++pos) {
|
||||
if (instrs_[pos].flip_jmp()) {
|
||||
if (execute()) {
|
||||
std::cout << "Success at instruction " << pos << ": " << instrs_[pos]
|
||||
<< "\n";
|
||||
std::cout << "Success at instruction " << pos << ": " << instrs_[pos] << "\n";
|
||||
return;
|
||||
}
|
||||
instrs_[pos].flip_jmp();
|
||||
@@ -130,7 +142,8 @@ struct VM {
|
||||
Value acc() const noexcept { return acc_; }
|
||||
|
||||
private:
|
||||
void execute(Instruction const &i) {
|
||||
void execute(Instruction const& i)
|
||||
{
|
||||
std::cout << pc_ << ": " << i;
|
||||
switch (i.opcode()) {
|
||||
case Opcode::Acc:
|
||||
@@ -154,7 +167,8 @@ private:
|
||||
Value acc_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
VM vm;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
vm.add_instruction(Instruction(line));
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
template <std::size_t L> struct Buffer {
|
||||
template<std::size_t L>
|
||||
struct Buffer
|
||||
{
|
||||
Buffer() {}
|
||||
|
||||
bool add_value(std::string const &s) {
|
||||
bool add_value(std::string const& s)
|
||||
{
|
||||
unsigned long i = std::stoul(s);
|
||||
auto size = buf_.size();
|
||||
if (size == L && !valid(i)) {
|
||||
@@ -23,7 +26,8 @@ template <std::size_t L> struct Buffer {
|
||||
}
|
||||
|
||||
private:
|
||||
bool valid(unsigned long v) const {
|
||||
bool valid(unsigned long v) const
|
||||
{
|
||||
assert(buf_.size() == L);
|
||||
for (auto i = buf_.begin(); i != buf_.end(); ++i) {
|
||||
auto j = i;
|
||||
@@ -41,7 +45,8 @@ private:
|
||||
std::list<unsigned long> buf_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Buffer<25> buf;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
if (!buf.add_value(line)) {
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
template <std::size_t L> struct Buffer {
|
||||
template<std::size_t L>
|
||||
struct Buffer
|
||||
{
|
||||
Buffer() {}
|
||||
|
||||
bool add_value(std::string const &s) {
|
||||
bool add_value(std::string const& s)
|
||||
{
|
||||
unsigned long i = std::stoul(s);
|
||||
bool result = true;
|
||||
auto size = buf_.size();
|
||||
@@ -20,7 +23,8 @@ template <std::size_t L> struct Buffer {
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned long get_weakness(unsigned long v) {
|
||||
unsigned long get_weakness(unsigned long v)
|
||||
{
|
||||
std::size_t sum_begin = 0;
|
||||
std::size_t sum_end = 0;
|
||||
unsigned long sum = 0;
|
||||
@@ -36,16 +40,15 @@ template <std::size_t L> struct Buffer {
|
||||
++sum_begin;
|
||||
}
|
||||
}
|
||||
std::cout << "sum_begin = " << sum_begin << " sum_end = " << sum_end
|
||||
<< "\n";
|
||||
std::vector<unsigned long> vec(buf_.begin() + sum_begin,
|
||||
buf_.begin() + sum_end);
|
||||
std::cout << "sum_begin = " << sum_begin << " sum_end = " << sum_end << "\n";
|
||||
std::vector<unsigned long> vec(buf_.begin() + sum_begin, buf_.begin() + sum_end);
|
||||
std::sort(vec.begin(), vec.end());
|
||||
return vec[0] + vec[vec.size() - 1];
|
||||
}
|
||||
|
||||
private:
|
||||
bool valid(unsigned long v) const {
|
||||
bool valid(unsigned long v) const
|
||||
{
|
||||
assert(buf_.size() >= L);
|
||||
for (auto i = buf_.size() - 25; i != buf_.size(); ++i) {
|
||||
for (auto j = i + 1; j != buf_.size(); ++j) {
|
||||
@@ -60,7 +63,8 @@ private:
|
||||
std::vector<unsigned long> buf_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Buffer<25> buf;
|
||||
unsigned long invalid = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
using Jolt = unsigned long;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::vector<Jolt> jolts;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
jolts.push_back(std::stoul(line));
|
||||
@@ -26,7 +27,6 @@ int main(int argc, char **argv) {
|
||||
// and the gap to our voltage
|
||||
++gaps[3];
|
||||
|
||||
std::cout << gaps[1] << " * " << gaps[3] << " = " << gaps[1] * gaps[3]
|
||||
<< "\n";
|
||||
std::cout << gaps[1] << " * " << gaps[3] << " = " << gaps[1] * gaps[3] << "\n";
|
||||
return 0;
|
||||
}
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
using Jolt = unsigned long;
|
||||
|
||||
Jolt count_valid_combinations(std::vector<Jolt> const &jolts) {
|
||||
Jolt count_valid_combinations(std::vector<Jolt> const& jolts)
|
||||
{
|
||||
std::vector<Jolt> valid(jolts.size(), 0);
|
||||
valid[jolts.size() - 1] = 1;
|
||||
std::size_t i = jolts.size() - 1;
|
||||
@@ -27,7 +28,8 @@ Jolt count_valid_combinations(std::vector<Jolt> const &jolts) {
|
||||
return valid[0];
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::vector<Jolt> jolts;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
jolts.push_back(std::stoul(line));
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
using Array = std::vector<std::string>;
|
||||
|
||||
char next_state(Array const &a, std::size_t row, std::size_t col) {
|
||||
char next_state(Array const& a, std::size_t row, std::size_t col)
|
||||
{
|
||||
unsigned occupied = 0;
|
||||
if (row > 0) {
|
||||
if (col > 0) {
|
||||
@@ -38,16 +39,19 @@ char next_state(Array const &a, std::size_t row, std::size_t col) {
|
||||
|
||||
if (a[row][col] == 'L' && occupied == 0) {
|
||||
return '#';
|
||||
} else if (a[row][col] == '#' && occupied >= 4) {
|
||||
}
|
||||
else if (a[row][col] == '#' && occupied >= 4) {
|
||||
return 'L';
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return a[row][col];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long count_occupied(Array const &a) {
|
||||
unsigned long count_occupied(Array const& a)
|
||||
{
|
||||
unsigned long count = 0;
|
||||
for (auto const &row : a) {
|
||||
for (auto const& row : a) {
|
||||
for (auto col : row) {
|
||||
count += (col == '#');
|
||||
}
|
||||
@@ -56,7 +60,8 @@ unsigned long count_occupied(Array const &a) {
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned long run_to_steady_state(Array const &a) {
|
||||
unsigned long run_to_steady_state(Array const& a)
|
||||
{
|
||||
Array current = a;
|
||||
bool changed = true;
|
||||
unsigned i = 0;
|
||||
@@ -81,7 +86,8 @@ unsigned long run_to_steady_state(Array const &a) {
|
||||
|
||||
return count_occupied(current);
|
||||
}
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Array array;
|
||||
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
using Array = std::vector<std::string>;
|
||||
|
||||
unsigned search(Array const &a, std::size_t row, std::size_t col, int rd,
|
||||
int cd) {
|
||||
unsigned search(Array const& a, std::size_t row, std::size_t col, int rd, int cd)
|
||||
{
|
||||
int cr = (int)row;
|
||||
int cc = (int)col;
|
||||
while (true) {
|
||||
@@ -36,7 +36,8 @@ unsigned search(Array const &a, std::size_t row, std::size_t col, int rd,
|
||||
assert(false);
|
||||
}
|
||||
|
||||
char next_state(Array const &a, std::size_t row, std::size_t col) {
|
||||
char next_state(Array const& a, std::size_t row, std::size_t col)
|
||||
{
|
||||
unsigned occupied = 0;
|
||||
for (int row_delta = -1; row_delta < 2; ++row_delta) {
|
||||
for (int col_delta = -1; col_delta < 2; ++col_delta) {
|
||||
@@ -46,16 +47,19 @@ char next_state(Array const &a, std::size_t row, std::size_t col) {
|
||||
|
||||
if (a[row][col] == 'L' && occupied == 0) {
|
||||
return '#';
|
||||
} else if (a[row][col] == '#' && occupied >= 5) {
|
||||
}
|
||||
else if (a[row][col] == '#' && occupied >= 5) {
|
||||
return 'L';
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return a[row][col];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long count_occupied(Array const &a) {
|
||||
unsigned long count_occupied(Array const& a)
|
||||
{
|
||||
unsigned long count = 0;
|
||||
for (auto const &row : a) {
|
||||
for (auto const& row : a) {
|
||||
for (auto col : row) {
|
||||
count += (col == '#');
|
||||
}
|
||||
@@ -64,7 +68,8 @@ unsigned long count_occupied(Array const &a) {
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned long run_to_steady_state(Array const &a) {
|
||||
unsigned long run_to_steady_state(Array const& a)
|
||||
{
|
||||
Array current = a;
|
||||
bool changed = true;
|
||||
unsigned i = 0;
|
||||
@@ -89,7 +94,8 @@ unsigned long run_to_steady_state(Array const &a) {
|
||||
|
||||
return count_occupied(current);
|
||||
}
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Array array;
|
||||
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
|
||||
enum class Heading { North = 'N', East = 'E', South = 'S', West = 'W' };
|
||||
|
||||
struct Position {
|
||||
struct Position
|
||||
{
|
||||
Position() : x_(0), y_(0), head_(Heading::East) {}
|
||||
|
||||
void move(std::string const &s) {
|
||||
void move(std::string const& s)
|
||||
{
|
||||
char act = s[0];
|
||||
int dist = std::stoi(s.substr(1));
|
||||
|
||||
@@ -39,7 +41,8 @@ struct Position {
|
||||
std::cout << s << ": (" << x_ << ", " << y_ << ")\n";
|
||||
}
|
||||
|
||||
void move(int dist, Heading head) {
|
||||
void move(int dist, Heading head)
|
||||
{
|
||||
switch (head) {
|
||||
case Heading::North:
|
||||
y_ += dist;
|
||||
@@ -59,7 +62,8 @@ struct Position {
|
||||
}
|
||||
}
|
||||
|
||||
void rotate_left(int deg) {
|
||||
void rotate_left(int deg)
|
||||
{
|
||||
/* We want the rang [-180, 180]. */
|
||||
while (deg < -180) {
|
||||
deg += 360;
|
||||
@@ -85,7 +89,8 @@ struct Position {
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
} else if (deg == 90) {
|
||||
}
|
||||
else if (deg == 90) {
|
||||
switch (head_) {
|
||||
case Heading::North:
|
||||
head_ = Heading::West;
|
||||
@@ -102,7 +107,8 @@ struct Position {
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
} else if (deg == 180 || deg == -180) {
|
||||
}
|
||||
else if (deg == 180 || deg == -180) {
|
||||
switch (head_) {
|
||||
case Heading::North:
|
||||
head_ = Heading::South;
|
||||
@@ -119,7 +125,8 @@ struct Position {
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
} else if (deg != 0) {
|
||||
}
|
||||
else if (deg != 0) {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
@@ -131,7 +138,8 @@ struct Position {
|
||||
Heading head_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Position pos;
|
||||
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
|
||||
enum class Heading { North = 'N', East = 'E', South = 'S', West = 'W' };
|
||||
|
||||
struct Position {
|
||||
struct Position
|
||||
{
|
||||
Position() : x_(0), y_(0), wx_(10), wy_(1), head_(Heading::East) {}
|
||||
|
||||
void move(std::string const &s) {
|
||||
void move(std::string const& s)
|
||||
{
|
||||
char act = s[0];
|
||||
int dist = std::stoi(s.substr(1));
|
||||
|
||||
@@ -37,11 +39,12 @@ struct Position {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
std::cout << s << ": Pos = (" << x_ << ", " << y_ << "), Way = (" << wx_
|
||||
<< ", " << wy_ << ")\n";
|
||||
std::cout << s << ": Pos = (" << x_ << ", " << y_ << "), Way = (" << wx_ << ", " << wy_
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
void move_way(int dist, Heading head) {
|
||||
void move_way(int dist, Heading head)
|
||||
{
|
||||
switch (head) {
|
||||
case Heading::North:
|
||||
wy_ += dist;
|
||||
@@ -61,7 +64,8 @@ struct Position {
|
||||
}
|
||||
}
|
||||
|
||||
void rotate_left(int deg) {
|
||||
void rotate_left(int deg)
|
||||
{
|
||||
/* We want the rang [-180, 180]. */
|
||||
while (deg < -180) {
|
||||
deg += 360;
|
||||
@@ -75,15 +79,18 @@ struct Position {
|
||||
int py = wy_;
|
||||
wx_ = py;
|
||||
wy_ = -px;
|
||||
} else if (deg == 90) {
|
||||
}
|
||||
else if (deg == 90) {
|
||||
int px = wx_;
|
||||
int py = wy_;
|
||||
wx_ = -py;
|
||||
wy_ = px;
|
||||
} else if (deg == 180 || deg == -180) {
|
||||
}
|
||||
else if (deg == 180 || deg == -180) {
|
||||
wx_ = -wx_;
|
||||
wy_ = -wy_;
|
||||
} else if (deg != 0) {
|
||||
}
|
||||
else if (deg != 0) {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
@@ -97,7 +104,8 @@ struct Position {
|
||||
Heading head_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Position pos;
|
||||
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
|
||||
using Time = unsigned long;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Time arrival;
|
||||
Time closest = ULONG_MAX;
|
||||
Time closest_id = 0;
|
||||
@@ -36,8 +37,7 @@ int main(int argc, char **argv) {
|
||||
if (next_departure_in == depart) {
|
||||
next_departure_in = 0;
|
||||
}
|
||||
std::cout << "Bus #" << depart
|
||||
<< " previous departure: " << (arrival / depart) * depart
|
||||
std::cout << "Bus #" << depart << " previous departure: " << (arrival / depart) * depart
|
||||
<< ", next departure in: " << next_departure_in << "\n";
|
||||
if (next_departure_in < closest) {
|
||||
closest = next_departure_in;
|
||||
@@ -45,8 +45,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Next departure # " << closest_id << " in " << closest
|
||||
<< " minutes.\n";
|
||||
std::cout << "Next departure # " << closest_id << " in " << closest << " minutes.\n";
|
||||
std::cout << "Result = " << closest * closest_id << "\n";
|
||||
return 0;
|
||||
}
|
||||
@@ -12,9 +12,10 @@ using Time = unsigned long;
|
||||
using IDPair = std::pair<Time, Time>;
|
||||
using IDVector = std::vector<IDPair>;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
std::getline(std::cin, line); // Ignore first line
|
||||
std::getline(std::cin, line); // Ignore first line
|
||||
|
||||
std::string buses;
|
||||
std::getline(std::cin, buses);
|
||||
@@ -26,7 +27,8 @@ int main(int argc, char **argv) {
|
||||
if (buses[pos] == ',') {
|
||||
++pos;
|
||||
continue;
|
||||
} else if (buses[pos] == 'x') {
|
||||
}
|
||||
else if (buses[pos] == 'x') {
|
||||
++offset;
|
||||
++pos;
|
||||
continue;
|
||||
@@ -43,12 +45,11 @@ int main(int argc, char **argv) {
|
||||
// Make assumption that all bus IDs are co-prime.
|
||||
Time t = 0;
|
||||
Time t_incr = 1;
|
||||
for (auto const &bus : ids) {
|
||||
for (auto const& bus : ids) {
|
||||
while ((t + bus.second) % bus.first != 0) {
|
||||
t += t_incr;
|
||||
}
|
||||
std::cout << "Bus #" << bus.first << " at offset " << bus.second
|
||||
<< " t = " << t << "\n";
|
||||
std::cout << "Bus #" << bus.first << " at offset " << bus.second << " t = " << t << "\n";
|
||||
t_incr *= bus.first;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
using Data = std::uint64_t;
|
||||
using Mem = std::vector<Data>;
|
||||
|
||||
struct Computer {
|
||||
struct Computer
|
||||
{
|
||||
Computer() : set_(0), clear_(0), mem_() {}
|
||||
|
||||
void add_instruction(std::string const &s) {
|
||||
void add_instruction(std::string const& s)
|
||||
{
|
||||
static const std::regex re("mem\\[(\\d+)\\] = (\\d+)");
|
||||
std::smatch m;
|
||||
|
||||
@@ -28,11 +30,12 @@ struct Computer {
|
||||
}
|
||||
std::cout << "mask set: " << std::hex << set_ << "\n";
|
||||
std::cout << "mask clear: " << std::hex << clear_ << "\n";
|
||||
} else if (std::regex_search(s, m, re)) {
|
||||
}
|
||||
else if (std::regex_search(s, m, re)) {
|
||||
Data loc = std::stoul(m.str(1));
|
||||
Data value = std::stoul(m.str(2));
|
||||
std::cout << "mem[" << std::dec << loc << " = (" << value << " | " << set_
|
||||
<< ") & " << clear_ << " = ";
|
||||
std::cout << "mem[" << std::dec << loc << " = (" << value << " | " << set_ << ") & " << clear_
|
||||
<< " = ";
|
||||
value = (value | set_) & clear_;
|
||||
std::cout << value << "\n";
|
||||
if (mem_.size() <= loc) {
|
||||
@@ -42,7 +45,8 @@ struct Computer {
|
||||
}
|
||||
}
|
||||
|
||||
Data mem_sum() const noexcept {
|
||||
Data mem_sum() const noexcept
|
||||
{
|
||||
Data r = 0;
|
||||
for (auto v : mem_) {
|
||||
r += v;
|
||||
@@ -55,7 +59,8 @@ struct Computer {
|
||||
Mem mem_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Computer c;
|
||||
|
||||
std::string line;
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
using Data = std::uint64_t;
|
||||
using Mem = std::map<Data, Data>;
|
||||
|
||||
struct Computer {
|
||||
|
||||
void add_instruction(std::string const &s) {
|
||||
struct Computer
|
||||
{
|
||||
void add_instruction(std::string const& s)
|
||||
{
|
||||
static const std::regex re("mem\\[(\\d+)\\] = (\\d+)");
|
||||
std::smatch m;
|
||||
|
||||
@@ -26,28 +27,29 @@ struct Computer {
|
||||
for (auto c : mask) {
|
||||
if (c == '1') {
|
||||
set_ |= Data(1) << bit;
|
||||
|
||||
} else if (c == 'X') {
|
||||
}
|
||||
else if (c == 'X') {
|
||||
bits_.push_back(std::size_t(1) << bit);
|
||||
std::cout << bit << " (" << (std::size_t(1) << bit) << ") ";
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(c == '0');
|
||||
}
|
||||
++bit;
|
||||
}
|
||||
assert(bit == mask.size());
|
||||
std::cout << " set: 0x" << std::hex << set_ << std::dec << "\n";
|
||||
} else if (std::regex_search(s, m, re)) {
|
||||
}
|
||||
else if (std::regex_search(s, m, re)) {
|
||||
Data loc = std::stoul(m.str(1));
|
||||
Data value = std::stoul(m.str(2));
|
||||
set_mem(loc, value);
|
||||
}
|
||||
}
|
||||
|
||||
void set_mem(Data loc, Data value) {
|
||||
std::cout << "Writing: " << value << " to base loc " << std::hex << loc
|
||||
<< " which floats to:";
|
||||
void set_mem(Data loc, Data value)
|
||||
{
|
||||
std::cout << "Writing: " << value << " to base loc " << std::hex << loc << " which floats to:";
|
||||
for (auto b : bits_) {
|
||||
loc &= ~b;
|
||||
}
|
||||
@@ -67,7 +69,8 @@ struct Computer {
|
||||
std::cout << std::dec << "\n";
|
||||
}
|
||||
|
||||
Data mem_sum() const noexcept {
|
||||
Data mem_sum() const noexcept
|
||||
{
|
||||
Data r = 0;
|
||||
for (auto v : mem_) {
|
||||
r += v.second;
|
||||
@@ -80,7 +83,8 @@ struct Computer {
|
||||
Mem mem_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Computer c;
|
||||
|
||||
std::string line;
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
|
||||
using NumMap = std::map<int, int>;
|
||||
|
||||
int add_to_map(NumMap &nums, int num, int turn) {
|
||||
int add_to_map(NumMap& nums, int num, int turn)
|
||||
{
|
||||
auto [it, success] = nums.insert({num, turn});
|
||||
if (success) {
|
||||
// std::cout << "Turn " << turn << ": " << num << " (new)\n";
|
||||
return 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
int r = turn - it->second;
|
||||
// std::cout << "Turn " << turn << ": " << num << " (previous seen turn "
|
||||
// << it->second << " dist = " << r << ")\n";
|
||||
@@ -23,7 +25,8 @@ int add_to_map(NumMap &nums, int num, int turn) {
|
||||
}
|
||||
}
|
||||
|
||||
int run(std::string const &s, int num_turns) {
|
||||
int run(std::string const& s, int num_turns)
|
||||
{
|
||||
NumMap seen;
|
||||
std::size_t pos = 0;
|
||||
std::size_t len;
|
||||
@@ -47,7 +50,8 @@ int run(std::string const &s, int num_turns) {
|
||||
return next_num;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
int r = run(line, 2020);
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
|
||||
using NumMap = std::unordered_map<int, int>;
|
||||
|
||||
int add_to_map(NumMap &nums, int num, int turn) {
|
||||
int add_to_map(NumMap& nums, int num, int turn)
|
||||
{
|
||||
auto [it, success] = nums.insert({num, turn});
|
||||
if (success) {
|
||||
// std::cout << "Turn " << turn << ": " << num << " (new)\n";
|
||||
return 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
int r = turn - it->second;
|
||||
// std::cout << "Turn " << turn << ": " << num << " (previous seen turn "
|
||||
// << it->second << " dist = " << r << ")\n";
|
||||
@@ -24,7 +26,8 @@ int add_to_map(NumMap &nums, int num, int turn) {
|
||||
}
|
||||
}
|
||||
|
||||
int run(std::string const &s, int num_turns) {
|
||||
int run(std::string const& s, int num_turns)
|
||||
{
|
||||
NumMap seen;
|
||||
std::size_t pos = 0;
|
||||
std::size_t len;
|
||||
@@ -48,7 +51,8 @@ int run(std::string const &s, int num_turns) {
|
||||
return next_num;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
int r = run(line, 30000000);
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
|
||||
using ValidVector = std::vector<bool>;
|
||||
|
||||
struct Classifier {
|
||||
void add_ranges(std::string const &s) {
|
||||
struct Classifier
|
||||
{
|
||||
void add_ranges(std::string const& s)
|
||||
{
|
||||
static const std::regex re("(\\w+): (\\d+)-(\\d+) or (\\d+)-(\\d+)");
|
||||
std::smatch m;
|
||||
if (std::regex_search(s, m, re)) {
|
||||
@@ -22,7 +24,8 @@ struct Classifier {
|
||||
}
|
||||
}
|
||||
|
||||
void add_range(std::string const &lows, std::string const &highs) {
|
||||
void add_range(std::string const& lows, std::string const& highs)
|
||||
{
|
||||
int low = std::stoi(lows);
|
||||
int high = std::stoi(highs);
|
||||
++high;
|
||||
@@ -36,7 +39,8 @@ struct Classifier {
|
||||
}
|
||||
}
|
||||
|
||||
int count_errors(std::string const &s) {
|
||||
int count_errors(std::string const& s)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
int result = 0;
|
||||
while (pos < s.size()) {
|
||||
@@ -59,7 +63,8 @@ struct Classifier {
|
||||
|
||||
enum class State { Permitted, Your, Nearby };
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
|
||||
State s = State::Permitted;
|
||||
@@ -68,13 +73,17 @@ int main(int argc, char **argv) {
|
||||
while (std::getline(std::cin, line)) {
|
||||
if (line == "your ticket:") {
|
||||
s = State::Your;
|
||||
} else if (line == "nearby tickets:") {
|
||||
}
|
||||
else if (line == "nearby tickets:") {
|
||||
s = State::Nearby;
|
||||
} else if (line == "") {
|
||||
}
|
||||
else if (line == "") {
|
||||
/* nothing */;
|
||||
} else if (s == State::Permitted) {
|
||||
}
|
||||
else if (s == State::Permitted) {
|
||||
c.add_ranges(line);
|
||||
} else if (s == State::Nearby) {
|
||||
}
|
||||
else if (s == State::Nearby) {
|
||||
e += c.count_errors(line);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
struct Classifier {
|
||||
void add_ranges(std::string const &s) {
|
||||
struct Classifier
|
||||
{
|
||||
void add_ranges(std::string const& s)
|
||||
{
|
||||
static const std::regex re("(.+): (\\d+)-(\\d+) or (\\d+)-(\\d+)");
|
||||
std::smatch m;
|
||||
if (std::regex_search(s, m, re)) {
|
||||
@@ -22,8 +24,8 @@ struct Classifier {
|
||||
}
|
||||
}
|
||||
|
||||
void add_range(std::string const &lows, std::string const &highs,
|
||||
std::size_t field) {
|
||||
void add_range(std::string const& lows, std::string const& highs, std::size_t field)
|
||||
{
|
||||
int low = std::stoi(lows);
|
||||
int high = std::stoi(highs);
|
||||
++high;
|
||||
@@ -39,13 +41,14 @@ struct Classifier {
|
||||
}
|
||||
}
|
||||
|
||||
void close() {
|
||||
void close()
|
||||
{
|
||||
idx_to_valid_field_.resize(0);
|
||||
idx_to_valid_field_.resize(field_names_.size(),
|
||||
(1 << field_names_.size()) - 1);
|
||||
idx_to_valid_field_.resize(field_names_.size(), (1 << field_names_.size()) - 1);
|
||||
}
|
||||
|
||||
int count_errors(std::string const &s) const {
|
||||
int count_errors(std::string const& s) const
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
int result = 0;
|
||||
while (pos < s.size()) {
|
||||
@@ -64,14 +67,14 @@ struct Classifier {
|
||||
return result;
|
||||
}
|
||||
|
||||
void mark_valid(std::string const &s) {
|
||||
void mark_valid(std::string const& s)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
unsigned idx = 0;
|
||||
while (pos < s.size()) {
|
||||
std::size_t len = 0;
|
||||
int num = std::stoi(s.substr(pos), &len);
|
||||
unsigned valid_fields =
|
||||
num >= num_to_valid_field_.size() ? 0 : num_to_valid_field_[num];
|
||||
unsigned valid_fields = num >= num_to_valid_field_.size() ? 0 : num_to_valid_field_[num];
|
||||
idx_to_valid_field_[idx] &= valid_fields;
|
||||
pos += len;
|
||||
while (pos < s.size() && s[pos] == ',') {
|
||||
@@ -82,12 +85,12 @@ struct Classifier {
|
||||
}
|
||||
}
|
||||
|
||||
void print_valid() const {
|
||||
void print_valid() const
|
||||
{
|
||||
for (std::size_t idx = 0; idx < idx_to_valid_field_.size(); ++idx) {
|
||||
std::cout << "Index " << idx << " valid for fields:";
|
||||
unsigned field = 0;
|
||||
for (auto valid_fields = idx_to_valid_field_[idx]; valid_fields != 0;
|
||||
valid_fields >>= 1) {
|
||||
for (auto valid_fields = idx_to_valid_field_[idx]; valid_fields != 0; valid_fields >>= 1) {
|
||||
if (valid_fields & 1) {
|
||||
std::cout << " " << field_names_[field];
|
||||
}
|
||||
@@ -97,15 +100,15 @@ struct Classifier {
|
||||
}
|
||||
}
|
||||
|
||||
void reduce() {
|
||||
void reduce()
|
||||
{
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
for (unsigned idx = 0; idx < idx_to_valid_field_.size(); ++idx) {
|
||||
auto valid_fields = idx_to_valid_field_[idx];
|
||||
if ((valid_fields & (valid_fields - 1)) == 0) {
|
||||
std::cout << "Index " << idx << " can only be field " << valid_fields
|
||||
<< "\n";
|
||||
std::cout << "Index " << idx << " can only be field " << valid_fields << "\n";
|
||||
for (unsigned idx2 = 0; idx2 < idx_to_valid_field_.size(); ++idx2) {
|
||||
if (idx == idx2) {
|
||||
continue;
|
||||
@@ -118,14 +121,15 @@ struct Classifier {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long calculate_product(std::string const &s,
|
||||
std::string const &prefix) {
|
||||
unsigned long calculate_product(std::string const& s, std::string const& prefix)
|
||||
{
|
||||
std::vector<unsigned> values;
|
||||
std::size_t pos = 0;
|
||||
while (pos < s.size()) {
|
||||
if (s[pos] == ',') {
|
||||
++pos;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::size_t len;
|
||||
values.push_back(std::stoi(s.substr(pos), &len));
|
||||
pos += len;
|
||||
@@ -136,8 +140,7 @@ struct Classifier {
|
||||
for (unsigned field = 0; field < field_names_.size(); ++field) {
|
||||
if (field_names_[field].substr(0, prefix.size()) == prefix) {
|
||||
unsigned idx = 0;
|
||||
while (idx < idx_to_valid_field_.size() &&
|
||||
idx_to_valid_field_[idx] != (1 << field)) {
|
||||
while (idx < idx_to_valid_field_.size() && idx_to_valid_field_[idx] != (1 << field)) {
|
||||
++idx;
|
||||
}
|
||||
assert(idx < idx_to_valid_field_.size());
|
||||
@@ -155,7 +158,8 @@ struct Classifier {
|
||||
|
||||
enum class State { Permitted, Your, Nearby };
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
|
||||
State s = State::Permitted;
|
||||
@@ -165,16 +169,21 @@ int main(int argc, char **argv) {
|
||||
while (std::getline(std::cin, line)) {
|
||||
if (line == "your ticket:") {
|
||||
s = State::Your;
|
||||
} else if (line == "nearby tickets:") {
|
||||
}
|
||||
else if (line == "nearby tickets:") {
|
||||
s = State::Nearby;
|
||||
c.close();
|
||||
} else if (line == "") {
|
||||
}
|
||||
else if (line == "") {
|
||||
/* nothing */;
|
||||
} else if (s == State::Permitted) {
|
||||
}
|
||||
else if (s == State::Permitted) {
|
||||
c.add_ranges(line);
|
||||
} else if (s == State::Your) {
|
||||
}
|
||||
else if (s == State::Your) {
|
||||
our_ticket = line;
|
||||
} else if (s == State::Nearby) {
|
||||
}
|
||||
else if (s == State::Nearby) {
|
||||
auto e2 = c.count_errors(line);
|
||||
e += e2;
|
||||
if (e2 == 0) {
|
||||
@@ -187,7 +196,6 @@ int main(int argc, char **argv) {
|
||||
c.reduce();
|
||||
c.print_valid();
|
||||
|
||||
std::cout << "Product: " << c.calculate_product(our_ticket, "departure ")
|
||||
<< "\n";
|
||||
std::cout << "Product: " << c.calculate_product(our_ticket, "departure ") << "\n";
|
||||
return 0;
|
||||
}
|
||||
@@ -9,13 +9,15 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
struct ConwayCubeState {
|
||||
struct ConwayCubeState
|
||||
{
|
||||
using Point = std::tuple<int, int, int>;
|
||||
using PointSet = std::set<Point>;
|
||||
using NeighbourMap = std::map<Point, unsigned>;
|
||||
|
||||
ConwayCubeState() : next_row_(0) {}
|
||||
void add_row(std::string const &s) {
|
||||
void add_row(std::string const& s)
|
||||
{
|
||||
for (int x = 0; x < s.size(); ++x) {
|
||||
if (s[x] == '#') {
|
||||
set_point(x, next_row_, 0);
|
||||
@@ -24,13 +26,15 @@ struct ConwayCubeState {
|
||||
++next_row_;
|
||||
}
|
||||
|
||||
ConwayCubeState next_state() const {
|
||||
ConwayCubeState next_state() const
|
||||
{
|
||||
ConwayCubeState next;
|
||||
for (auto const &n : neighbours_) {
|
||||
for (auto const& n : neighbours_) {
|
||||
bool active = points_.find(n.first) != points_.end();
|
||||
if (active && (n.second == 2 || n.second == 3)) {
|
||||
next.set_point(n.first);
|
||||
} else if (!active && n.second == 3) {
|
||||
}
|
||||
else if (!active && n.second == 3) {
|
||||
next.set_point(n.first);
|
||||
}
|
||||
}
|
||||
@@ -41,11 +45,10 @@ struct ConwayCubeState {
|
||||
auto active() const { return points_.size(); }
|
||||
|
||||
private:
|
||||
void set_point(Point const &pt) {
|
||||
set_point(std::get<0>(pt), std::get<1>(pt), std::get<2>(pt));
|
||||
}
|
||||
void set_point(Point const& pt) { set_point(std::get<0>(pt), std::get<1>(pt), std::get<2>(pt)); }
|
||||
|
||||
void set_point(int px, int py, int pz) {
|
||||
void set_point(int px, int py, int pz)
|
||||
{
|
||||
points_.insert({px, py, pz});
|
||||
|
||||
for (int x = px - 1; x < px + 2; ++x) {
|
||||
@@ -69,7 +72,8 @@ private:
|
||||
NeighbourMap neighbours_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
ConwayCubeState state;
|
||||
while (std::getline(std::cin, line)) {
|
||||
|
||||
@@ -9,13 +9,15 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
struct ConwayCubeState {
|
||||
struct ConwayCubeState
|
||||
{
|
||||
using Point = std::tuple<int, int, int, int>;
|
||||
using PointSet = std::set<Point>;
|
||||
using NeighbourMap = std::map<Point, unsigned>;
|
||||
|
||||
ConwayCubeState() : next_row_(0) {}
|
||||
void add_row(std::string const &s) {
|
||||
void add_row(std::string const& s)
|
||||
{
|
||||
for (int x = 0; x < s.size(); ++x) {
|
||||
if (s[x] == '#') {
|
||||
set_point(x, next_row_, 0, 0);
|
||||
@@ -24,13 +26,15 @@ struct ConwayCubeState {
|
||||
++next_row_;
|
||||
}
|
||||
|
||||
ConwayCubeState next_state() const {
|
||||
ConwayCubeState next_state() const
|
||||
{
|
||||
ConwayCubeState next;
|
||||
for (auto const &n : neighbours_) {
|
||||
for (auto const& n : neighbours_) {
|
||||
bool active = points_.find(n.first) != points_.end();
|
||||
if (active && (n.second == 2 || n.second == 3)) {
|
||||
next.set_point(n.first);
|
||||
} else if (!active && n.second == 3) {
|
||||
}
|
||||
else if (!active && n.second == 3) {
|
||||
next.set_point(n.first);
|
||||
}
|
||||
}
|
||||
@@ -41,12 +45,13 @@ struct ConwayCubeState {
|
||||
auto active() const { return points_.size(); }
|
||||
|
||||
private:
|
||||
void set_point(Point const &pt) {
|
||||
set_point(std::get<0>(pt), std::get<1>(pt), std::get<2>(pt),
|
||||
std::get<3>(pt));
|
||||
void set_point(Point const& pt)
|
||||
{
|
||||
set_point(std::get<0>(pt), std::get<1>(pt), std::get<2>(pt), std::get<3>(pt));
|
||||
}
|
||||
|
||||
void set_point(int pw, int px, int py, int pz) {
|
||||
void set_point(int pw, int px, int py, int pz)
|
||||
{
|
||||
points_.insert({pw, px, py, pz});
|
||||
|
||||
for (int w = pw - 1; w < pw + 2; ++w) {
|
||||
@@ -72,7 +77,8 @@ private:
|
||||
NeighbourMap neighbours_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
ConwayCubeState state;
|
||||
while (std::getline(std::cin, line)) {
|
||||
|
||||
@@ -9,46 +9,46 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
enum class Token : char {
|
||||
Eof,
|
||||
Number,
|
||||
LParens = '(',
|
||||
RParens = ')',
|
||||
Add = '+',
|
||||
Multiply = '*'
|
||||
};
|
||||
enum class Token : char { Eof, Number, LParens = '(', RParens = ')', Add = '+', Multiply = '*' };
|
||||
using Value = unsigned long;
|
||||
|
||||
struct Parser {
|
||||
Parser(std::string const &s) : expr_(s), pos_(0) { skip_whitespace(); }
|
||||
struct Parser
|
||||
{
|
||||
Parser(std::string const& s) : expr_(s), pos_(0) { skip_whitespace(); }
|
||||
|
||||
Value evaluate() { return binop(); }
|
||||
|
||||
private:
|
||||
Value binop() {
|
||||
Value binop()
|
||||
{
|
||||
auto value = primary();
|
||||
do {
|
||||
if (peek() == Token::Add) {
|
||||
chew(Token::Add);
|
||||
value += primary();
|
||||
} else if (peek() == Token::Multiply) {
|
||||
}
|
||||
else if (peek() == Token::Multiply) {
|
||||
chew(Token::Multiply);
|
||||
value *= primary();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
Value primary() {
|
||||
Value primary()
|
||||
{
|
||||
if (peek() == Token::LParens) {
|
||||
chew(Token::LParens);
|
||||
Value value = binop();
|
||||
chew(Token::RParens);
|
||||
return value;
|
||||
} else if (peek() == Token::Number) {
|
||||
}
|
||||
else if (peek() == Token::Number) {
|
||||
return chew_number();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << "expr_ = " << expr_ << "\n";
|
||||
std::cout << "pos_ = " << pos_ << "\n";
|
||||
std::cout << "End = " << expr_.substr(pos_) << "\n";
|
||||
@@ -56,7 +56,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
Token peek() {
|
||||
Token peek()
|
||||
{
|
||||
if (pos_ == expr_.size()) {
|
||||
return Token::Eof;
|
||||
}
|
||||
@@ -89,7 +90,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void chew(Token tok) {
|
||||
void chew(Token tok)
|
||||
{
|
||||
assert(peek() == tok);
|
||||
switch (tok) {
|
||||
case Token::LParens:
|
||||
@@ -104,13 +106,15 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void skip_whitespace() {
|
||||
void skip_whitespace()
|
||||
{
|
||||
while (pos_ < expr_.size() && expr_[pos_] == ' ') {
|
||||
++pos_;
|
||||
}
|
||||
}
|
||||
|
||||
Value chew_number() {
|
||||
Value chew_number()
|
||||
{
|
||||
assert(peek() == Token::Number);
|
||||
|
||||
std::size_t len = 0;
|
||||
@@ -124,7 +128,8 @@ private:
|
||||
std::string::size_type pos_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
Value result = 0;
|
||||
while (std::getline(std::cin, line)) {
|
||||
|
||||
@@ -9,55 +9,56 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
enum class Token : char {
|
||||
Eof,
|
||||
Number,
|
||||
LParens = '(',
|
||||
RParens = ')',
|
||||
Add = '+',
|
||||
Multiply = '*'
|
||||
};
|
||||
enum class Token : char { Eof, Number, LParens = '(', RParens = ')', Add = '+', Multiply = '*' };
|
||||
using Value = unsigned long;
|
||||
|
||||
struct Parser {
|
||||
Parser(std::string const &s) : expr_(s), pos_(0) { skip_whitespace(); }
|
||||
struct Parser
|
||||
{
|
||||
Parser(std::string const& s) : expr_(s), pos_(0) { skip_whitespace(); }
|
||||
|
||||
Value evaluate() { return multop(); }
|
||||
|
||||
private:
|
||||
Value addop() {
|
||||
Value addop()
|
||||
{
|
||||
auto value = primary();
|
||||
do {
|
||||
if (peek() == Token::Add) {
|
||||
chew(Token::Add);
|
||||
value += primary();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
Value multop() {
|
||||
Value multop()
|
||||
{
|
||||
auto value = addop();
|
||||
do {
|
||||
if (peek() == Token::Multiply) {
|
||||
chew(Token::Multiply);
|
||||
value *= addop();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
Value primary() {
|
||||
Value primary()
|
||||
{
|
||||
if (peek() == Token::LParens) {
|
||||
chew(Token::LParens);
|
||||
Value value = evaluate();
|
||||
chew(Token::RParens);
|
||||
return value;
|
||||
} else if (peek() == Token::Number) {
|
||||
}
|
||||
else if (peek() == Token::Number) {
|
||||
return chew_number();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << "expr_ = " << expr_ << "\n";
|
||||
std::cout << "pos_ = " << pos_ << "\n";
|
||||
std::cout << "End = " << expr_.substr(pos_) << "\n";
|
||||
@@ -65,7 +66,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
Token peek() {
|
||||
Token peek()
|
||||
{
|
||||
if (pos_ == expr_.size()) {
|
||||
return Token::Eof;
|
||||
}
|
||||
@@ -98,7 +100,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void chew(Token tok) {
|
||||
void chew(Token tok)
|
||||
{
|
||||
assert(peek() == tok);
|
||||
switch (tok) {
|
||||
case Token::LParens:
|
||||
@@ -113,13 +116,15 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void skip_whitespace() {
|
||||
void skip_whitespace()
|
||||
{
|
||||
while (pos_ < expr_.size() && expr_[pos_] == ' ') {
|
||||
++pos_;
|
||||
}
|
||||
}
|
||||
|
||||
Value chew_number() {
|
||||
Value chew_number()
|
||||
{
|
||||
assert(peek() == Token::Number);
|
||||
|
||||
std::size_t len = 0;
|
||||
@@ -133,7 +138,8 @@ private:
|
||||
std::string::size_type pos_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
Value result = 0;
|
||||
while (std::getline(std::cin, line)) {
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
struct Matcher {
|
||||
void add_rule(std::string const &s) {
|
||||
struct Matcher
|
||||
{
|
||||
void add_rule(std::string const& s)
|
||||
{
|
||||
std::size_t len = 0;
|
||||
unsigned long id = std::stoul(s, &len);
|
||||
assert(s[len] == ':');
|
||||
@@ -26,24 +28,25 @@ struct Matcher {
|
||||
|
||||
void calculate_regex() { re_.assign("^" + expand_rule(0) + "$"); }
|
||||
|
||||
bool does_match(std::string const &s) const {
|
||||
return std::regex_match(s, re_);
|
||||
}
|
||||
bool does_match(std::string const& s) const { return std::regex_match(s, re_); }
|
||||
|
||||
private:
|
||||
std::string expand_rule(std::size_t id) {
|
||||
std::string expand_rule(std::size_t id)
|
||||
{
|
||||
std::string re;
|
||||
std::string const &rule = rules_[id];
|
||||
std::string const& rule = rules_[id];
|
||||
std::size_t pos = 0;
|
||||
bool needs_brackets = false;
|
||||
while (pos < rule.size()) {
|
||||
if (rule[pos] == ' ') {
|
||||
++pos;
|
||||
} else if (rule[pos] == '|') {
|
||||
}
|
||||
else if (rule[pos] == '|') {
|
||||
re += "|";
|
||||
needs_brackets = true;
|
||||
++pos;
|
||||
} else if (rule[pos] == '"') {
|
||||
}
|
||||
else if (rule[pos] == '"') {
|
||||
++pos;
|
||||
while (pos < rule.size() && rule[pos] != '"') {
|
||||
re += rule[pos];
|
||||
@@ -52,12 +55,14 @@ private:
|
||||
assert(pos < rule.size());
|
||||
assert(rule[pos] == '"');
|
||||
++pos;
|
||||
} else if (std::isdigit(rule[pos])) {
|
||||
}
|
||||
else if (std::isdigit(rule[pos])) {
|
||||
std::size_t len = 0;
|
||||
std::size_t subid = std::stoul(rule.substr(pos), &len);
|
||||
pos += len;
|
||||
re += expand_rule(subid);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
@@ -73,7 +78,8 @@ private:
|
||||
std::regex re_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
Matcher matcher;
|
||||
bool adding_rules = true;
|
||||
@@ -82,9 +88,11 @@ int main(void) {
|
||||
if (line.empty()) {
|
||||
adding_rules = false;
|
||||
matcher.calculate_regex();
|
||||
} else if (adding_rules) {
|
||||
}
|
||||
else if (adding_rules) {
|
||||
matcher.add_rule(line);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
bool m = matcher.does_match(line);
|
||||
std::cout << line << ": does " << (m ? "" : "not ") << "match\n";
|
||||
matches += m;
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
struct Matcher {
|
||||
void add_rule(std::string const &s) {
|
||||
struct Matcher
|
||||
{
|
||||
void add_rule(std::string const& s)
|
||||
{
|
||||
std::size_t len = 0;
|
||||
unsigned long id = std::stoul(s, &len);
|
||||
assert(s[len] == ':');
|
||||
@@ -24,12 +26,14 @@ struct Matcher {
|
||||
rules_[id] = s.substr(len);
|
||||
}
|
||||
|
||||
void calculate_regex() {
|
||||
void calculate_regex()
|
||||
{
|
||||
re42_ = expand_rule(42);
|
||||
re31_ = expand_rule(31);
|
||||
}
|
||||
|
||||
bool does_match(std::string const &s) const {
|
||||
bool does_match(std::string const& s) const
|
||||
{
|
||||
std::smatch m;
|
||||
std::string begin = "^" + re42_ + re42_;
|
||||
unsigned repeats = 1;
|
||||
@@ -50,19 +54,22 @@ struct Matcher {
|
||||
}
|
||||
|
||||
private:
|
||||
std::string expand_rule(std::size_t id) {
|
||||
std::string expand_rule(std::size_t id)
|
||||
{
|
||||
std::string re;
|
||||
std::string const &rule = rules_[id];
|
||||
std::string const& rule = rules_[id];
|
||||
std::size_t pos = 0;
|
||||
bool needs_brackets = false;
|
||||
while (pos < rule.size()) {
|
||||
if (rule[pos] == ' ') {
|
||||
++pos;
|
||||
} else if (rule[pos] == '|') {
|
||||
}
|
||||
else if (rule[pos] == '|') {
|
||||
re += "|";
|
||||
needs_brackets = true;
|
||||
++pos;
|
||||
} else if (rule[pos] == '"') {
|
||||
}
|
||||
else if (rule[pos] == '"') {
|
||||
++pos;
|
||||
while (pos < rule.size() && rule[pos] != '"') {
|
||||
re += rule[pos];
|
||||
@@ -71,12 +78,14 @@ private:
|
||||
assert(pos < rule.size());
|
||||
assert(rule[pos] == '"');
|
||||
++pos;
|
||||
} else if (std::isdigit(rule[pos])) {
|
||||
}
|
||||
else if (std::isdigit(rule[pos])) {
|
||||
std::size_t len = 0;
|
||||
std::size_t subid = std::stoul(rule.substr(pos), &len);
|
||||
pos += len;
|
||||
re += expand_rule(subid);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
@@ -93,7 +102,8 @@ private:
|
||||
std::string re31_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
Matcher matcher;
|
||||
bool adding_rules = true;
|
||||
@@ -102,9 +112,11 @@ int main(void) {
|
||||
if (line.empty()) {
|
||||
adding_rules = false;
|
||||
matcher.calculate_regex();
|
||||
} else if (adding_rules) {
|
||||
}
|
||||
else if (adding_rules) {
|
||||
matcher.add_rule(line);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
bool m = matcher.does_match(line);
|
||||
std::cout << line << ": does " << (m ? "" : "not ") << "match\n";
|
||||
matches += m;
|
||||
|
||||
@@ -14,8 +14,10 @@ using Hash = unsigned long;
|
||||
|
||||
enum Edge { Top, Left, Bottom, Right };
|
||||
|
||||
struct Picture {
|
||||
Picture(std::string id, std::istream &is) : in_use_(false) {
|
||||
struct Picture
|
||||
{
|
||||
Picture(std::string id, std::istream& is) : in_use_(false)
|
||||
{
|
||||
assert(id.substr(0, 5) == "Tile ");
|
||||
id_ = std::stoul(id.substr(5));
|
||||
std::string line;
|
||||
@@ -27,20 +29,22 @@ struct Picture {
|
||||
}
|
||||
}
|
||||
|
||||
Picture(Picture const &) = delete;
|
||||
Picture &operator=(Picture const &) = delete;
|
||||
Picture(Picture &&) = default;
|
||||
Picture &operator=(Picture &&) = default;
|
||||
Picture(Picture const&) = delete;
|
||||
Picture& operator=(Picture const&) = delete;
|
||||
Picture(Picture&&) = default;
|
||||
Picture& operator=(Picture&&) = default;
|
||||
|
||||
void flip() {
|
||||
for (auto &r : rows_) {
|
||||
void flip()
|
||||
{
|
||||
for (auto& r : rows_) {
|
||||
std::reverse(r.begin(), r.end());
|
||||
}
|
||||
}
|
||||
|
||||
void rotate() {
|
||||
void rotate()
|
||||
{
|
||||
std::vector<std::string> copy(rows_.size());
|
||||
for (auto const &r : rows_) {
|
||||
for (auto const& r : rows_) {
|
||||
std::size_t off = copy.size();
|
||||
assert(r.size() == copy.size());
|
||||
for (auto c : r) {
|
||||
@@ -51,7 +55,8 @@ struct Picture {
|
||||
rows_ = copy;
|
||||
}
|
||||
|
||||
Hash hash(Edge edge) const {
|
||||
Hash hash(Edge edge) const
|
||||
{
|
||||
unsigned x = (edge == Edge::Right) ? rows_[0].size() - 1 : 0;
|
||||
unsigned y = (edge == Edge::Bottom) ? rows_.size() - 1 : 0;
|
||||
unsigned dx = (edge == Edge::Top || edge == Edge::Bottom) ? 1 : 0;
|
||||
@@ -70,11 +75,9 @@ struct Picture {
|
||||
|
||||
Id id() const noexcept { return id_; }
|
||||
|
||||
bool operator<(Picture const &pict) const noexcept { return id_ < pict.id_; }
|
||||
bool operator<(Picture const& pict) const noexcept { return id_ < pict.id_; }
|
||||
|
||||
bool operator==(Picture const &pict) const noexcept {
|
||||
return id_ == pict.id_;
|
||||
}
|
||||
bool operator==(Picture const& pict) const noexcept { return id_ == pict.id_; }
|
||||
|
||||
bool in_use() const noexcept { return in_use_; }
|
||||
void use() noexcept { in_use_ = true; }
|
||||
@@ -90,14 +93,16 @@ using Pictures = std::map<Id, Picture>;
|
||||
using HashMap = std::multimap<Hash, Id>;
|
||||
using Array = std::map<std::pair<unsigned, unsigned>, Id>;
|
||||
|
||||
struct PictureArray {
|
||||
void add(Picture &&pic) {
|
||||
struct PictureArray
|
||||
{
|
||||
void add(Picture&& pic)
|
||||
{
|
||||
auto id = pic.id();
|
||||
auto [it, success] = pictures_.insert(std::make_pair(id, std::move(pic)));
|
||||
assert(success);
|
||||
|
||||
// Set up hash -> ID mapping
|
||||
Picture &picture = it->second;
|
||||
Picture& picture = it->second;
|
||||
for (unsigned r = 0; r < 4; ++r) {
|
||||
for (unsigned f = 0; f < 2; ++f) {
|
||||
hash_map_.insert({picture.hash(Edge::Top), picture.id()});
|
||||
@@ -107,13 +112,13 @@ struct PictureArray {
|
||||
}
|
||||
}
|
||||
|
||||
Id solve() {
|
||||
Id solve()
|
||||
{
|
||||
assert(pictures_.size() == 9 || pictures_.size() == 144);
|
||||
for (auto &kv : pictures_) {
|
||||
for (auto& kv : pictures_) {
|
||||
if (try_position(0, 0, kv.second)) {
|
||||
print_ids();
|
||||
return piece(0, 0).id() * piece(width() - 1, 0).id() *
|
||||
piece(0, height() - 1).id() *
|
||||
return piece(0, 0).id() * piece(width() - 1, 0).id() * piece(0, height() - 1).id() *
|
||||
piece(width() - 1, height() - 1).id();
|
||||
}
|
||||
}
|
||||
@@ -123,7 +128,8 @@ struct PictureArray {
|
||||
}
|
||||
|
||||
private:
|
||||
bool try_position(unsigned x, unsigned y, Picture &pict) {
|
||||
bool try_position(unsigned x, unsigned y, Picture& pict)
|
||||
{
|
||||
if (pict.in_use()) {
|
||||
return false;
|
||||
}
|
||||
@@ -180,7 +186,8 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
void print_ids() const {
|
||||
void print_ids() const
|
||||
{
|
||||
for (unsigned y = 0; y < height(); ++y) {
|
||||
for (unsigned x = 0; x < width(); ++x) {
|
||||
std::cout << " " << piece(x, y).id();
|
||||
@@ -189,20 +196,24 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
Picture const &piece(unsigned x, unsigned y) const {
|
||||
auto const &it = array_.find({x, y});
|
||||
Picture const& piece(unsigned x, unsigned y) const
|
||||
{
|
||||
auto const& it = array_.find({x, y});
|
||||
assert(it != array_.end());
|
||||
auto const &itp = pictures_.find(it->second);
|
||||
auto const& itp = pictures_.find(it->second);
|
||||
assert(itp != pictures_.end());
|
||||
return itp->second;
|
||||
}
|
||||
|
||||
unsigned width() const noexcept {
|
||||
unsigned width() const noexcept
|
||||
{
|
||||
if (pictures_.size() == 9) {
|
||||
return 3;
|
||||
} else if (pictures_.size() == 144) {
|
||||
}
|
||||
else if (pictures_.size() == 144) {
|
||||
return 12;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@@ -216,7 +227,8 @@ private:
|
||||
Array array_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
PictureArray pictures_;
|
||||
|
||||
std::string line;
|
||||
|
||||
@@ -16,8 +16,10 @@ enum Edge { Top, Left, Bottom, Right };
|
||||
|
||||
struct PictureArray;
|
||||
|
||||
struct Picture {
|
||||
Picture(std::string id, std::istream &is) : in_use_(false) {
|
||||
struct Picture
|
||||
{
|
||||
Picture(std::string id, std::istream& is) : in_use_(false)
|
||||
{
|
||||
assert(id.substr(0, 5) == "Tile ");
|
||||
id_ = std::stoul(id.substr(5));
|
||||
std::string line;
|
||||
@@ -29,22 +31,24 @@ struct Picture {
|
||||
}
|
||||
}
|
||||
|
||||
Picture(PictureArray const &array);
|
||||
Picture(PictureArray const& array);
|
||||
|
||||
Picture(Picture const &) = delete;
|
||||
Picture &operator=(Picture const &) = delete;
|
||||
Picture(Picture &&) = default;
|
||||
Picture &operator=(Picture &&) = default;
|
||||
Picture(Picture const&) = delete;
|
||||
Picture& operator=(Picture const&) = delete;
|
||||
Picture(Picture&&) = default;
|
||||
Picture& operator=(Picture&&) = default;
|
||||
|
||||
void flip() {
|
||||
for (auto &r : rows_) {
|
||||
void flip()
|
||||
{
|
||||
for (auto& r : rows_) {
|
||||
std::reverse(r.begin(), r.end());
|
||||
}
|
||||
}
|
||||
|
||||
void rotate() {
|
||||
void rotate()
|
||||
{
|
||||
std::vector<std::string> copy(rows_.size());
|
||||
for (auto const &r : rows_) {
|
||||
for (auto const& r : rows_) {
|
||||
std::size_t off = copy.size();
|
||||
assert(r.size() == copy.size());
|
||||
for (auto c : r) {
|
||||
@@ -55,7 +59,8 @@ struct Picture {
|
||||
rows_ = copy;
|
||||
}
|
||||
|
||||
Hash hash(Edge edge) const {
|
||||
Hash hash(Edge edge) const
|
||||
{
|
||||
unsigned x = (edge == Edge::Right) ? rows_[0].size() - 1 : 0;
|
||||
unsigned y = (edge == Edge::Bottom) ? rows_.size() - 1 : 0;
|
||||
unsigned dx = (edge == Edge::Top || edge == Edge::Bottom) ? 1 : 0;
|
||||
@@ -74,19 +79,18 @@ struct Picture {
|
||||
|
||||
Id id() const noexcept { return id_; }
|
||||
|
||||
bool operator<(Picture const &pict) const noexcept { return id_ < pict.id_; }
|
||||
bool operator<(Picture const& pict) const noexcept { return id_ < pict.id_; }
|
||||
|
||||
bool operator==(Picture const &pict) const noexcept {
|
||||
return id_ == pict.id_;
|
||||
}
|
||||
bool operator==(Picture const& pict) const noexcept { return id_ == pict.id_; }
|
||||
|
||||
bool in_use() const noexcept { return in_use_; }
|
||||
void use() noexcept { in_use_ = true; }
|
||||
void release() noexcept { in_use_ = false; }
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, Picture const &pict);
|
||||
friend std::ostream& operator<<(std::ostream& os, Picture const& pict);
|
||||
|
||||
unsigned find_monsters() {
|
||||
unsigned find_monsters()
|
||||
{
|
||||
for (unsigned r = 0; r < 4; ++r) {
|
||||
rotate();
|
||||
for (unsigned f = 0; f < 2; ++f) {
|
||||
@@ -101,9 +105,10 @@ struct Picture {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned roughness() const {
|
||||
unsigned roughness() const
|
||||
{
|
||||
unsigned rough = 0;
|
||||
for (auto const &r : rows_) {
|
||||
for (auto const& r : rows_) {
|
||||
for (auto c : r) {
|
||||
if (c == '#') {
|
||||
++rough;
|
||||
@@ -114,7 +119,8 @@ struct Picture {
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned find_monsters1() {
|
||||
unsigned find_monsters1()
|
||||
{
|
||||
// 0 1
|
||||
// 01234567890123456789
|
||||
// #
|
||||
@@ -146,12 +152,13 @@ private:
|
||||
for (std::size_t y = 0; y <= rows_.size() - mheight; ++y) {
|
||||
for (std::string::size_type x = 0; x <= rows_[y].size() - mwidth; ++x) {
|
||||
std::size_t cy = 0;
|
||||
std::string::size_type const *cx = locs;
|
||||
std::string::size_type const* cx = locs;
|
||||
bool found = true;
|
||||
while (cy < mheight) {
|
||||
if (*cx == std::string::npos) {
|
||||
++cy;
|
||||
} else if (rows_[y + cy][x + *cx] != '#') {
|
||||
}
|
||||
else if (rows_[y + cy][x + *cx] != '#') {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
@@ -160,11 +167,12 @@ private:
|
||||
if (found) {
|
||||
++monster_count;
|
||||
std::size_t cy = 0;
|
||||
std::string::size_type const *cx = locs;
|
||||
std::string::size_type const* cx = locs;
|
||||
while (cy < mheight) {
|
||||
if (*cx == std::string::npos) {
|
||||
++cy;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
rows_[y + cy][x + *cx] = '*';
|
||||
}
|
||||
++cx;
|
||||
@@ -182,8 +190,9 @@ private:
|
||||
bool in_use_;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, Picture const &pict) {
|
||||
for (auto const &r : pict.rows_) {
|
||||
std::ostream& operator<<(std::ostream& os, Picture const& pict)
|
||||
{
|
||||
for (auto const& r : pict.rows_) {
|
||||
os << r << '\n';
|
||||
}
|
||||
return os;
|
||||
@@ -193,14 +202,16 @@ using Pictures = std::map<Id, Picture>;
|
||||
using HashMap = std::multimap<Hash, Id>;
|
||||
using Array = std::map<std::pair<unsigned, unsigned>, Id>;
|
||||
|
||||
struct PictureArray {
|
||||
void add(Picture &&pic) {
|
||||
struct PictureArray
|
||||
{
|
||||
void add(Picture&& pic)
|
||||
{
|
||||
auto id = pic.id();
|
||||
auto [it, success] = pictures_.insert(std::make_pair(id, std::move(pic)));
|
||||
assert(success);
|
||||
|
||||
// Set up hash -> ID mapping
|
||||
Picture &picture = it->second;
|
||||
Picture& picture = it->second;
|
||||
for (unsigned r = 0; r < 4; ++r) {
|
||||
for (unsigned f = 0; f < 2; ++f) {
|
||||
hash_map_.insert({picture.hash(Edge::Top), picture.id()});
|
||||
@@ -210,13 +221,13 @@ struct PictureArray {
|
||||
}
|
||||
}
|
||||
|
||||
Id solve() {
|
||||
Id solve()
|
||||
{
|
||||
assert(pictures_.size() == 9 || pictures_.size() == 144);
|
||||
for (auto &kv : pictures_) {
|
||||
for (auto& kv : pictures_) {
|
||||
if (try_position(0, 0, kv.second)) {
|
||||
print_ids();
|
||||
return piece(0, 0).id() * piece(width() - 1, 0).id() *
|
||||
piece(0, height() - 1).id() *
|
||||
return piece(0, 0).id() * piece(width() - 1, 0).id() * piece(0, height() - 1).id() *
|
||||
piece(width() - 1, height() - 1).id();
|
||||
}
|
||||
}
|
||||
@@ -224,12 +235,15 @@ struct PictureArray {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
unsigned width() const noexcept {
|
||||
unsigned width() const noexcept
|
||||
{
|
||||
if (pictures_.size() == 9) {
|
||||
return 3;
|
||||
} else if (pictures_.size() == 144) {
|
||||
}
|
||||
else if (pictures_.size() == 144) {
|
||||
return 12;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@@ -238,16 +252,18 @@ struct PictureArray {
|
||||
|
||||
unsigned height() const noexcept { return width(); }
|
||||
|
||||
Picture const &piece(unsigned x, unsigned y) const {
|
||||
auto const &it = array_.find({x, y});
|
||||
Picture const& piece(unsigned x, unsigned y) const
|
||||
{
|
||||
auto const& it = array_.find({x, y});
|
||||
assert(it != array_.end());
|
||||
auto const &itp = pictures_.find(it->second);
|
||||
auto const& itp = pictures_.find(it->second);
|
||||
assert(itp != pictures_.end());
|
||||
return itp->second;
|
||||
}
|
||||
|
||||
private:
|
||||
bool try_position(unsigned x, unsigned y, Picture &pict) {
|
||||
bool try_position(unsigned x, unsigned y, Picture& pict)
|
||||
{
|
||||
if (pict.in_use()) {
|
||||
return false;
|
||||
}
|
||||
@@ -304,7 +320,8 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
void print_ids() const {
|
||||
void print_ids() const
|
||||
{
|
||||
for (unsigned y = 0; y < height(); ++y) {
|
||||
for (unsigned x = 0; x < width(); ++x) {
|
||||
std::cout << " " << piece(x, y).id();
|
||||
@@ -318,11 +335,12 @@ private:
|
||||
Array array_;
|
||||
};
|
||||
|
||||
Picture::Picture(PictureArray const &array) : id_(0), in_use_(false) {
|
||||
Picture::Picture(PictureArray const& array) : id_(0), in_use_(false)
|
||||
{
|
||||
for (unsigned y = 0; y < array.height(); ++y) {
|
||||
auto ybase = rows_.size();
|
||||
for (unsigned x = 0; x < array.width(); ++x) {
|
||||
auto &pict = array.piece(x, y);
|
||||
auto& pict = array.piece(x, y);
|
||||
for (auto py = 1; py < pict.rows_.size() - 1; ++py) {
|
||||
auto yidx = ybase + py - 1;
|
||||
if (rows_.size() <= yidx) {
|
||||
@@ -336,7 +354,8 @@ Picture::Picture(PictureArray const &array) : id_(0), in_use_(false) {
|
||||
assert(rows_[0].size() == array.width() * 8);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
PictureArray pictures_;
|
||||
|
||||
std::string line;
|
||||
|
||||
@@ -19,9 +19,11 @@ using IngredientInfo = std::pair<unsigned, Allergens>;
|
||||
using IngredientMap = std::map<Ingredient, IngredientInfo>;
|
||||
using AllergenMap = std::map<Allergen, Ingredients>;
|
||||
|
||||
class IngredientParser {
|
||||
class IngredientParser
|
||||
{
|
||||
public:
|
||||
void add_recipe(std::string const &s) {
|
||||
void add_recipe(std::string const& s)
|
||||
{
|
||||
auto it = s.begin();
|
||||
Ingredients i;
|
||||
while (it != s.end()) {
|
||||
@@ -33,10 +35,10 @@ public:
|
||||
it = ite;
|
||||
if (ingredient == "(contains") {
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
i.insert(ingredient);
|
||||
auto [iit, success] =
|
||||
ingredients_.insert({ingredient, {1, Allergens()}});
|
||||
auto [iit, success] = ingredients_.insert({ingredient, {1, Allergens()}});
|
||||
if (!success) {
|
||||
iit->second.first++;
|
||||
}
|
||||
@@ -44,8 +46,7 @@ public:
|
||||
}
|
||||
|
||||
while (it != s.end()) {
|
||||
auto ite = std::find_if(
|
||||
it, s.end(), [](char c) -> bool { return c == ',' || c == ')'; });
|
||||
auto ite = std::find_if(it, s.end(), [](char c) -> bool { return c == ',' || c == ')'; });
|
||||
auto allergen = std::string(it, ite);
|
||||
++ite;
|
||||
while (ite != s.end() && *ite == ' ') {
|
||||
@@ -56,18 +57,18 @@ public:
|
||||
if (!success) {
|
||||
Ingredients a;
|
||||
std::set_intersection(i.begin(), i.end(), insert_it->second.begin(),
|
||||
insert_it->second.end(),
|
||||
std::inserter(a, a.end()));
|
||||
insert_it->second.end(), std::inserter(a, a.end()));
|
||||
insert_it->second = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned clean_ingredients() {
|
||||
for (auto const &kv : allergens_) {
|
||||
unsigned clean_ingredients()
|
||||
{
|
||||
for (auto const& kv : allergens_) {
|
||||
auto allergen = kv.first;
|
||||
std::cout << "Allergen " << allergen << ":";
|
||||
for (auto const &i : kv.second) {
|
||||
for (auto const& i : kv.second) {
|
||||
std::cout << " " << i;
|
||||
auto it = ingredients_.find(i);
|
||||
assert(it != ingredients_.end());
|
||||
@@ -77,10 +78,9 @@ public:
|
||||
}
|
||||
|
||||
unsigned count = 0;
|
||||
for (auto const &i : ingredients_) {
|
||||
for (auto const& i : ingredients_) {
|
||||
if (i.second.second.size() == 0) {
|
||||
std::cout << i.first << " is not an allergen, appears "
|
||||
<< i.second.first << ".\n";
|
||||
std::cout << i.first << " is not an allergen, appears " << i.second.first << ".\n";
|
||||
count += i.second.first;
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,8 @@ private:
|
||||
AllergenMap allergens_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
IngredientParser parser;
|
||||
while (std::getline(std::cin, line)) {
|
||||
|
||||
@@ -19,9 +19,11 @@ using IngredientInfo = std::pair<unsigned, Allergens>;
|
||||
using IngredientMap = std::map<Ingredient, IngredientInfo>;
|
||||
using AllergenMap = std::map<Allergen, Ingredients>;
|
||||
|
||||
class IngredientParser {
|
||||
class IngredientParser
|
||||
{
|
||||
public:
|
||||
void add_recipe(std::string const &s) {
|
||||
void add_recipe(std::string const& s)
|
||||
{
|
||||
auto it = s.begin();
|
||||
Ingredients i;
|
||||
while (it != s.end()) {
|
||||
@@ -33,10 +35,10 @@ public:
|
||||
it = ite;
|
||||
if (ingredient == "(contains") {
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
i.insert(ingredient);
|
||||
auto [iit, success] =
|
||||
ingredients_.insert({ingredient, {1, Allergens()}});
|
||||
auto [iit, success] = ingredients_.insert({ingredient, {1, Allergens()}});
|
||||
if (!success) {
|
||||
iit->second.first++;
|
||||
}
|
||||
@@ -44,8 +46,7 @@ public:
|
||||
}
|
||||
|
||||
while (it != s.end()) {
|
||||
auto ite = std::find_if(
|
||||
it, s.end(), [](char c) -> bool { return c == ',' || c == ')'; });
|
||||
auto ite = std::find_if(it, s.end(), [](char c) -> bool { return c == ',' || c == ')'; });
|
||||
auto allergen = std::string(it, ite);
|
||||
++ite;
|
||||
while (ite != s.end() && *ite == ' ') {
|
||||
@@ -56,18 +57,18 @@ public:
|
||||
if (!success) {
|
||||
Ingredients a;
|
||||
std::set_intersection(i.begin(), i.end(), insert_it->second.begin(),
|
||||
insert_it->second.end(),
|
||||
std::inserter(a, a.end()));
|
||||
insert_it->second.end(), std::inserter(a, a.end()));
|
||||
insert_it->second = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned clean_ingredients() {
|
||||
for (auto const &kv : allergens_) {
|
||||
unsigned clean_ingredients()
|
||||
{
|
||||
for (auto const& kv : allergens_) {
|
||||
auto allergen = kv.first;
|
||||
std::cout << "Allergen " << allergen << ":";
|
||||
for (auto const &i : kv.second) {
|
||||
for (auto const& i : kv.second) {
|
||||
std::cout << " " << i;
|
||||
auto it = ingredients_.find(i);
|
||||
assert(it != ingredients_.end());
|
||||
@@ -77,10 +78,9 @@ public:
|
||||
}
|
||||
|
||||
unsigned count = 0;
|
||||
for (auto const &i : ingredients_) {
|
||||
for (auto const& i : ingredients_) {
|
||||
if (i.second.second.size() == 0) {
|
||||
std::cout << i.first << " is not an allergen, appears "
|
||||
<< i.second.first << ".\n";
|
||||
std::cout << i.first << " is not an allergen, appears " << i.second.first << ".\n";
|
||||
count += i.second.first;
|
||||
}
|
||||
}
|
||||
@@ -88,23 +88,23 @@ public:
|
||||
return count;
|
||||
}
|
||||
|
||||
std::string dangerous_ingredients() {
|
||||
std::string dangerous_ingredients()
|
||||
{
|
||||
bool changed = true;
|
||||
Ingredients i;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
for (auto const &kv : allergens_) {
|
||||
for (auto const& kv : allergens_) {
|
||||
if (kv.second.size() == 1) {
|
||||
auto it = kv.second.begin();
|
||||
Ingredient const &ing = *it;
|
||||
Ingredient const& ing = *it;
|
||||
auto [iit, success] = i.insert(ing);
|
||||
if (!success) {
|
||||
continue;
|
||||
}
|
||||
changed = true;
|
||||
std::cout << "Allergen " << kv.first << " is in ingredient " << ing
|
||||
<< "\n";
|
||||
for (auto &kv2 : allergens_) {
|
||||
std::cout << "Allergen " << kv.first << " is in ingredient " << ing << "\n";
|
||||
for (auto& kv2 : allergens_) {
|
||||
if (kv2.second.size() != 1) {
|
||||
kv2.second.erase(ing);
|
||||
}
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
}
|
||||
|
||||
std::string result;
|
||||
for (auto const &kv : allergens_) {
|
||||
for (auto const& kv : allergens_) {
|
||||
result += ",";
|
||||
result += *kv.second.begin();
|
||||
}
|
||||
@@ -127,7 +127,8 @@ private:
|
||||
AllergenMap allergens_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
IngredientParser parser;
|
||||
while (std::getline(std::cin, line)) {
|
||||
|
||||
@@ -14,8 +14,10 @@ using Card = unsigned;
|
||||
using Cards = std::list<Card>;
|
||||
using Score = unsigned long;
|
||||
|
||||
struct Player {
|
||||
Player(std::istream &is) {
|
||||
struct Player
|
||||
{
|
||||
Player(std::istream& is)
|
||||
{
|
||||
std::string line;
|
||||
if (!std::getline(is, name_)) {
|
||||
assert(false);
|
||||
@@ -33,7 +35,8 @@ struct Player {
|
||||
void pop_front() { cards_.pop_front(); }
|
||||
void push_back(Card c) { cards_.push_back(c); }
|
||||
|
||||
Score score() const {
|
||||
Score score() const
|
||||
{
|
||||
Score r = 0;
|
||||
unsigned idx = 1;
|
||||
for (auto it = cards_.rbegin(); it != cards_.rend(); ++it) {
|
||||
@@ -48,7 +51,8 @@ private:
|
||||
Cards cards_;
|
||||
};
|
||||
|
||||
Score play_game(Player &p1, Player &p2) {
|
||||
Score play_game(Player& p1, Player& p2)
|
||||
{
|
||||
while (!p1.empty() && !p2.empty()) {
|
||||
Card c1 = p1.front();
|
||||
Card c2 = p2.front();
|
||||
@@ -57,7 +61,8 @@ Score play_game(Player &p1, Player &p2) {
|
||||
if (c1 > c2) {
|
||||
p1.push_back(c1);
|
||||
p1.push_back(c2);
|
||||
} else if (c1 < c2) {
|
||||
}
|
||||
else if (c1 < c2) {
|
||||
p2.push_back(c2);
|
||||
p2.push_back(c1);
|
||||
}
|
||||
@@ -66,7 +71,8 @@ Score play_game(Player &p1, Player &p2) {
|
||||
return p1.score() + p2.score();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
Player player1(std::cin);
|
||||
Player player2(std::cin);
|
||||
|
||||
|
||||
@@ -15,8 +15,10 @@ using Cards = std::list<Card>;
|
||||
using Score = unsigned long;
|
||||
using Hash = std::string;
|
||||
|
||||
struct Player {
|
||||
Player(std::istream &is) {
|
||||
struct Player
|
||||
{
|
||||
Player(std::istream& is)
|
||||
{
|
||||
std::string line;
|
||||
if (!std::getline(is, name_)) {
|
||||
assert(false);
|
||||
@@ -35,7 +37,8 @@ struct Player {
|
||||
void push_back(Card c) { cards_.push_back(c); }
|
||||
std::size_t size() const { return cards_.size(); }
|
||||
|
||||
Score score() const {
|
||||
Score score() const
|
||||
{
|
||||
Score r = 0;
|
||||
unsigned idx = 1;
|
||||
for (auto it = cards_.rbegin(); it != cards_.rend(); ++it) {
|
||||
@@ -45,7 +48,8 @@ struct Player {
|
||||
return r;
|
||||
}
|
||||
|
||||
Hash hash() const {
|
||||
Hash hash() const
|
||||
{
|
||||
std::string r = name_;
|
||||
for (auto c : cards_) {
|
||||
assert(c > 0);
|
||||
@@ -56,21 +60,23 @@ struct Player {
|
||||
return r;
|
||||
}
|
||||
|
||||
Player(Player const &prev, Card size) : name_(prev.name_ + "-") {
|
||||
Player(Player const& prev, Card size) : name_(prev.name_ + "-")
|
||||
{
|
||||
auto it = prev.cards_.begin();
|
||||
for (Card i = 0; i < size; ++i) {
|
||||
cards_.push_back(*it++);
|
||||
}
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, Player const &p);
|
||||
friend std::ostream& operator<<(std::ostream& os, Player const& p);
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
Cards cards_;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, Player const &p) {
|
||||
std::ostream& operator<<(std::ostream& os, Player const& p)
|
||||
{
|
||||
os << p.name_;
|
||||
for (auto c : p.cards_) {
|
||||
os << " " << c;
|
||||
@@ -79,7 +85,8 @@ std::ostream &operator<<(std::ostream &os, Player const &p) {
|
||||
}
|
||||
|
||||
// False = p1 wins, true = p2 wins.
|
||||
bool play_game(Player &p1, Player &p2) {
|
||||
bool play_game(Player& p1, Player& p2)
|
||||
{
|
||||
std::set<Hash> hashes;
|
||||
|
||||
while (!p1.empty() && !p2.empty()) {
|
||||
@@ -100,17 +107,21 @@ bool play_game(Player &p1, Player &p2) {
|
||||
if (!result) {
|
||||
p1.push_back(c1);
|
||||
p1.push_back(c2);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p2.push_back(c2);
|
||||
p2.push_back(c1);
|
||||
}
|
||||
} else if (c1 > c2) {
|
||||
}
|
||||
else if (c1 > c2) {
|
||||
p1.push_back(c1);
|
||||
p1.push_back(c2);
|
||||
} else if (c1 < c2) {
|
||||
}
|
||||
else if (c1 < c2) {
|
||||
p2.push_back(c2);
|
||||
p2.push_back(c1);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +129,8 @@ bool play_game(Player &p1, Player &p2) {
|
||||
return p1.empty();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
Player player1(std::cin);
|
||||
Player player2(std::cin);
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
struct Cups {
|
||||
Cups(std::string const &s) : s_(s) {
|
||||
std::cout << "Initial state: " << s_ << "\n";
|
||||
}
|
||||
struct Cups
|
||||
{
|
||||
Cups(std::string const& s) : s_(s) { std::cout << "Initial state: " << s_ << "\n"; }
|
||||
|
||||
void play(unsigned moves) {
|
||||
void play(unsigned moves)
|
||||
{
|
||||
// We assume the current value is always at index 0.
|
||||
// So the values to remove are in offsets [1, 4).
|
||||
while (moves-- > 0) {
|
||||
@@ -27,13 +27,13 @@ struct Cups {
|
||||
d = d == '1' ? '9' : d - 1;
|
||||
}
|
||||
|
||||
s_ = s_.substr(4, dest - 3) + s_.substr(1, 3) + s_.substr(dest + 1) +
|
||||
s_[0];
|
||||
s_ = s_.substr(4, dest - 3) + s_.substr(1, 3) + s_.substr(dest + 1) + s_[0];
|
||||
std::cout << moves << ": " << s_ << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
std::string result() const {
|
||||
std::string result() const
|
||||
{
|
||||
auto split = s_.find('1');
|
||||
return s_.substr(split + 1) + s_.substr(0, split);
|
||||
}
|
||||
@@ -42,7 +42,8 @@ private:
|
||||
std::string s_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
Cups cups(line);
|
||||
|
||||
@@ -11,24 +11,27 @@
|
||||
#include <vector>
|
||||
|
||||
using Value = unsigned long;
|
||||
struct Cup {
|
||||
struct Cup
|
||||
{
|
||||
Cup() : value_(0), next_(nullptr) {}
|
||||
|
||||
Value value() const { return value_; }
|
||||
void value(Value v) { value_ = v; }
|
||||
Cup *next() const { return next_; }
|
||||
void next(Cup *n) { next_ = n; }
|
||||
Cup* next() const { return next_; }
|
||||
void next(Cup* n) { next_ = n; }
|
||||
|
||||
private:
|
||||
Value value_;
|
||||
Cup *next_;
|
||||
Cup* next_;
|
||||
};
|
||||
|
||||
struct Cups {
|
||||
struct Cups
|
||||
{
|
||||
static constexpr std::size_t num_cups_ = 1000000;
|
||||
static constexpr std::size_t num_moves_ = 10000000;
|
||||
|
||||
Cups(std::string const &s) : cups_(new Cup[num_cups_]), current_(cups_) {
|
||||
Cups(std::string const& s) : cups_(new Cup[num_cups_]), current_(cups_)
|
||||
{
|
||||
std::size_t idx = 0;
|
||||
for (auto c : s) {
|
||||
cups_[idx].value(c - '0');
|
||||
@@ -47,17 +50,18 @@ struct Cups {
|
||||
|
||||
~Cups() { delete[] cups_; }
|
||||
|
||||
void play() {
|
||||
void play()
|
||||
{
|
||||
for (std::size_t move = 0; move < num_moves_; ++move) {
|
||||
if (move % 1000 == 0) {
|
||||
std::cout << "A" << move << " " << current_ - cups_ << " "
|
||||
<< current_->value() << " " << result() << "\n";
|
||||
std::cout << "A" << move << " " << current_ - cups_ << " " << current_->value() << " "
|
||||
<< result() << "\n";
|
||||
// print();
|
||||
}
|
||||
|
||||
// Remove first three after current.
|
||||
Cup *rb = current_->next();
|
||||
Cup *re = rb->next()->next();
|
||||
Cup* rb = current_->next();
|
||||
Cup* re = rb->next()->next();
|
||||
current_->next(re->next());
|
||||
re->next(nullptr);
|
||||
|
||||
@@ -74,14 +78,15 @@ struct Cups {
|
||||
// Where do we insert? Note that we use the hack that all the values are
|
||||
// actually in an index and we know what the value is (roughly) based on
|
||||
// the index.
|
||||
Cup *ins = nullptr;
|
||||
Cup* ins = nullptr;
|
||||
if (vm1 < 10) {
|
||||
ins = cups_;
|
||||
while (ins->value() != vm1) {
|
||||
assert(ins != cups_ + 10);
|
||||
++ins;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ins = cups_ + vm1 - 1;
|
||||
}
|
||||
|
||||
@@ -96,8 +101,9 @@ struct Cups {
|
||||
}
|
||||
}
|
||||
|
||||
Value result() const {
|
||||
Cup *one = cups_;
|
||||
Value result() const
|
||||
{
|
||||
Cup* one = cups_;
|
||||
while (one->value() != 1) {
|
||||
++one;
|
||||
assert(one != cups_ + num_cups_);
|
||||
@@ -106,9 +112,10 @@ struct Cups {
|
||||
return one->next()->value() * one->next()->next()->value();
|
||||
}
|
||||
|
||||
void print() const {
|
||||
void print() const
|
||||
{
|
||||
std::cout << "State:";
|
||||
Cup const *c = current_;
|
||||
Cup const* c = current_;
|
||||
do {
|
||||
std::cout << " " << c->value();
|
||||
c = c->next();
|
||||
@@ -117,11 +124,12 @@ struct Cups {
|
||||
}
|
||||
|
||||
private:
|
||||
Cup *cups_;
|
||||
Cup *current_;
|
||||
Cup* cups_;
|
||||
Cup* current_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
Cups cups(line);
|
||||
|
||||
@@ -14,8 +14,10 @@ using Coord = long;
|
||||
using Position = std::pair<Coord, Coord>;
|
||||
using Tiles = std::set<Position>;
|
||||
|
||||
struct Tiler {
|
||||
void flip_tile(std::string const &s) {
|
||||
struct Tiler
|
||||
{
|
||||
void flip_tile(std::string const& s)
|
||||
{
|
||||
Coord x = 0;
|
||||
Coord y = 0;
|
||||
auto it = s.begin();
|
||||
@@ -30,9 +32,11 @@ struct Tiler {
|
||||
|
||||
if (*it == 'e') {
|
||||
x += dx;
|
||||
} else if (*it == 'w') {
|
||||
}
|
||||
else if (*it == 'w') {
|
||||
x -= dx;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
++it;
|
||||
@@ -51,7 +55,8 @@ private:
|
||||
Tiles black_tiles_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
Tiler tiler;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
|
||||
@@ -12,14 +12,17 @@
|
||||
|
||||
using Coord = long;
|
||||
using Position = std::pair<Coord, Coord>;
|
||||
struct State {
|
||||
struct State
|
||||
{
|
||||
bool black_ = false;
|
||||
int neighbours_ = 0;
|
||||
};
|
||||
using Tiles = std::map<Position, State>;
|
||||
|
||||
struct Tiler {
|
||||
void flip_tile(std::string const &s) {
|
||||
struct Tiler
|
||||
{
|
||||
void flip_tile(std::string const& s)
|
||||
{
|
||||
Coord x = 0;
|
||||
Coord y = 0;
|
||||
auto it = s.begin();
|
||||
@@ -34,9 +37,11 @@ struct Tiler {
|
||||
|
||||
if (*it == 'e') {
|
||||
x += dx;
|
||||
} else if (*it == 'w') {
|
||||
}
|
||||
else if (*it == 'w') {
|
||||
x -= dx;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
++it;
|
||||
@@ -46,13 +51,14 @@ struct Tiler {
|
||||
flip_tile(x, y);
|
||||
}
|
||||
|
||||
Tiler next_state() const {
|
||||
Tiler next_state() const
|
||||
{
|
||||
Tiler next(*this);
|
||||
for (auto const &kv : tiles_) {
|
||||
if (kv.second.black_ &&
|
||||
(kv.second.neighbours_ == 0 || kv.second.neighbours_ > 2)) {
|
||||
for (auto const& kv : tiles_) {
|
||||
if (kv.second.black_ && (kv.second.neighbours_ == 0 || kv.second.neighbours_ > 2)) {
|
||||
next.flip_tile(kv.first.first, kv.first.second);
|
||||
} else if (!kv.second.black_ && kv.second.neighbours_ == 2) {
|
||||
}
|
||||
else if (!kv.second.black_ && kv.second.neighbours_ == 2) {
|
||||
next.flip_tile(kv.first.first, kv.first.second);
|
||||
}
|
||||
}
|
||||
@@ -60,9 +66,10 @@ struct Tiler {
|
||||
return next;
|
||||
}
|
||||
|
||||
std::size_t black_count() const noexcept {
|
||||
std::size_t black_count() const noexcept
|
||||
{
|
||||
std::size_t count = 0;
|
||||
for (auto const &kv : tiles_) {
|
||||
for (auto const& kv : tiles_) {
|
||||
count += kv.second.black_;
|
||||
}
|
||||
|
||||
@@ -70,7 +77,8 @@ struct Tiler {
|
||||
}
|
||||
|
||||
private:
|
||||
void set_neighbours(Coord x, Coord y, int delta) {
|
||||
void set_neighbours(Coord x, Coord y, int delta)
|
||||
{
|
||||
set_neighbour(x + 2, y, delta);
|
||||
set_neighbour(x + 1, y - 1, delta);
|
||||
set_neighbour(x - 1, y - 1, delta);
|
||||
@@ -79,7 +87,8 @@ private:
|
||||
set_neighbour(x + 1, y + 1, delta);
|
||||
}
|
||||
|
||||
void set_neighbour(Coord x, Coord y, int delta) {
|
||||
void set_neighbour(Coord x, Coord y, int delta)
|
||||
{
|
||||
auto [it, success] = tiles_.insert({{x, y}, {false, delta}});
|
||||
if (!success) {
|
||||
it->second.neighbours_ += delta;
|
||||
@@ -87,14 +96,16 @@ private:
|
||||
assert(it->second.neighbours_ >= 0);
|
||||
}
|
||||
|
||||
void flip_tile(Coord x, Coord y) {
|
||||
void flip_tile(Coord x, Coord y)
|
||||
{
|
||||
auto [it, success] = tiles_.insert({{x, y}, {true, 0}});
|
||||
if (!success) {
|
||||
it->second.black_ = !it->second.black_;
|
||||
}
|
||||
if (it->second.black_) {
|
||||
set_neighbours(x, y, 1);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
set_neighbours(x, y, -1);
|
||||
}
|
||||
}
|
||||
@@ -103,7 +114,8 @@ private:
|
||||
Tiles tiles_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
Tiler tiler;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
constexpr unsigned mod = 20201227;
|
||||
constexpr unsigned initial_subject = 7;
|
||||
|
||||
unsigned lcg(unsigned i, unsigned subject) {
|
||||
unsigned lcg(unsigned i, unsigned subject)
|
||||
{
|
||||
return ((unsigned long)i * (unsigned long)subject) % mod;
|
||||
}
|
||||
|
||||
unsigned find_loop_length(unsigned pk) {
|
||||
unsigned find_loop_length(unsigned pk)
|
||||
{
|
||||
unsigned v = 1;
|
||||
unsigned loop = 0;
|
||||
while (v != pk) {
|
||||
@@ -28,7 +30,8 @@ unsigned find_loop_length(unsigned pk) {
|
||||
return loop;
|
||||
}
|
||||
|
||||
unsigned apply(unsigned pk, unsigned loop_size) {
|
||||
unsigned apply(unsigned pk, unsigned loop_size)
|
||||
{
|
||||
unsigned v = 1;
|
||||
for (unsigned i = 0; i < loop_size; ++i) {
|
||||
v = lcg(v, pk);
|
||||
@@ -37,7 +40,8 @@ unsigned apply(unsigned pk, unsigned loop_size) {
|
||||
return v;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
unsigned pk1 = std::stoul(line);
|
||||
|
||||
Reference in New Issue
Block a user