Add .clang-format and apply it
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
int floor = 0;
|
||||
for (auto c : line) {
|
||||
|
@@ -2,7 +2,8 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
int floor = 0;
|
||||
std::string::size_type pos = 0;
|
||||
|
@@ -3,11 +3,13 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
struct Box {
|
||||
struct Box
|
||||
{
|
||||
/** Construct box.
|
||||
* \param s String representation of dimensions 'lxwxh'
|
||||
*/
|
||||
Box(std::string const &s) {
|
||||
Box(std::string const& s)
|
||||
{
|
||||
std::size_t pos = 0;
|
||||
l_ = std::stoul(s, &pos, 10);
|
||||
assert(s[pos] == 'x');
|
||||
@@ -20,7 +22,8 @@ struct Box {
|
||||
}
|
||||
|
||||
// How much paper does this box need?
|
||||
unsigned long paper_needed() const {
|
||||
unsigned long paper_needed() const
|
||||
{
|
||||
unsigned long s1 = l_ * w_;
|
||||
unsigned long s2 = w_ * h_;
|
||||
unsigned long s3 = h_ * l_;
|
||||
@@ -32,7 +35,8 @@ struct Box {
|
||||
unsigned long h_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned long total = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
Box b(line);
|
||||
|
@@ -3,11 +3,13 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
struct Box {
|
||||
struct Box
|
||||
{
|
||||
/** Construct box.
|
||||
* \param s String representation of dimensions 'lxwxh'
|
||||
*/
|
||||
Box(std::string const &s) {
|
||||
Box(std::string const& s)
|
||||
{
|
||||
std::size_t pos = 0;
|
||||
l_ = std::stoul(s, &pos, 10);
|
||||
assert(s[pos] == 'x');
|
||||
@@ -20,7 +22,8 @@ struct Box {
|
||||
}
|
||||
|
||||
// How much paper does this box need?
|
||||
unsigned long paper_needed() const {
|
||||
unsigned long paper_needed() const
|
||||
{
|
||||
unsigned long s1 = l_ * w_;
|
||||
unsigned long s2 = w_ * h_;
|
||||
unsigned long s3 = h_ * l_;
|
||||
@@ -28,7 +31,8 @@ struct Box {
|
||||
}
|
||||
|
||||
// How much ribbon do we need?
|
||||
unsigned long ribbon_needed() const {
|
||||
unsigned long ribbon_needed() const
|
||||
{
|
||||
// The various side perimeters - we want the min of these multiplied by
|
||||
// volume.
|
||||
unsigned long p1 = 2 * (l_ + w_);
|
||||
@@ -42,7 +46,8 @@ struct Box {
|
||||
unsigned long h_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned long total = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
Box b(line);
|
||||
|
@@ -4,18 +4,19 @@
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
struct Pos {
|
||||
struct Pos
|
||||
{
|
||||
Pos(int x, int y) : x_(x), y_(y) {}
|
||||
|
||||
bool operator<(Pos const &rhs) const noexcept {
|
||||
bool operator<(Pos const& rhs) const noexcept
|
||||
{
|
||||
return x_ < rhs.x_ || (x_ == rhs.x_ && y_ < rhs.y_);
|
||||
}
|
||||
|
||||
bool operator==(Pos const &rhs) const noexcept {
|
||||
return x_ == rhs.x_ && y_ == rhs.y_;
|
||||
}
|
||||
bool operator==(Pos const& rhs) const noexcept { return x_ == rhs.x_ && y_ == rhs.y_; }
|
||||
|
||||
void move(char c) {
|
||||
void move(char c)
|
||||
{
|
||||
switch (c) {
|
||||
case '>':
|
||||
++x_;
|
||||
@@ -39,7 +40,8 @@ struct Pos {
|
||||
int y_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
std::set<Pos> visited;
|
||||
Pos santa(0, 0);
|
||||
|
@@ -4,18 +4,19 @@
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
struct Pos {
|
||||
struct Pos
|
||||
{
|
||||
Pos(int x, int y) : x_(x), y_(y) {}
|
||||
|
||||
bool operator<(Pos const &rhs) const noexcept {
|
||||
bool operator<(Pos const& rhs) const noexcept
|
||||
{
|
||||
return x_ < rhs.x_ || (x_ == rhs.x_ && y_ < rhs.y_);
|
||||
}
|
||||
|
||||
bool operator==(Pos const &rhs) const noexcept {
|
||||
return x_ == rhs.x_ && y_ == rhs.y_;
|
||||
}
|
||||
bool operator==(Pos const& rhs) const noexcept { return x_ == rhs.x_ && y_ == rhs.y_; }
|
||||
|
||||
void move(char c) noexcept {
|
||||
void move(char c) noexcept
|
||||
{
|
||||
switch (c) {
|
||||
case '>':
|
||||
++x_;
|
||||
@@ -39,7 +40,8 @@ struct Pos {
|
||||
int y_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
std::set<Pos> visited;
|
||||
Pos santa(0, 0);
|
||||
@@ -51,7 +53,8 @@ int main(int argc, char **argv) {
|
||||
if (do_robo) {
|
||||
robo_santa.move(c);
|
||||
visited.insert(robo_santa);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
santa.move(c);
|
||||
visited.insert(santa);
|
||||
}
|
||||
|
@@ -8,26 +8,29 @@
|
||||
|
||||
using MD5Digest = unsigned char[EVP_MAX_MD_SIZE];
|
||||
|
||||
unsigned int md5(MD5Digest digest, std::string const &s) {
|
||||
EVP_MD const* md{EVP_md5()};
|
||||
unsigned int md_len;
|
||||
unsigned int md5(MD5Digest digest, std::string const& s)
|
||||
{
|
||||
EVP_MD const* md{EVP_md5()};
|
||||
unsigned int md_len;
|
||||
|
||||
EVP_MD_CTX* md_ctxt{EVP_MD_CTX_new()};
|
||||
assert(md_ctxt != NULL);
|
||||
EVP_DigestInit_ex2(md_ctxt, md, NULL);
|
||||
EVP_DigestUpdate(md_ctxt, s.data(), s.length());
|
||||
EVP_DigestFinal_ex(md_ctxt, digest, &md_len);
|
||||
return md_len;
|
||||
EVP_MD_CTX* md_ctxt{EVP_MD_CTX_new()};
|
||||
assert(md_ctxt != NULL);
|
||||
EVP_DigestInit_ex2(md_ctxt, md, NULL);
|
||||
EVP_DigestUpdate(md_ctxt, s.data(), s.length());
|
||||
EVP_DigestFinal_ex(md_ctxt, digest, &md_len);
|
||||
return md_len;
|
||||
}
|
||||
|
||||
bool is_valid(std::string const &s) {
|
||||
bool is_valid(std::string const& s)
|
||||
{
|
||||
MD5Digest digest;
|
||||
auto len = md5(digest, s);
|
||||
assert(len >= 3);
|
||||
return digest[0] == 0 && digest[1] == 0 && (digest[2] & 0xf0) == 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
unsigned i = 0;
|
||||
while (!is_valid(line + std::to_string(i))) {
|
||||
|
@@ -8,26 +8,29 @@
|
||||
|
||||
using MD5Digest = unsigned char[EVP_MAX_MD_SIZE];
|
||||
|
||||
unsigned int md5(MD5Digest digest, std::string const &s) {
|
||||
EVP_MD const* md{EVP_md5()};
|
||||
unsigned int md_len;
|
||||
unsigned int md5(MD5Digest digest, std::string const& s)
|
||||
{
|
||||
EVP_MD const* md{EVP_md5()};
|
||||
unsigned int md_len;
|
||||
|
||||
EVP_MD_CTX* md_ctxt{EVP_MD_CTX_new()};
|
||||
assert(md_ctxt != NULL);
|
||||
EVP_DigestInit_ex2(md_ctxt, md, NULL);
|
||||
EVP_DigestUpdate(md_ctxt, s.data(), s.length());
|
||||
EVP_DigestFinal_ex(md_ctxt, digest, &md_len);
|
||||
return md_len;
|
||||
EVP_MD_CTX* md_ctxt{EVP_MD_CTX_new()};
|
||||
assert(md_ctxt != NULL);
|
||||
EVP_DigestInit_ex2(md_ctxt, md, NULL);
|
||||
EVP_DigestUpdate(md_ctxt, s.data(), s.length());
|
||||
EVP_DigestFinal_ex(md_ctxt, digest, &md_len);
|
||||
return md_len;
|
||||
}
|
||||
|
||||
bool is_valid(std::string const &s) {
|
||||
bool is_valid(std::string const& s)
|
||||
{
|
||||
MD5Digest digest;
|
||||
auto len = md5(digest, s);
|
||||
assert(len >= 3);
|
||||
return digest[0] == 0 && digest[1] == 0 && digest[2] == 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
unsigned i = 0;
|
||||
while (!is_valid(line + std::to_string(i))) {
|
||||
|
@@ -9,7 +9,8 @@
|
||||
// >=3 vowels
|
||||
// At least one double letter
|
||||
// No instances of 'ab', 'cd', 'pq', or 'xy'.
|
||||
bool is_nice(std::string const &s) noexcept {
|
||||
bool is_nice(std::string const& s) noexcept
|
||||
{
|
||||
unsigned vowel_count = 0;
|
||||
bool repeated = false;
|
||||
char last = '\0';
|
||||
@@ -22,8 +23,8 @@ bool is_nice(std::string const &s) noexcept {
|
||||
if (c == last) {
|
||||
repeated = true;
|
||||
}
|
||||
if ((last == 'a' && c == 'b') || (last == 'c' && c == 'd') ||
|
||||
(last == 'p' && c == 'q') || (last == 'x' && c == 'y')) {
|
||||
if ((last == 'a' && c == 'b') || (last == 'c' && c == 'd') || (last == 'p' && c == 'q') ||
|
||||
(last == 'x' && c == 'y')) {
|
||||
return false;
|
||||
}
|
||||
last = c;
|
||||
@@ -32,7 +33,8 @@ bool is_nice(std::string const &s) noexcept {
|
||||
return repeated && vowel_count >= 3;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned nice_strings;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
nice_strings += is_nice(line);
|
||||
|
@@ -8,7 +8,8 @@
|
||||
// Nice strings have:
|
||||
// repeated double letters - but not overlapping
|
||||
// repeated letters separated by one other.
|
||||
bool is_nice(std::string const &s) noexcept {
|
||||
bool is_nice(std::string const& s) noexcept
|
||||
{
|
||||
bool repeated_pair = false;
|
||||
bool repeated_sep = false;
|
||||
|
||||
@@ -34,7 +35,8 @@ bool is_nice(std::string const &s) noexcept {
|
||||
return repeated_pair && repeated_sep;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned nice_strings;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
nice_strings += is_nice(line);
|
||||
|
@@ -10,10 +10,11 @@ enum class Action { TurnOn, Toggle, TurnOff };
|
||||
using Point = std::pair<unsigned, unsigned>;
|
||||
|
||||
/// A command
|
||||
struct Command {
|
||||
Command(std::string const &s) {
|
||||
const char *re =
|
||||
"(turn on|toggle|turn off)\\s(\\d+),(\\d+)\\sthrough\\s(\\d+),(\\d+)";
|
||||
struct Command
|
||||
{
|
||||
Command(std::string const& s)
|
||||
{
|
||||
const char* re = "(turn on|toggle|turn off)\\s(\\d+),(\\d+)\\sthrough\\s(\\d+),(\\d+)";
|
||||
std::smatch m;
|
||||
if (!std::regex_search(s, m, std::regex(re))) {
|
||||
std::cerr << "Unable to interpret:" << s << "\n";
|
||||
@@ -21,11 +22,14 @@ struct Command {
|
||||
}
|
||||
if (m.str(1) == std::string("turn on")) {
|
||||
act_ = Action::TurnOn;
|
||||
} else if (m.str(1) == std::string("turn off")) {
|
||||
}
|
||||
else if (m.str(1) == std::string("turn off")) {
|
||||
act_ = Action::TurnOff;
|
||||
} else if (m.str(1) == std::string("toggle")) {
|
||||
}
|
||||
else if (m.str(1) == std::string("toggle")) {
|
||||
act_ = Action::Toggle;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
bottom_left_.first = std::stoul(m.str(2), nullptr, 10);
|
||||
@@ -40,8 +44,11 @@ struct Command {
|
||||
};
|
||||
|
||||
/// Array of lights
|
||||
template <unsigned N> struct Array {
|
||||
Array() noexcept {
|
||||
template<unsigned N>
|
||||
struct Array
|
||||
{
|
||||
Array() noexcept
|
||||
{
|
||||
for (unsigned i = 0; i < N; ++i) {
|
||||
for (unsigned j = 0; j < N; ++j) {
|
||||
lights_[i][j] = false;
|
||||
@@ -50,16 +57,15 @@ template <unsigned N> struct Array {
|
||||
}
|
||||
|
||||
/// Apply a command
|
||||
void apply(Command const &command) noexcept {
|
||||
void apply(Command const& command) noexcept
|
||||
{
|
||||
assert(command.bottom_left_.first < N);
|
||||
assert(command.bottom_left_.second < N);
|
||||
assert(command.top_right_.first < N);
|
||||
assert(command.top_right_.second < N);
|
||||
|
||||
for (unsigned i = command.bottom_left_.first; i <= command.top_right_.first;
|
||||
++i) {
|
||||
for (unsigned j = command.bottom_left_.second;
|
||||
j <= command.top_right_.second; ++j) {
|
||||
for (unsigned i = command.bottom_left_.first; i <= command.top_right_.first; ++i) {
|
||||
for (unsigned j = command.bottom_left_.second; j <= command.top_right_.second; ++j) {
|
||||
switch (command.act_) {
|
||||
case Action::TurnOn:
|
||||
lights_[i][j] = true;
|
||||
@@ -76,7 +82,8 @@ template <unsigned N> struct Array {
|
||||
}
|
||||
|
||||
/// How many lights are on
|
||||
unsigned num_on() const noexcept {
|
||||
unsigned num_on() const noexcept
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (unsigned i = 0; i < N; ++i) {
|
||||
for (unsigned j = 0; j < N; ++j) {
|
||||
@@ -88,7 +95,8 @@ template <unsigned N> struct Array {
|
||||
}
|
||||
|
||||
/// Output a bitmap
|
||||
void bitmap() const {
|
||||
void bitmap() const
|
||||
{
|
||||
std::cout << "P1\n" << N << " " << N << "\n";
|
||||
for (unsigned i = 0; i < N; ++i) {
|
||||
for (unsigned j = 0; j < N; ++j) {
|
||||
@@ -104,7 +112,8 @@ template <unsigned N> struct Array {
|
||||
bool lights_[N][N];
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Array<1000> arr;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
Command cmd(line);
|
||||
|
@@ -7,10 +7,11 @@
|
||||
|
||||
enum class Action { TurnOn, Toggle, TurnOff };
|
||||
using Point = std::pair<unsigned, unsigned>;
|
||||
struct Command {
|
||||
Command(std::string const &s) {
|
||||
const char *re =
|
||||
"(turn on|toggle|turn off)\\s(\\d+),(\\d+)\\sthrough\\s(\\d+),(\\d+)";
|
||||
struct Command
|
||||
{
|
||||
Command(std::string const& s)
|
||||
{
|
||||
const char* re = "(turn on|toggle|turn off)\\s(\\d+),(\\d+)\\sthrough\\s(\\d+),(\\d+)";
|
||||
std::smatch m;
|
||||
if (!std::regex_search(s, m, std::regex(re))) {
|
||||
std::cerr << "Unable to interpret:" << s << "\n";
|
||||
@@ -18,11 +19,14 @@ struct Command {
|
||||
}
|
||||
if (m.str(1) == std::string("turn on")) {
|
||||
act_ = Action::TurnOn;
|
||||
} else if (m.str(1) == std::string("turn off")) {
|
||||
}
|
||||
else if (m.str(1) == std::string("turn off")) {
|
||||
act_ = Action::TurnOff;
|
||||
} else if (m.str(1) == std::string("toggle")) {
|
||||
}
|
||||
else if (m.str(1) == std::string("toggle")) {
|
||||
act_ = Action::Toggle;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
bottom_left_.first = std::stoul(m.str(2), nullptr, 10);
|
||||
@@ -36,8 +40,11 @@ struct Command {
|
||||
Point top_right_;
|
||||
};
|
||||
|
||||
template <unsigned N> struct Array {
|
||||
Array() noexcept {
|
||||
template<unsigned N>
|
||||
struct Array
|
||||
{
|
||||
Array() noexcept
|
||||
{
|
||||
for (unsigned i = 0; i < N; ++i) {
|
||||
for (unsigned j = 0; j < N; ++j) {
|
||||
lights_[i][j] = 0;
|
||||
@@ -45,16 +52,15 @@ template <unsigned N> struct Array {
|
||||
}
|
||||
}
|
||||
|
||||
void apply(Command const &command) noexcept {
|
||||
void apply(Command const& command) noexcept
|
||||
{
|
||||
assert(command.bottom_left_.first < N);
|
||||
assert(command.bottom_left_.second < N);
|
||||
assert(command.top_right_.first < N);
|
||||
assert(command.top_right_.second < N);
|
||||
|
||||
for (unsigned i = command.bottom_left_.first; i <= command.top_right_.first;
|
||||
++i) {
|
||||
for (unsigned j = command.bottom_left_.second;
|
||||
j <= command.top_right_.second; ++j) {
|
||||
for (unsigned i = command.bottom_left_.first; i <= command.top_right_.first; ++i) {
|
||||
for (unsigned j = command.bottom_left_.second; j <= command.top_right_.second; ++j) {
|
||||
switch (command.act_) {
|
||||
case Action::TurnOn:
|
||||
++lights_[i][j];
|
||||
@@ -72,7 +78,8 @@ template <unsigned N> struct Array {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned brightness() const noexcept {
|
||||
unsigned brightness() const noexcept
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (unsigned i = 0; i < N; ++i) {
|
||||
for (unsigned j = 0; j < N; ++j) {
|
||||
@@ -83,7 +90,8 @@ template <unsigned N> struct Array {
|
||||
}
|
||||
|
||||
/// Output a bitmap
|
||||
void bitmap() const {
|
||||
void bitmap() const
|
||||
{
|
||||
unsigned max = 0;
|
||||
for (unsigned i = 0; i < N; ++i) {
|
||||
for (unsigned j = 0; j < N; ++j) {
|
||||
@@ -103,7 +111,8 @@ template <unsigned N> struct Array {
|
||||
unsigned lights_[N][N];
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Array<1000> arr;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
Command cmd(line);
|
||||
|
@@ -24,22 +24,28 @@
|
||||
// implementation)
|
||||
|
||||
// helper type for the visitor #4
|
||||
template <class... Ts> struct Overloaded : Ts... { using Ts::operator()...; };
|
||||
template<class... Ts>
|
||||
struct Overloaded : Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
// explicit deduction guide (not needed as of C++20)
|
||||
template <class... Ts> Overloaded(Ts...) -> Overloaded<Ts...>;
|
||||
template<class... Ts>
|
||||
Overloaded(Ts...) -> Overloaded<Ts...>;
|
||||
|
||||
/// Instruction action
|
||||
enum class Action {
|
||||
Set, ///< Set value
|
||||
And, ///< And two values
|
||||
Or, ///< Or two values
|
||||
LShift, ///< Left shift
|
||||
RShift, ///< Right shift
|
||||
Not ///< Bitwise not
|
||||
Set, ///< Set value
|
||||
And, ///< And two values
|
||||
Or, ///< Or two values
|
||||
LShift, ///< Left shift
|
||||
RShift, ///< Right shift
|
||||
Not ///< Bitwise not
|
||||
};
|
||||
|
||||
/// Pretty-print action
|
||||
std::ostream &operator<<(std::ostream &os, Action act) {
|
||||
std::ostream& operator<<(std::ostream& os, Action act)
|
||||
{
|
||||
switch (act) {
|
||||
case Action::Set:
|
||||
os << "SET";
|
||||
@@ -63,22 +69,24 @@ std::ostream &operator<<(std::ostream &os, Action act) {
|
||||
return os;
|
||||
}
|
||||
|
||||
using Value = std::uint16_t; ///< Value
|
||||
using Wire = std::string; ///< Wire name (string)
|
||||
using Signal = std::variant<Value, Wire>; ///< Either a wire or explicit value
|
||||
using Value = std::uint16_t; ///< Value
|
||||
using Wire = std::string; ///< Wire name (string)
|
||||
using Signal = std::variant<Value, Wire>; ///< Either a wire or explicit value
|
||||
|
||||
/// Outputter for a signal
|
||||
std::ostream &operator<<(std::ostream &os, Signal const &signal) {
|
||||
std::ostream& operator<<(std::ostream& os, Signal const& signal)
|
||||
{
|
||||
return std::visit(
|
||||
[&os](auto &&arg) -> std::ostream & {
|
||||
os << arg;
|
||||
return os;
|
||||
},
|
||||
signal);
|
||||
[&os](auto&& arg) -> std::ostream& {
|
||||
os << arg;
|
||||
return os;
|
||||
},
|
||||
signal);
|
||||
}
|
||||
|
||||
/** \brief An instruction. */
|
||||
struct Instruction {
|
||||
struct Instruction
|
||||
{
|
||||
/** \brief Construct an instruction.
|
||||
*
|
||||
* \subsection Grammar
|
||||
@@ -92,7 +100,8 @@ struct Instruction {
|
||||
* binop := signal op signal '->' wire
|
||||
* instr := binop | not | set
|
||||
*/
|
||||
Instruction(std::string const &s) {
|
||||
Instruction(std::string const& s)
|
||||
{
|
||||
if (parse_bin_op(s)) {
|
||||
return;
|
||||
}
|
||||
@@ -110,20 +119,22 @@ struct Instruction {
|
||||
Action action() const noexcept { return act_; }
|
||||
|
||||
/// Get the destination wire
|
||||
Wire const &dest() const noexcept { return dest_; }
|
||||
Wire const& dest() const noexcept { return dest_; }
|
||||
|
||||
/// Get the first (or only) source
|
||||
Signal const &src1() const noexcept { return src1_; }
|
||||
Signal const& src1() const noexcept { return src1_; }
|
||||
|
||||
/// Get the second source
|
||||
Signal const &src2() const noexcept {
|
||||
Signal const& src2() const noexcept
|
||||
{
|
||||
assert(act_ != Action::Set && act_ != Action::Not);
|
||||
return src2_;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Parse a <not> instruction. Return true if successful.
|
||||
bool parse_not(std::string const &s) {
|
||||
bool parse_not(std::string const& s)
|
||||
{
|
||||
if (s.substr(0, 4) == "NOT ") {
|
||||
std::string::size_type pos = 4;
|
||||
while (s[pos] == ' ') {
|
||||
@@ -135,7 +146,8 @@ private:
|
||||
}
|
||||
|
||||
/// Parse a <bin_op> instruction. Return true if successful.
|
||||
bool parse_bin_op(std::string const &s) {
|
||||
bool parse_bin_op(std::string const& s)
|
||||
{
|
||||
static const std::regex re("^([[:lower:][:digit:]]+) ([[:upper:]]+) "
|
||||
"([[:lower:][:digit:]]+) -> ([[:lower:]]+)");
|
||||
std::smatch m;
|
||||
@@ -145,13 +157,17 @@ private:
|
||||
|
||||
if (m.str(2) == "AND") {
|
||||
act_ = Action::And;
|
||||
} else if (m.str(2) == "OR") {
|
||||
}
|
||||
else if (m.str(2) == "OR") {
|
||||
act_ = Action::Or;
|
||||
} else if (m.str(2) == "LSHIFT") {
|
||||
}
|
||||
else if (m.str(2) == "LSHIFT") {
|
||||
act_ = Action::LShift;
|
||||
} else if (m.str(2) == "RSHIFT") {
|
||||
}
|
||||
else if (m.str(2) == "RSHIFT") {
|
||||
act_ = Action::RShift;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
dest_ = m.str(4);
|
||||
@@ -165,7 +181,8 @@ private:
|
||||
///
|
||||
/// Also used for the latter half of <not> parsing. ACT tells you what is
|
||||
/// being parsed. Returns true if parsing successful.
|
||||
bool parse_set(std::string const &s, Action act = Action::Set) {
|
||||
bool parse_set(std::string const& s, Action act = Action::Set)
|
||||
{
|
||||
static const std::regex re("^([[:lower:][:digit:]]+) -> ([[:lower:]]+)");
|
||||
std::smatch m;
|
||||
if (!std::regex_search(s, m, re)) {
|
||||
@@ -179,23 +196,26 @@ private:
|
||||
}
|
||||
|
||||
/// Make a Signal from a string.
|
||||
Signal make_signal(std::string const &s) {
|
||||
Signal make_signal(std::string const& s)
|
||||
{
|
||||
if (std::isdigit(s[0])) {
|
||||
auto u = std::stoul(s, nullptr, 10);
|
||||
assert(u <= UINT16_MAX);
|
||||
return Signal(static_cast<std::uint16_t>(u));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return Signal(s);
|
||||
}
|
||||
}
|
||||
|
||||
Action act_; ///< Action
|
||||
Wire dest_; ///< Destination wire
|
||||
Signal src1_, src2_; ///< Source signals
|
||||
Action act_; ///< Action
|
||||
Wire dest_; ///< Destination wire
|
||||
Signal src1_, src2_; ///< Source signals
|
||||
};
|
||||
|
||||
/// Outputter for an instruction.
|
||||
std::ostream &operator<<(std::ostream &os, Instruction const &instr) {
|
||||
std::ostream& operator<<(std::ostream& os, Instruction const& instr)
|
||||
{
|
||||
os << instr.action() << " " << instr.dest() << ", " << instr.src1();
|
||||
if (instr.action() != Action::Set && instr.action() != Action::Not) {
|
||||
os << ", " << instr.src2();
|
||||
@@ -204,56 +224,58 @@ std::ostream &operator<<(std::ostream &os, Instruction const &instr) {
|
||||
}
|
||||
|
||||
/// Ma
|
||||
using ValueMap = std::map<Wire, Value>; ///< Map wires to values
|
||||
using Instructions = std::vector<Instruction>; ///< Instructions to execute
|
||||
using ValueMap = std::map<Wire, Value>; ///< Map wires to values
|
||||
using Instructions = std::vector<Instruction>; ///< Instructions to execute
|
||||
|
||||
struct VM {
|
||||
struct VM
|
||||
{
|
||||
/// Add an instruction the the list we have
|
||||
void add_instr(Instruction const &instr) { instrs_.push_back(instr); }
|
||||
void add_instr(Instruction const& instr) { instrs_.push_back(instr); }
|
||||
|
||||
/// Has this wire a known value?
|
||||
bool has_value(Wire const &w) const noexcept {
|
||||
return values_.find(w) != values_.end();
|
||||
}
|
||||
bool has_value(Wire const& w) const noexcept { return values_.find(w) != values_.end(); }
|
||||
|
||||
/// Has this signal a known value?
|
||||
bool has_value(Signal const &s) const noexcept {
|
||||
return std::visit(Overloaded{[](Value v) { return true; },
|
||||
[&](Wire const &w) { return has_value(w); }},
|
||||
s);
|
||||
bool has_value(Signal const& s) const noexcept
|
||||
{
|
||||
return std::visit(
|
||||
Overloaded{[](Value v) { return true; }, [&](Wire const& w) { return has_value(w); }}, s);
|
||||
}
|
||||
|
||||
/// Get the value on the wire
|
||||
Value value(Wire const &w) const noexcept {
|
||||
Value value(Wire const& w) const noexcept
|
||||
{
|
||||
assert(has_value(w));
|
||||
return values_.find(w)->second;
|
||||
}
|
||||
|
||||
/// Get the value of a signal
|
||||
Value value(Signal const &s) const noexcept {
|
||||
return std::visit(Overloaded{[](Value v) { return v; },
|
||||
[&](Wire const &w) { return value(w); }},
|
||||
s);
|
||||
Value value(Signal const& s) const noexcept
|
||||
{
|
||||
return std::visit(
|
||||
Overloaded{[](Value v) { return v; }, [&](Wire const& w) { return value(w); }}, s);
|
||||
}
|
||||
|
||||
/// Set the value of a wire
|
||||
void value(Wire const &w, Value value) {
|
||||
void value(Wire const& w, Value value)
|
||||
{
|
||||
auto [it, success] = values_.insert({w, value});
|
||||
assert(success);
|
||||
}
|
||||
|
||||
/// Set the value of a signal
|
||||
void value(Signal const &s, Value v) {
|
||||
std::visit(Overloaded{[v](Value v2) { assert(v == v2); },
|
||||
[&, v](Wire const &w) { value(w, v); }},
|
||||
s);
|
||||
void value(Signal const& s, Value v)
|
||||
{
|
||||
std::visit(
|
||||
Overloaded{[v](Value v2) { assert(v == v2); }, [&, v](Wire const& w) { value(w, v); }}, s);
|
||||
}
|
||||
|
||||
/// Execute the instructions. Returns true if we have updated some wire
|
||||
/// values.
|
||||
bool execute() {
|
||||
bool execute()
|
||||
{
|
||||
bool done_anything = false;
|
||||
for (auto const &instr : instrs_) {
|
||||
for (auto const& instr : instrs_) {
|
||||
done_anything |= execute_instr(instr);
|
||||
}
|
||||
|
||||
@@ -268,15 +290,15 @@ private:
|
||||
* An instruction may not be executed if the incoming signals have not been
|
||||
* set yet.
|
||||
*/
|
||||
bool execute_instr(Instruction const &instr) {
|
||||
bool execute_instr(Instruction const& instr)
|
||||
{
|
||||
std::cout << instr << " # ";
|
||||
|
||||
// First of all check there is something to do - i.e. that the destination
|
||||
// register has not been set already.
|
||||
Wire dest = instr.dest();
|
||||
if (has_value(dest)) {
|
||||
std::cout << "already has value: " << dest << " = " << value(dest)
|
||||
<< "\n";
|
||||
std::cout << "already has value: " << dest << " = " << value(dest) << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -286,17 +308,13 @@ private:
|
||||
case Action::Not:
|
||||
return execute_single_src(instr, [](Value src) { return ~src; });
|
||||
case Action::And:
|
||||
return execute_double_src(
|
||||
instr, [](Value src1, Value src2) { return src1 & src2; });
|
||||
return execute_double_src(instr, [](Value src1, Value src2) { return src1 & src2; });
|
||||
case Action::Or:
|
||||
return execute_double_src(
|
||||
instr, [](Value src1, Value src2) { return src1 | src2; });
|
||||
return execute_double_src(instr, [](Value src1, Value src2) { return src1 | src2; });
|
||||
case Action::LShift:
|
||||
return execute_double_src(
|
||||
instr, [](Value src1, Value src2) { return src1 << src2; });
|
||||
return execute_double_src(instr, [](Value src1, Value src2) { return src1 << src2; });
|
||||
case Action::RShift:
|
||||
return execute_double_src(
|
||||
instr, [](Value src1, Value src2) { return src1 >> src2; });
|
||||
return execute_double_src(instr, [](Value src1, Value src2) { return src1 >> src2; });
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -307,8 +325,8 @@ private:
|
||||
* \param fn How to modify the source value to the dest.
|
||||
* \return True if we executed the function.
|
||||
*/
|
||||
bool execute_single_src(Instruction const &instr,
|
||||
std::function<Value(Value)> fn) {
|
||||
bool execute_single_src(Instruction const& instr, std::function<Value(Value)> fn)
|
||||
{
|
||||
Wire dest = instr.dest();
|
||||
Signal src = instr.src1();
|
||||
if (has_value(src)) {
|
||||
@@ -326,8 +344,8 @@ private:
|
||||
* \param fn How to modify the source values to the dest.
|
||||
* \return True if we executed the function.
|
||||
*/
|
||||
bool execute_double_src(Instruction const &instr,
|
||||
std::function<Value(Value, Value)> fn) {
|
||||
bool execute_double_src(Instruction const& instr, std::function<Value(Value, Value)> fn)
|
||||
{
|
||||
Wire dest = instr.dest();
|
||||
Signal src1 = instr.src1();
|
||||
Signal src2 = instr.src2();
|
||||
@@ -345,7 +363,8 @@ private:
|
||||
Instructions instrs_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
VM vm;
|
||||
|
||||
// Parse the input
|
||||
@@ -365,7 +384,8 @@ int main(int argc, char **argv) {
|
||||
std::cout << "a = ";
|
||||
if (!vm.has_value(a)) {
|
||||
std::cout << "UNSET\n";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << vm.value(a) << "\n";
|
||||
}
|
||||
|
||||
|
@@ -24,22 +24,28 @@
|
||||
// implementation)
|
||||
|
||||
// helper type for the visitor #4
|
||||
template <class... Ts> struct Overloaded : Ts... { using Ts::operator()...; };
|
||||
template<class... Ts>
|
||||
struct Overloaded : Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
// explicit deduction guide (not needed as of C++20)
|
||||
template <class... Ts> Overloaded(Ts...) -> Overloaded<Ts...>;
|
||||
template<class... Ts>
|
||||
Overloaded(Ts...) -> Overloaded<Ts...>;
|
||||
|
||||
/// Instruction action
|
||||
enum class Action {
|
||||
Set, ///< Set value
|
||||
And, ///< And two values
|
||||
Or, ///< Or two values
|
||||
LShift, ///< Left shift
|
||||
RShift, ///< Right shift
|
||||
Not ///< Bitwise not
|
||||
Set, ///< Set value
|
||||
And, ///< And two values
|
||||
Or, ///< Or two values
|
||||
LShift, ///< Left shift
|
||||
RShift, ///< Right shift
|
||||
Not ///< Bitwise not
|
||||
};
|
||||
|
||||
/// Pretty-print action
|
||||
std::ostream &operator<<(std::ostream &os, Action act) {
|
||||
std::ostream& operator<<(std::ostream& os, Action act)
|
||||
{
|
||||
switch (act) {
|
||||
case Action::Set:
|
||||
os << "SET";
|
||||
@@ -63,22 +69,24 @@ std::ostream &operator<<(std::ostream &os, Action act) {
|
||||
return os;
|
||||
}
|
||||
|
||||
using Value = std::uint16_t; ///< Value
|
||||
using Wire = std::string; ///< Wire name (string)
|
||||
using Signal = std::variant<Value, Wire>; ///< Either a wire or explicit value
|
||||
using Value = std::uint16_t; ///< Value
|
||||
using Wire = std::string; ///< Wire name (string)
|
||||
using Signal = std::variant<Value, Wire>; ///< Either a wire or explicit value
|
||||
|
||||
/// Outputter for a signal
|
||||
std::ostream &operator<<(std::ostream &os, Signal const &signal) {
|
||||
std::ostream& operator<<(std::ostream& os, Signal const& signal)
|
||||
{
|
||||
return std::visit(
|
||||
[&os](auto &&arg) -> std::ostream & {
|
||||
os << arg;
|
||||
return os;
|
||||
},
|
||||
signal);
|
||||
[&os](auto&& arg) -> std::ostream& {
|
||||
os << arg;
|
||||
return os;
|
||||
},
|
||||
signal);
|
||||
}
|
||||
|
||||
/** \brief An instruction. */
|
||||
struct Instruction {
|
||||
struct Instruction
|
||||
{
|
||||
/** \brief Construct an instruction.
|
||||
*
|
||||
* \subsection Grammar
|
||||
@@ -92,7 +100,8 @@ struct Instruction {
|
||||
* binop := signal op signal '->' wire
|
||||
* instr := binop | not | set
|
||||
*/
|
||||
Instruction(std::string const &s) {
|
||||
Instruction(std::string const& s)
|
||||
{
|
||||
if (parse_bin_op(s)) {
|
||||
return;
|
||||
}
|
||||
@@ -110,20 +119,22 @@ struct Instruction {
|
||||
Action action() const noexcept { return act_; }
|
||||
|
||||
/// Get the destination wire
|
||||
Wire const &dest() const noexcept { return dest_; }
|
||||
Wire const& dest() const noexcept { return dest_; }
|
||||
|
||||
/// Get the first (or only) source
|
||||
Signal const &src1() const noexcept { return src1_; }
|
||||
Signal const& src1() const noexcept { return src1_; }
|
||||
|
||||
/// Get the second source
|
||||
Signal const &src2() const noexcept {
|
||||
Signal const& src2() const noexcept
|
||||
{
|
||||
assert(act_ != Action::Set && act_ != Action::Not);
|
||||
return src2_;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Parse a <not> instruction. Return true if successful.
|
||||
bool parse_not(std::string const &s) {
|
||||
bool parse_not(std::string const& s)
|
||||
{
|
||||
if (s.substr(0, 4) == "NOT ") {
|
||||
std::string::size_type pos = 4;
|
||||
while (s[pos] == ' ') {
|
||||
@@ -135,7 +146,8 @@ private:
|
||||
}
|
||||
|
||||
/// Parse a <bin_op> instruction. Return true if successful.
|
||||
bool parse_bin_op(std::string const &s) {
|
||||
bool parse_bin_op(std::string const& s)
|
||||
{
|
||||
static const std::regex re("^([[:lower:][:digit:]]+) ([[:upper:]]+) "
|
||||
"([[:lower:][:digit:]]+) -> ([[:lower:]]+)");
|
||||
std::smatch m;
|
||||
@@ -145,13 +157,17 @@ private:
|
||||
|
||||
if (m.str(2) == "AND") {
|
||||
act_ = Action::And;
|
||||
} else if (m.str(2) == "OR") {
|
||||
}
|
||||
else if (m.str(2) == "OR") {
|
||||
act_ = Action::Or;
|
||||
} else if (m.str(2) == "LSHIFT") {
|
||||
}
|
||||
else if (m.str(2) == "LSHIFT") {
|
||||
act_ = Action::LShift;
|
||||
} else if (m.str(2) == "RSHIFT") {
|
||||
}
|
||||
else if (m.str(2) == "RSHIFT") {
|
||||
act_ = Action::RShift;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
dest_ = m.str(4);
|
||||
@@ -165,7 +181,8 @@ private:
|
||||
///
|
||||
/// Also used for the latter half of <not> parsing. ACT tells you what is
|
||||
/// being parsed. Returns true if parsing successful.
|
||||
bool parse_set(std::string const &s, Action act = Action::Set) {
|
||||
bool parse_set(std::string const& s, Action act = Action::Set)
|
||||
{
|
||||
static const std::regex re("^([[:lower:][:digit:]]+) -> ([[:lower:]]+)");
|
||||
std::smatch m;
|
||||
if (!std::regex_search(s, m, re)) {
|
||||
@@ -179,23 +196,26 @@ private:
|
||||
}
|
||||
|
||||
/// Make a Signal from a string.
|
||||
Signal make_signal(std::string const &s) {
|
||||
Signal make_signal(std::string const& s)
|
||||
{
|
||||
if (std::isdigit(s[0])) {
|
||||
auto u = std::stoul(s, nullptr, 10);
|
||||
assert(u <= UINT16_MAX);
|
||||
return Signal(static_cast<std::uint16_t>(u));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return Signal(s);
|
||||
}
|
||||
}
|
||||
|
||||
Action act_; ///< Action
|
||||
Wire dest_; ///< Destination wire
|
||||
Signal src1_, src2_; ///< Source signals
|
||||
Action act_; ///< Action
|
||||
Wire dest_; ///< Destination wire
|
||||
Signal src1_, src2_; ///< Source signals
|
||||
};
|
||||
|
||||
/// Outputter for an instruction.
|
||||
std::ostream &operator<<(std::ostream &os, Instruction const &instr) {
|
||||
std::ostream& operator<<(std::ostream& os, Instruction const& instr)
|
||||
{
|
||||
os << instr.action() << " " << instr.dest() << ", " << instr.src1();
|
||||
if (instr.action() != Action::Set && instr.action() != Action::Not) {
|
||||
os << ", " << instr.src2();
|
||||
@@ -204,56 +224,58 @@ std::ostream &operator<<(std::ostream &os, Instruction const &instr) {
|
||||
}
|
||||
|
||||
/// Ma
|
||||
using ValueMap = std::map<Wire, Value>; ///< Map wires to values
|
||||
using Instructions = std::vector<Instruction>; ///< Instructions to execute
|
||||
using ValueMap = std::map<Wire, Value>; ///< Map wires to values
|
||||
using Instructions = std::vector<Instruction>; ///< Instructions to execute
|
||||
|
||||
struct VM {
|
||||
struct VM
|
||||
{
|
||||
/// Add an instruction the the list we have
|
||||
void add_instr(Instruction const &instr) { instrs_.push_back(instr); }
|
||||
void add_instr(Instruction const& instr) { instrs_.push_back(instr); }
|
||||
|
||||
/// Has this wire a known value?
|
||||
bool has_value(Wire const &w) const noexcept {
|
||||
return values_.find(w) != values_.end();
|
||||
}
|
||||
bool has_value(Wire const& w) const noexcept { return values_.find(w) != values_.end(); }
|
||||
|
||||
/// Has this signal a known value?
|
||||
bool has_value(Signal const &s) const noexcept {
|
||||
return std::visit(Overloaded{[](Value v) { return true; },
|
||||
[&](Wire const &w) { return has_value(w); }},
|
||||
s);
|
||||
bool has_value(Signal const& s) const noexcept
|
||||
{
|
||||
return std::visit(
|
||||
Overloaded{[](Value v) { return true; }, [&](Wire const& w) { return has_value(w); }}, s);
|
||||
}
|
||||
|
||||
/// Get the value on the wire
|
||||
Value value(Wire const &w) const noexcept {
|
||||
Value value(Wire const& w) const noexcept
|
||||
{
|
||||
assert(has_value(w));
|
||||
return values_.find(w)->second;
|
||||
}
|
||||
|
||||
/// Get the value of a signal
|
||||
Value value(Signal const &s) const noexcept {
|
||||
return std::visit(Overloaded{[](Value v) { return v; },
|
||||
[&](Wire const &w) { return value(w); }},
|
||||
s);
|
||||
Value value(Signal const& s) const noexcept
|
||||
{
|
||||
return std::visit(
|
||||
Overloaded{[](Value v) { return v; }, [&](Wire const& w) { return value(w); }}, s);
|
||||
}
|
||||
|
||||
/// Set the value of a wire
|
||||
void value(Wire const &w, Value value) {
|
||||
void value(Wire const& w, Value value)
|
||||
{
|
||||
auto [it, success] = values_.insert({w, value});
|
||||
assert(success);
|
||||
}
|
||||
|
||||
/// Set the value of a signal
|
||||
void value(Signal const &s, Value v) {
|
||||
std::visit(Overloaded{[v](Value v2) { assert(v == v2); },
|
||||
[&, v](Wire const &w) { value(w, v); }},
|
||||
s);
|
||||
void value(Signal const& s, Value v)
|
||||
{
|
||||
std::visit(
|
||||
Overloaded{[v](Value v2) { assert(v == v2); }, [&, v](Wire const& w) { value(w, v); }}, s);
|
||||
}
|
||||
|
||||
/// Execute the instructions. Returns true if we have updated some wire
|
||||
/// values.
|
||||
bool execute() {
|
||||
bool execute()
|
||||
{
|
||||
bool done_anything = false;
|
||||
for (auto const &instr : instrs_) {
|
||||
for (auto const& instr : instrs_) {
|
||||
done_anything |= execute_instr(instr);
|
||||
}
|
||||
|
||||
@@ -268,15 +290,15 @@ private:
|
||||
* An instruction may not be executed if the incoming signals have not been
|
||||
* set yet.
|
||||
*/
|
||||
bool execute_instr(Instruction const &instr) {
|
||||
bool execute_instr(Instruction const& instr)
|
||||
{
|
||||
std::cout << instr << " # ";
|
||||
|
||||
// First of all check there is something to do - i.e. that the destination
|
||||
// register has not been set already.
|
||||
Wire dest = instr.dest();
|
||||
if (has_value(dest)) {
|
||||
std::cout << "already has value: " << dest << " = " << value(dest)
|
||||
<< "\n";
|
||||
std::cout << "already has value: " << dest << " = " << value(dest) << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -286,17 +308,13 @@ private:
|
||||
case Action::Not:
|
||||
return execute_single_src(instr, [](Value src) { return ~src; });
|
||||
case Action::And:
|
||||
return execute_double_src(
|
||||
instr, [](Value src1, Value src2) { return src1 & src2; });
|
||||
return execute_double_src(instr, [](Value src1, Value src2) { return src1 & src2; });
|
||||
case Action::Or:
|
||||
return execute_double_src(
|
||||
instr, [](Value src1, Value src2) { return src1 | src2; });
|
||||
return execute_double_src(instr, [](Value src1, Value src2) { return src1 | src2; });
|
||||
case Action::LShift:
|
||||
return execute_double_src(
|
||||
instr, [](Value src1, Value src2) { return src1 << src2; });
|
||||
return execute_double_src(instr, [](Value src1, Value src2) { return src1 << src2; });
|
||||
case Action::RShift:
|
||||
return execute_double_src(
|
||||
instr, [](Value src1, Value src2) { return src1 >> src2; });
|
||||
return execute_double_src(instr, [](Value src1, Value src2) { return src1 >> src2; });
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -307,8 +325,8 @@ private:
|
||||
* \param fn How to modify the source value to the dest.
|
||||
* \return True if we executed the function.
|
||||
*/
|
||||
bool execute_single_src(Instruction const &instr,
|
||||
std::function<Value(Value)> fn) {
|
||||
bool execute_single_src(Instruction const& instr, std::function<Value(Value)> fn)
|
||||
{
|
||||
Wire dest = instr.dest();
|
||||
Signal src = instr.src1();
|
||||
if (has_value(src)) {
|
||||
@@ -326,8 +344,8 @@ private:
|
||||
* \param fn How to modify the source values to the dest.
|
||||
* \return True if we executed the function.
|
||||
*/
|
||||
bool execute_double_src(Instruction const &instr,
|
||||
std::function<Value(Value, Value)> fn) {
|
||||
bool execute_double_src(Instruction const& instr, std::function<Value(Value, Value)> fn)
|
||||
{
|
||||
Wire dest = instr.dest();
|
||||
Signal src1 = instr.src1();
|
||||
Signal src2 = instr.src2();
|
||||
@@ -345,7 +363,8 @@ private:
|
||||
Instructions instrs_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
VM vm;
|
||||
|
||||
// Parse the input
|
||||
@@ -365,7 +384,8 @@ int main(int argc, char **argv) {
|
||||
std::cout << "a = ";
|
||||
if (!vm.has_value(a)) {
|
||||
std::cout << "UNSET\n";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << vm.value(a) << "\n";
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,8 @@
|
||||
|
||||
enum class State { Begin, Normal, Escape, Hex1, Hex2, End };
|
||||
|
||||
std::string unescape(std::string const &s) {
|
||||
std::string unescape(std::string const& s)
|
||||
{
|
||||
std::string unescaped;
|
||||
static const std::string hex = "0123456789abcdef0123456789ABCDEF";
|
||||
|
||||
@@ -23,9 +24,11 @@ std::string unescape(std::string const &s) {
|
||||
case State::Normal:
|
||||
if (c == '\\') {
|
||||
state = State::Escape;
|
||||
} else if (c == '"') {
|
||||
}
|
||||
else if (c == '"') {
|
||||
state = State::End;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
unescaped += c;
|
||||
}
|
||||
break;
|
||||
@@ -33,10 +36,12 @@ std::string unescape(std::string const &s) {
|
||||
if (c == '\\' || c == '"') {
|
||||
state = State::Normal;
|
||||
unescaped += c;
|
||||
} else if (c == 'x') {
|
||||
}
|
||||
else if (c == 'x') {
|
||||
byte = 0;
|
||||
state = State::Hex1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
@@ -62,16 +67,16 @@ std::string unescape(std::string const &s) {
|
||||
return unescaped;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned len = 0;
|
||||
|
||||
// Parse the input
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
std::string unescaped = unescape(line);
|
||||
len += line.length() - unescaped.length();
|
||||
std::cout << line << ": " << line.length() << " written bytes, "
|
||||
<< unescaped.length() << " memory bytes, difference: "
|
||||
<< line.length() - unescaped.length() << "\n";
|
||||
std::cout << line << ": " << line.length() << " written bytes, " << unescaped.length()
|
||||
<< " memory bytes, difference: " << line.length() - unescaped.length() << "\n";
|
||||
}
|
||||
|
||||
std::cout << len << "\n";
|
||||
|
@@ -6,7 +6,8 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
std::string escape(std::string const &s) {
|
||||
std::string escape(std::string const& s)
|
||||
{
|
||||
std::string escaped;
|
||||
escaped += '"';
|
||||
for (auto c : s) {
|
||||
@@ -19,16 +20,16 @@ std::string escape(std::string const &s) {
|
||||
return escaped;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned len = 0;
|
||||
|
||||
// Parse the input
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
std::string escaped = escape(line);
|
||||
len += escaped.length() - line.length();
|
||||
std::cout << line << ": " << line.length() << " memory bytes, "
|
||||
<< escaped.length() << " escaped bytes, difference: "
|
||||
<< escaped.length() - line.length() << "\n";
|
||||
std::cout << line << ": " << line.length() << " memory bytes, " << escaped.length()
|
||||
<< " escaped bytes, difference: " << escaped.length() - line.length() << "\n";
|
||||
}
|
||||
|
||||
std::cout << len << "\n";
|
||||
|
@@ -13,8 +13,10 @@ using Edge = std::pair<Node, Node>;
|
||||
using Nodes = std::set<Node>;
|
||||
using Edges = std::map<Edge, Weight>;
|
||||
|
||||
struct Graph {
|
||||
void add_edge(std::string const &s) {
|
||||
struct Graph
|
||||
{
|
||||
void add_edge(std::string const& s)
|
||||
{
|
||||
static const std::regex re("(.+) to (.+) = (\\d+)");
|
||||
std::smatch m;
|
||||
if (!std::regex_search(s, m, re)) {
|
||||
@@ -35,7 +37,8 @@ struct Graph {
|
||||
std::cout << n1 << " <-> " << n2 << " weight: " << w << "\n";
|
||||
}
|
||||
|
||||
Weight solve_tsp() const {
|
||||
Weight solve_tsp() const
|
||||
{
|
||||
Weight min_weight = ~0U;
|
||||
std::vector<Node> nodes(nodes_.begin(), nodes_.end());
|
||||
std::sort(nodes.begin(), nodes.end());
|
||||
@@ -64,7 +67,8 @@ struct Graph {
|
||||
Edges weights_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Graph g;
|
||||
|
||||
// Parse the input
|
||||
|
@@ -13,8 +13,10 @@ using Edge = std::pair<Node, Node>;
|
||||
using Nodes = std::set<Node>;
|
||||
using Edges = std::map<Edge, Weight>;
|
||||
|
||||
struct Graph {
|
||||
void add_edge(std::string const &s) {
|
||||
struct Graph
|
||||
{
|
||||
void add_edge(std::string const& s)
|
||||
{
|
||||
static const std::regex re("(.+) to (.+) = (\\d+)");
|
||||
std::smatch m;
|
||||
if (!std::regex_search(s, m, re)) {
|
||||
@@ -35,7 +37,8 @@ struct Graph {
|
||||
std::cout << n1 << " <-> " << n2 << " weight: " << w << "\n";
|
||||
}
|
||||
|
||||
Weight solve_tsp() const {
|
||||
Weight solve_tsp() const
|
||||
{
|
||||
Weight min_weight = ~0U;
|
||||
visit_all_perms([&min_weight](Weight w) {
|
||||
if (w < min_weight) {
|
||||
@@ -46,7 +49,8 @@ struct Graph {
|
||||
return min_weight;
|
||||
}
|
||||
|
||||
Weight solve_max_tsp() const {
|
||||
Weight solve_max_tsp() const
|
||||
{
|
||||
Weight max_weight = 0;
|
||||
visit_all_perms([&max_weight](Weight w) {
|
||||
if (w > max_weight) {
|
||||
@@ -58,7 +62,9 @@ struct Graph {
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Fn> void visit_all_perms(Fn fn) const {
|
||||
template<typename Fn>
|
||||
void visit_all_perms(Fn fn) const
|
||||
{
|
||||
std::vector<Node> nodes(nodes_.begin(), nodes_.end());
|
||||
std::sort(nodes.begin(), nodes.end());
|
||||
do {
|
||||
@@ -80,7 +86,8 @@ private:
|
||||
Edges weights_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Graph g;
|
||||
|
||||
// Parse the input
|
||||
|
@@ -7,7 +7,8 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
std::string look_and_say(std::string const &s) {
|
||||
std::string look_and_say(std::string const& s)
|
||||
{
|
||||
std::string result;
|
||||
for (std::string::size_type i = 0; i < s.length();) {
|
||||
unsigned num = 0;
|
||||
@@ -22,14 +23,13 @@ std::string look_and_say(std::string const &s) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
std::cout << "Application 0, length = " << line.length() << ": " << line
|
||||
<< "\n";
|
||||
std::cout << "Application 0, length = " << line.length() << ": " << line << "\n";
|
||||
for (int i = 1; i < 41; ++i) {
|
||||
line = look_and_say(line);
|
||||
std::cout << "Application " << i << ", length = " << line.length()
|
||||
<< "\n";
|
||||
std::cout << "Application " << i << ", length = " << line.length() << "\n";
|
||||
}
|
||||
std::cout << "Length: " << line.length() << "\n";
|
||||
}
|
||||
|
@@ -7,7 +7,8 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
std::string look_and_say(std::string const &s) {
|
||||
std::string look_and_say(std::string const& s)
|
||||
{
|
||||
std::string result;
|
||||
for (std::string::size_type i = 0; i < s.length();) {
|
||||
unsigned num = 0;
|
||||
@@ -22,14 +23,13 @@ std::string look_and_say(std::string const &s) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
std::cout << "Application 0, length = " << line.length() << ": " << line
|
||||
<< "\n";
|
||||
std::cout << "Application 0, length = " << line.length() << ": " << line << "\n";
|
||||
for (int i = 1; i < 51; ++i) {
|
||||
line = look_and_say(line);
|
||||
std::cout << "Application " << i << ", length = " << line.length()
|
||||
<< "\n";
|
||||
std::cout << "Application " << i << ", length = " << line.length() << "\n";
|
||||
}
|
||||
std::cout << "Length: " << line.length() << "\n";
|
||||
}
|
||||
|
@@ -9,7 +9,8 @@
|
||||
|
||||
bool illegal_char(char c) { return c == 'i' || c == 'l' || c == 'o'; }
|
||||
|
||||
void pre_advance_password(std::string &s) {
|
||||
void pre_advance_password(std::string& s)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
while (pos < s.length() && !illegal_char(s[pos])) {
|
||||
++pos;
|
||||
@@ -23,14 +24,16 @@ void pre_advance_password(std::string &s) {
|
||||
}
|
||||
}
|
||||
|
||||
void advance_password(std::string &s) {
|
||||
void advance_password(std::string& s)
|
||||
{
|
||||
auto pos = s.length() - 1;
|
||||
while (true) {
|
||||
if (s[pos] == 'z') {
|
||||
assert(pos != 0);
|
||||
s[pos] = 'a';
|
||||
pos -= 1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
++s[pos];
|
||||
if (illegal_char(s[pos])) {
|
||||
++s[pos];
|
||||
@@ -40,7 +43,8 @@ void advance_password(std::string &s) {
|
||||
}
|
||||
}
|
||||
|
||||
bool valid_password(std::string const &s) {
|
||||
bool valid_password(std::string const& s)
|
||||
{
|
||||
unsigned double_count = 0;
|
||||
bool run = false;
|
||||
char last2 = '\0';
|
||||
@@ -48,7 +52,8 @@ bool valid_password(std::string const &s) {
|
||||
for (auto c : s) {
|
||||
if (c == last && last2 != c) {
|
||||
++double_count;
|
||||
} else if (c == last + 1 && c == last2 + 2) {
|
||||
}
|
||||
else if (c == last + 1 && c == last2 + 2) {
|
||||
run = true;
|
||||
}
|
||||
last2 = last;
|
||||
@@ -58,7 +63,8 @@ bool valid_password(std::string const &s) {
|
||||
return double_count >= 2 && run;
|
||||
}
|
||||
|
||||
std::string next_password(std::string const &s) {
|
||||
std::string next_password(std::string const& s)
|
||||
{
|
||||
std::string result = s;
|
||||
pre_advance_password(result);
|
||||
do {
|
||||
@@ -67,11 +73,11 @@ std::string next_password(std::string const &s) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
std::string next = next_password(line);
|
||||
std::cout << "Current password: " << line << "; Next password: " << next
|
||||
<< "\n";
|
||||
std::cout << "Current password: " << line << "; Next password: " << next << "\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
@@ -9,7 +9,8 @@
|
||||
|
||||
bool illegal_char(char c) { return c == 'i' || c == 'l' || c == 'o'; }
|
||||
|
||||
void pre_advance_password(std::string &s) {
|
||||
void pre_advance_password(std::string& s)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
while (pos < s.length() && !illegal_char(s[pos])) {
|
||||
++pos;
|
||||
@@ -23,14 +24,16 @@ void pre_advance_password(std::string &s) {
|
||||
}
|
||||
}
|
||||
|
||||
void advance_password(std::string &s) {
|
||||
void advance_password(std::string& s)
|
||||
{
|
||||
auto pos = s.length() - 1;
|
||||
while (true) {
|
||||
if (s[pos] == 'z') {
|
||||
assert(pos != 0);
|
||||
s[pos] = 'a';
|
||||
pos -= 1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
++s[pos];
|
||||
if (illegal_char(s[pos])) {
|
||||
++s[pos];
|
||||
@@ -40,7 +43,8 @@ void advance_password(std::string &s) {
|
||||
}
|
||||
}
|
||||
|
||||
bool valid_password(std::string const &s) {
|
||||
bool valid_password(std::string const& s)
|
||||
{
|
||||
unsigned double_count = 0;
|
||||
bool run = false;
|
||||
char last2 = '\0';
|
||||
@@ -48,7 +52,8 @@ bool valid_password(std::string const &s) {
|
||||
for (auto c : s) {
|
||||
if (c == last && last2 != c) {
|
||||
++double_count;
|
||||
} else if (c == last + 1 && c == last2 + 2) {
|
||||
}
|
||||
else if (c == last + 1 && c == last2 + 2) {
|
||||
run = true;
|
||||
}
|
||||
last2 = last;
|
||||
@@ -58,7 +63,8 @@ bool valid_password(std::string const &s) {
|
||||
return double_count >= 2 && run;
|
||||
}
|
||||
|
||||
std::string next_password(std::string const &s) {
|
||||
std::string next_password(std::string const& s)
|
||||
{
|
||||
std::string result = s;
|
||||
pre_advance_password(result);
|
||||
do {
|
||||
@@ -67,7 +73,8 @@ std::string next_password(std::string const &s) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
std::string next = next_password(line);
|
||||
std::string next2 = next_password(next);
|
||||
|
@@ -7,7 +7,8 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
int parse_numbers(std::string const &s) {
|
||||
int parse_numbers(std::string const& s)
|
||||
{
|
||||
static const std::regex re("-?\\d+");
|
||||
std::string left = s;
|
||||
std::smatch m;
|
||||
@@ -20,7 +21,8 @@ int parse_numbers(std::string const &s) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int acc = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
acc += parse_numbers(line);
|
||||
|
@@ -8,7 +8,8 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
int do_parse(std::string const &s, std::string::size_type &pos) {
|
||||
int do_parse(std::string const& s, std::string::size_type& pos)
|
||||
{
|
||||
int result = 0;
|
||||
bool ignore = false;
|
||||
|
||||
@@ -16,16 +17,20 @@ int do_parse(std::string const &s, std::string::size_type &pos) {
|
||||
if (s[pos] == '{') {
|
||||
++pos;
|
||||
result += do_parse(s, pos);
|
||||
} else if (s[pos] == '[') {
|
||||
}
|
||||
else if (s[pos] == '[') {
|
||||
++pos;
|
||||
result += do_parse(s, pos);
|
||||
} else if (s[pos] == '}') {
|
||||
}
|
||||
else if (s[pos] == '}') {
|
||||
++pos;
|
||||
return ignore ? 0 : result;
|
||||
} else if (s[pos] == ']') {
|
||||
}
|
||||
else if (s[pos] == ']') {
|
||||
++pos;
|
||||
return result;
|
||||
} else if (s[pos] == '"') {
|
||||
}
|
||||
else if (s[pos] == '"') {
|
||||
++pos;
|
||||
auto e = s.find('"', pos);
|
||||
assert(e != std::string::npos);
|
||||
@@ -34,11 +39,13 @@ int do_parse(std::string const &s, std::string::size_type &pos) {
|
||||
ignore = true;
|
||||
}
|
||||
pos = e + 1;
|
||||
} else if (std::isdigit(s[pos]) || s[pos] == '-') {
|
||||
}
|
||||
else if (std::isdigit(s[pos]) || s[pos] == '-') {
|
||||
std::size_t len = 0;
|
||||
result += std::stoi(s.substr(pos), &len);
|
||||
pos += len;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(s[pos] == ',' || s[pos] == ':');
|
||||
++pos;
|
||||
}
|
||||
@@ -47,14 +54,16 @@ int do_parse(std::string const &s, std::string::size_type &pos) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int parse_numbers(std::string const &s) {
|
||||
int parse_numbers(std::string const& s)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
int result = do_parse(s, pos);
|
||||
assert(pos == s.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int acc = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
acc += parse_numbers(line);
|
||||
|
@@ -9,7 +9,8 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
struct Graph {
|
||||
struct Graph
|
||||
{
|
||||
using Node = std::string;
|
||||
using Weight = int;
|
||||
using Nodes = std::set<Node>;
|
||||
@@ -17,10 +18,10 @@ struct Graph {
|
||||
using Edge = std::pair<Node, Node>;
|
||||
using EdgeWeights = std::map<Edge, Weight>;
|
||||
|
||||
void add_edge(std::string const &s) {
|
||||
static const std::regex re(
|
||||
"(\\w+) would (gain|lose) (\\d+) happiness units? "
|
||||
"by sitting next to (\\w+).");
|
||||
void add_edge(std::string const& s)
|
||||
{
|
||||
static const std::regex re("(\\w+) would (gain|lose) (\\d+) happiness units? "
|
||||
"by sitting next to (\\w+).");
|
||||
std::smatch m;
|
||||
if (std::regex_search(s, m, re)) {
|
||||
nodes_.insert(m.str(1));
|
||||
@@ -30,18 +31,20 @@ struct Graph {
|
||||
delta = -delta;
|
||||
}
|
||||
weights_.insert({{m.str(1), m.str(4)}, delta});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
Weight max_happiness() const {
|
||||
Weight max_happiness() const
|
||||
{
|
||||
int max_happiness = INT_MIN;
|
||||
NodeList nl(nodes_.begin(), nodes_.end());
|
||||
std::sort(nl.begin(), nl.end());
|
||||
do {
|
||||
std::cout << "\r";
|
||||
for (auto const &s : nl) {
|
||||
for (auto const& s : nl) {
|
||||
std::cout << s << " ";
|
||||
}
|
||||
int h = happiness(nl);
|
||||
@@ -56,7 +59,8 @@ struct Graph {
|
||||
return max_happiness;
|
||||
}
|
||||
|
||||
int happiness(NodeList const &nl) const {
|
||||
int happiness(NodeList const& nl) const
|
||||
{
|
||||
int h = 0;
|
||||
h += weights_.find(std::make_pair(nl[nl.size() - 1], nl[0]))->second;
|
||||
h += weights_.find(std::make_pair(nl[0], nl[nl.size() - 1]))->second;
|
||||
@@ -71,7 +75,8 @@ struct Graph {
|
||||
EdgeWeights weights_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Graph g;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
g.add_edge(line);
|
||||
|
@@ -9,7 +9,8 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
struct Graph {
|
||||
struct Graph
|
||||
{
|
||||
Graph() { nodes_.insert("self"); }
|
||||
using Node = std::string;
|
||||
using Weight = int;
|
||||
@@ -18,10 +19,10 @@ struct Graph {
|
||||
using Edge = std::pair<Node, Node>;
|
||||
using EdgeWeights = std::map<Edge, Weight>;
|
||||
|
||||
void add_edge(std::string const &s) {
|
||||
static const std::regex re(
|
||||
"(\\w+) would (gain|lose) (\\d+) happiness units? "
|
||||
"by sitting next to (\\w+).");
|
||||
void add_edge(std::string const& s)
|
||||
{
|
||||
static const std::regex re("(\\w+) would (gain|lose) (\\d+) happiness units? "
|
||||
"by sitting next to (\\w+).");
|
||||
std::smatch m;
|
||||
if (std::regex_search(s, m, re)) {
|
||||
nodes_.insert(m.str(1));
|
||||
@@ -33,18 +34,20 @@ struct Graph {
|
||||
delta = -delta;
|
||||
}
|
||||
weights_.insert({{m.str(1), m.str(4)}, delta});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
Weight max_happiness() const {
|
||||
Weight max_happiness() const
|
||||
{
|
||||
int max_happiness = INT_MIN;
|
||||
NodeList nl(nodes_.begin(), nodes_.end());
|
||||
std::sort(nl.begin(), nl.end());
|
||||
do {
|
||||
std::cout << "\r";
|
||||
for (auto const &s : nl) {
|
||||
for (auto const& s : nl) {
|
||||
std::cout << s << " ";
|
||||
}
|
||||
int h = happiness(nl);
|
||||
@@ -59,7 +62,8 @@ struct Graph {
|
||||
return max_happiness;
|
||||
}
|
||||
|
||||
int happiness(NodeList const &nl) const {
|
||||
int happiness(NodeList const& nl) const
|
||||
{
|
||||
int h = 0;
|
||||
h += weights_.find(std::make_pair(nl[nl.size() - 1], nl[0]))->second;
|
||||
h += weights_.find(std::make_pair(nl[0], nl[nl.size() - 1]))->second;
|
||||
@@ -74,7 +78,8 @@ struct Graph {
|
||||
EdgeWeights weights_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Graph g;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
g.add_edge(line);
|
||||
|
@@ -11,7 +11,8 @@
|
||||
|
||||
using Distance = unsigned long;
|
||||
|
||||
Distance distance(std::string const &s, unsigned t) {
|
||||
Distance distance(std::string const& s, unsigned t)
|
||||
{
|
||||
static const std::regex re("(\\w+) can fly (\\d+) km/s for (\\d+) seconds?, "
|
||||
"but then must rest for (\\d+) seconds?.");
|
||||
std::smatch m;
|
||||
@@ -32,15 +33,17 @@ Distance distance(std::string const &s, unsigned t) {
|
||||
t = std::min(t, fly_time);
|
||||
result += t * fly_speed;
|
||||
|
||||
std::cout << m.str(1) << "(" << fly_speed << ", " << fly_time << ", "
|
||||
<< rest_time << ") = " << result << "\n";
|
||||
std::cout << m.str(1) << "(" << fly_speed << ", " << fly_time << ", " << rest_time
|
||||
<< ") = " << result << "\n";
|
||||
return result;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Distance max_d = 0;
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
max_d = std::max(max_d, distance(line, 2503));
|
||||
|
@@ -16,29 +16,30 @@ using Speed = unsigned long;
|
||||
struct Reindeer;
|
||||
using ReindeerSet = std::set<Reindeer>;
|
||||
|
||||
struct Reindeer {
|
||||
Reindeer(std::string const &s) {
|
||||
static const std::regex re(
|
||||
"(\\w+) can fly (\\d+) km/s for (\\d+) seconds?, "
|
||||
"but then must rest for (\\d+) seconds?.");
|
||||
struct Reindeer
|
||||
{
|
||||
Reindeer(std::string const& s)
|
||||
{
|
||||
static const std::regex re("(\\w+) can fly (\\d+) km/s for (\\d+) seconds?, "
|
||||
"but then must rest for (\\d+) seconds?.");
|
||||
std::smatch m;
|
||||
if (std::regex_search(s, m, re)) {
|
||||
name_ = m.str(1);
|
||||
speed_ = std::stoul(m.str(2));
|
||||
fly_time_ = std::stoul(m.str(3));
|
||||
rest_time_ = std::stoul(m.str(4));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(Reindeer const &rhs) const noexcept {
|
||||
return name_ < rhs.name_;
|
||||
}
|
||||
bool operator<(Reindeer const& rhs) const noexcept { return name_ < rhs.name_; }
|
||||
|
||||
std::string const &name() const { return name_; }
|
||||
std::string const& name() const { return name_; }
|
||||
|
||||
Distance distance(Time t) const { // Period and number of them
|
||||
Distance distance(Time t) const
|
||||
{ // Period and number of them
|
||||
Time period = fly_time_ + rest_time_;
|
||||
unsigned periods = t / period;
|
||||
|
||||
@@ -59,7 +60,8 @@ struct Reindeer {
|
||||
Time rest_time_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ReindeerSet reindeer;
|
||||
|
||||
for (std::string line; std::getline(std::cin, line);) {
|
||||
@@ -68,21 +70,20 @@ int main(int argc, char **argv) {
|
||||
|
||||
std::map<std::string, unsigned> score;
|
||||
for (unsigned t = 1; t < 2504; ++t) {
|
||||
auto it =
|
||||
std::max_element(reindeer.begin(), reindeer.end(),
|
||||
[t](Reindeer const &lhs, Reindeer const &rhs) -> bool {
|
||||
return lhs.distance(t) < rhs.distance(t);
|
||||
});
|
||||
auto it = std::max_element(reindeer.begin(), reindeer.end(),
|
||||
[t](Reindeer const& lhs, Reindeer const& rhs) -> bool {
|
||||
return lhs.distance(t) < rhs.distance(t);
|
||||
});
|
||||
auto [iit, success] = score.insert({it->name(), 1});
|
||||
if (!success) {
|
||||
iit->second++;
|
||||
}
|
||||
}
|
||||
|
||||
auto it = std::max_element(score.begin(), score.end(),
|
||||
[](auto const &lhs, auto const &rhs) -> bool {
|
||||
return lhs.second < rhs.second;
|
||||
});
|
||||
auto it =
|
||||
std::max_element(score.begin(), score.end(), [](auto const& lhs, auto const& rhs) -> bool {
|
||||
return lhs.second < rhs.second;
|
||||
});
|
||||
std::cout << it->first << " wins with a score of " << it->second << "\n";
|
||||
|
||||
return 0;
|
||||
|
@@ -12,8 +12,10 @@
|
||||
using Score = long;
|
||||
using PropertyMap = std::map<std::string, Score>;
|
||||
|
||||
struct Ingredient {
|
||||
explicit Ingredient(std::string const &s) {
|
||||
struct Ingredient
|
||||
{
|
||||
explicit Ingredient(std::string const& s)
|
||||
{
|
||||
auto colon = s.find(':');
|
||||
name_ = s.substr(0, colon);
|
||||
auto suffix = s.substr(colon + 1);
|
||||
@@ -22,25 +24,24 @@ struct Ingredient {
|
||||
static const std::regex re(",? (\\w+) (-?\\d+)");
|
||||
std::smatch m;
|
||||
if (std::regex_search(suffix, m, re)) {
|
||||
auto [it, success] =
|
||||
properties_.insert({m.str(1), std::stol(m.str(2))});
|
||||
auto [it, success] = properties_.insert({m.str(1), std::stol(m.str(2))});
|
||||
assert(success);
|
||||
std::cout << " " << it->first << ": " << it->second << "\n";
|
||||
suffix = m.suffix();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(Ingredient const &rhs) const noexcept {
|
||||
return name_ < rhs.name_;
|
||||
}
|
||||
bool operator<(Ingredient const& rhs) const noexcept { return name_ < rhs.name_; }
|
||||
|
||||
std::string const &name() const noexcept { return name_; }
|
||||
std::string const& name() const noexcept { return name_; }
|
||||
|
||||
void update_score(Score amount, PropertyMap &totals) const {
|
||||
for (auto const &kv : properties_) {
|
||||
void update_score(Score amount, PropertyMap& totals) const
|
||||
{
|
||||
for (auto const& kv : properties_) {
|
||||
if (kv.first == "calories") {
|
||||
continue;
|
||||
}
|
||||
@@ -56,20 +57,20 @@ private:
|
||||
PropertyMap properties_;
|
||||
};
|
||||
|
||||
struct Ingredients {
|
||||
void add_ingredient(std::string const &s) {
|
||||
ingredients_.push_back(Ingredient(s));
|
||||
}
|
||||
struct Ingredients
|
||||
{
|
||||
void add_ingredient(std::string const& s) { ingredients_.push_back(Ingredient(s)); }
|
||||
|
||||
Score best_combination(Score amount) const {
|
||||
Score best_combination(Score amount) const
|
||||
{
|
||||
PropertyMap totals;
|
||||
return best_combination(amount, ingredients_.begin(), 0UL, totals);
|
||||
}
|
||||
|
||||
private:
|
||||
Score best_combination(Score amount,
|
||||
std::vector<Ingredient>::const_iterator it,
|
||||
Score best_score, PropertyMap &totals) const {
|
||||
Score best_combination(Score amount, std::vector<Ingredient>::const_iterator it, Score best_score,
|
||||
PropertyMap& totals) const
|
||||
{
|
||||
it->update_score(amount, totals);
|
||||
auto it2 = it;
|
||||
++it2;
|
||||
@@ -83,17 +84,17 @@ private:
|
||||
for (auto allocation = amount - 1; allocation > 0; --allocation) {
|
||||
it->update_score(-1, totals);
|
||||
best_score =
|
||||
std::max(best_score, best_combination(amount - allocation, it2,
|
||||
best_score, totals));
|
||||
std::max(best_score, best_combination(amount - allocation, it2, best_score, totals));
|
||||
}
|
||||
it->update_score(-1, totals);
|
||||
|
||||
return best_score;
|
||||
}
|
||||
|
||||
Score calculate_score(PropertyMap const &totals) const {
|
||||
Score calculate_score(PropertyMap const& totals) const
|
||||
{
|
||||
Score r = 1;
|
||||
for (auto const &kv : totals) {
|
||||
for (auto const& kv : totals) {
|
||||
if (kv.first == "calories") {
|
||||
continue;
|
||||
}
|
||||
@@ -109,7 +110,8 @@ private:
|
||||
std::vector<Ingredient> ingredients_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Ingredients ingredients;
|
||||
|
||||
std::string line;
|
||||
|
@@ -12,8 +12,10 @@
|
||||
using Score = long;
|
||||
using PropertyMap = std::map<std::string, Score>;
|
||||
|
||||
struct Ingredient {
|
||||
explicit Ingredient(std::string const &s) {
|
||||
struct Ingredient
|
||||
{
|
||||
explicit Ingredient(std::string const& s)
|
||||
{
|
||||
auto colon = s.find(':');
|
||||
name_ = s.substr(0, colon);
|
||||
auto suffix = s.substr(colon + 1);
|
||||
@@ -22,25 +24,24 @@ struct Ingredient {
|
||||
static const std::regex re(",? (\\w+) (-?\\d+)");
|
||||
std::smatch m;
|
||||
if (std::regex_search(suffix, m, re)) {
|
||||
auto [it, success] =
|
||||
properties_.insert({m.str(1), std::stol(m.str(2))});
|
||||
auto [it, success] = properties_.insert({m.str(1), std::stol(m.str(2))});
|
||||
assert(success);
|
||||
std::cout << " " << it->first << ": " << it->second << "\n";
|
||||
suffix = m.suffix();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(Ingredient const &rhs) const noexcept {
|
||||
return name_ < rhs.name_;
|
||||
}
|
||||
bool operator<(Ingredient const& rhs) const noexcept { return name_ < rhs.name_; }
|
||||
|
||||
std::string const &name() const noexcept { return name_; }
|
||||
std::string const& name() const noexcept { return name_; }
|
||||
|
||||
void update_score(Score amount, PropertyMap &totals) const {
|
||||
for (auto const &kv : properties_) {
|
||||
void update_score(Score amount, PropertyMap& totals) const
|
||||
{
|
||||
for (auto const& kv : properties_) {
|
||||
auto [it, success] = totals.insert({kv.first, amount * kv.second});
|
||||
if (!success) {
|
||||
it->second += amount * kv.second;
|
||||
@@ -53,20 +54,20 @@ private:
|
||||
PropertyMap properties_;
|
||||
};
|
||||
|
||||
struct Ingredients {
|
||||
void add_ingredient(std::string const &s) {
|
||||
ingredients_.push_back(Ingredient(s));
|
||||
}
|
||||
struct Ingredients
|
||||
{
|
||||
void add_ingredient(std::string const& s) { ingredients_.push_back(Ingredient(s)); }
|
||||
|
||||
Score best_combination(Score amount) const {
|
||||
Score best_combination(Score amount) const
|
||||
{
|
||||
PropertyMap totals;
|
||||
return best_combination(amount, ingredients_.begin(), 0UL, totals);
|
||||
}
|
||||
|
||||
private:
|
||||
Score best_combination(Score amount,
|
||||
std::vector<Ingredient>::const_iterator it,
|
||||
Score best_score, PropertyMap &totals) const {
|
||||
Score best_combination(Score amount, std::vector<Ingredient>::const_iterator it, Score best_score,
|
||||
PropertyMap& totals) const
|
||||
{
|
||||
it->update_score(amount, totals);
|
||||
auto it2 = it;
|
||||
++it2;
|
||||
@@ -80,18 +81,18 @@ private:
|
||||
for (auto allocation = amount - 1; allocation > 0; --allocation) {
|
||||
it->update_score(-1, totals);
|
||||
best_score =
|
||||
std::max(best_score, best_combination(amount - allocation, it2,
|
||||
best_score, totals));
|
||||
std::max(best_score, best_combination(amount - allocation, it2, best_score, totals));
|
||||
}
|
||||
it->update_score(-1, totals);
|
||||
|
||||
return best_score;
|
||||
}
|
||||
|
||||
Score calculate_score(PropertyMap const &totals) const {
|
||||
Score calculate_score(PropertyMap const& totals) const
|
||||
{
|
||||
Score r = 1;
|
||||
Score calories = 0;
|
||||
for (auto const &kv : totals) {
|
||||
for (auto const& kv : totals) {
|
||||
if (kv.first == "calories") {
|
||||
calories += kv.second;
|
||||
continue;
|
||||
@@ -110,7 +111,8 @@ private:
|
||||
std::vector<Ingredient> ingredients_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Ingredients ingredients;
|
||||
|
||||
std::string line;
|
||||
|
@@ -22,7 +22,8 @@ static const InfoMap the_real_aunt_sue({{"children", 3},
|
||||
{"cars", 2},
|
||||
{"perfumes", 1}});
|
||||
|
||||
bool matches_sue(std::string const &s) {
|
||||
bool matches_sue(std::string const& s)
|
||||
{
|
||||
assert(s.substr(0, 4) == "Sue ");
|
||||
std::size_t pos = 4;
|
||||
std::size_t len = 0;
|
||||
@@ -34,7 +35,8 @@ bool matches_sue(std::string const &s) {
|
||||
while (pos < s.size()) {
|
||||
if (s[pos] == ' ' || s[pos] == ',') {
|
||||
++pos;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto colon = s.find(':', pos);
|
||||
assert(colon != std::string::npos);
|
||||
std::string name = s.substr(pos, colon - pos);
|
||||
@@ -57,7 +59,8 @@ bool matches_sue(std::string const &s) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
if (matches_sue(line)) {
|
||||
|
@@ -28,7 +28,8 @@ static const InfoMap the_real_aunt_sue({{"children", {3, Equality}},
|
||||
{"cars", {2, Equality}},
|
||||
{"perfumes", {1, Equality}}});
|
||||
|
||||
bool matches_sue(std::string const &s) {
|
||||
bool matches_sue(std::string const& s)
|
||||
{
|
||||
assert(s.substr(0, 4) == "Sue ");
|
||||
std::size_t pos = 4;
|
||||
std::size_t len = 0;
|
||||
@@ -40,7 +41,8 @@ bool matches_sue(std::string const &s) {
|
||||
while (pos < s.size()) {
|
||||
if (s[pos] == ' ' || s[pos] == ',') {
|
||||
++pos;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto colon = s.find(':', pos);
|
||||
assert(colon != std::string::npos);
|
||||
std::string name = s.substr(pos, colon - pos);
|
||||
@@ -63,7 +65,8 @@ bool matches_sue(std::string const &s) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
if (matches_sue(line)) {
|
||||
|
@@ -14,9 +14,9 @@ constexpr Quantity total = 150;
|
||||
|
||||
using Quantities = std::vector<Quantity>;
|
||||
|
||||
unsigned count_combinations(Quantities::const_iterator it,
|
||||
Quantities::const_iterator end, Quantity amount,
|
||||
unsigned depth = 0) {
|
||||
unsigned count_combinations(Quantities::const_iterator it, Quantities::const_iterator end,
|
||||
Quantity amount, unsigned depth = 0)
|
||||
{
|
||||
// We have no room for this container
|
||||
std::cout << std::string(depth, ' ') << *it << ": " << amount << "\n";
|
||||
if (amount < *it) {
|
||||
@@ -36,7 +36,8 @@ unsigned count_combinations(Quantities::const_iterator it,
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned count_combinations(Quantities const &containers) {
|
||||
unsigned count_combinations(Quantities const& containers)
|
||||
{
|
||||
unsigned result = 0;
|
||||
for (auto it = containers.begin(); it != containers.end(); ++it) {
|
||||
result += count_combinations(it, containers.end(), total);
|
||||
@@ -44,7 +45,8 @@ unsigned count_combinations(Quantities const &containers) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
Quantities containers;
|
||||
while (std::getline(std::cin, line)) {
|
||||
|
@@ -14,11 +14,11 @@ constexpr Quantity total = 150;
|
||||
|
||||
using Quantities = std::vector<Quantity>;
|
||||
|
||||
template <typename Fn1, typename Fn2>
|
||||
unsigned count_combinations(Quantities::const_iterator it,
|
||||
Quantities::const_iterator end, Quantity amount,
|
||||
unsigned depth, Fn1 base_result,
|
||||
unsigned init_addend, Fn2 adder) {
|
||||
template<typename Fn1, typename Fn2>
|
||||
unsigned count_combinations(Quantities::const_iterator it, Quantities::const_iterator end,
|
||||
Quantity amount, unsigned depth, Fn1 base_result, unsigned init_addend,
|
||||
Fn2 adder)
|
||||
{
|
||||
// We have no room for this container
|
||||
std::cout << std::string(depth, ' ') << *it << ": " << amount;
|
||||
if (amount < *it) {
|
||||
@@ -36,45 +36,42 @@ unsigned count_combinations(Quantities::const_iterator it,
|
||||
amount -= *it;
|
||||
auto result = init_addend;
|
||||
while (++it != end) {
|
||||
auto child_score = count_combinations(it, end, amount, depth + 1,
|
||||
base_result, init_addend, adder);
|
||||
auto child_score =
|
||||
count_combinations(it, end, amount, depth + 1, base_result, init_addend, adder);
|
||||
result = adder(result, child_score);
|
||||
}
|
||||
std::cout << std::string(depth, ' ') << "Recursion result: " << result
|
||||
<< "\n";
|
||||
std::cout << std::string(depth, ' ') << "Recursion result: " << result << "\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Fn1, typename Fn2>
|
||||
unsigned count_combinations(Quantities const &containers, Quantity amount,
|
||||
Fn1 base_result, unsigned init_addend, Fn2 adder) {
|
||||
template<typename Fn1, typename Fn2>
|
||||
unsigned count_combinations(Quantities const& containers, Quantity amount, Fn1 base_result,
|
||||
unsigned init_addend, Fn2 adder)
|
||||
{
|
||||
unsigned result = init_addend;
|
||||
for (auto it = containers.begin(); it != containers.end(); ++it) {
|
||||
result = adder(result, count_combinations(it, containers.end(), total, 0,
|
||||
base_result, init_addend, adder));
|
||||
result = adder(
|
||||
result, count_combinations(it, containers.end(), total, 0, base_result, init_addend, adder));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned find_shortest_combination(Quantities const &containers) {
|
||||
unsigned find_shortest_combination(Quantities const& containers)
|
||||
{
|
||||
return count_combinations(
|
||||
containers, total, [](unsigned depth) { return depth; }, UINT_MAX,
|
||||
[](unsigned current, unsigned child_score) {
|
||||
return std::min(current, child_score);
|
||||
});
|
||||
containers, total, [](unsigned depth) { return depth; }, UINT_MAX,
|
||||
[](unsigned current, unsigned child_score) { return std::min(current, child_score); });
|
||||
}
|
||||
|
||||
unsigned count_min_length_combinations(Quantities const &containers,
|
||||
unsigned expected_depth) {
|
||||
unsigned count_min_length_combinations(Quantities const& containers, unsigned expected_depth)
|
||||
{
|
||||
return count_combinations(
|
||||
containers, total,
|
||||
[expected_depth](unsigned depth) { return depth == expected_depth; }, 0,
|
||||
[](unsigned current, unsigned child_score) {
|
||||
return current + child_score;
|
||||
});
|
||||
containers, total, [expected_depth](unsigned depth) { return depth == expected_depth; }, 0,
|
||||
[](unsigned current, unsigned child_score) { return current + child_score; });
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
Quantities containers;
|
||||
while (std::getline(std::cin, line)) {
|
||||
|
@@ -10,9 +10,10 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
struct ConwayState {
|
||||
ConwayState(std::size_t width, std::string const &s)
|
||||
: width_(width), state_(width_ * width_, 0) {
|
||||
struct ConwayState
|
||||
{
|
||||
ConwayState(std::size_t width, std::string const& s) : width_(width), state_(width_ * width_, 0)
|
||||
{
|
||||
assert(s.size() == width_ * width_);
|
||||
|
||||
for (std::size_t i = 0; i < state_.size(); ++i) {
|
||||
@@ -22,7 +23,8 @@ struct ConwayState {
|
||||
}
|
||||
}
|
||||
|
||||
ConwayState next_state() const {
|
||||
ConwayState next_state() const
|
||||
{
|
||||
ConwayState next(*this);
|
||||
for (std::size_t i = 0; i < state_.size(); ++i) {
|
||||
if (state_[i] == (2 | active_) || state_[i] == (3 | active_)) {
|
||||
@@ -36,23 +38,22 @@ struct ConwayState {
|
||||
return next;
|
||||
}
|
||||
|
||||
std::size_t num_active() const {
|
||||
return std::accumulate(state_.begin(), state_.end(), std::size_t(0),
|
||||
[](std::size_t current, unsigned char info) {
|
||||
return current + ((info & active_) != 0);
|
||||
});
|
||||
std::size_t num_active() const
|
||||
{
|
||||
return std::accumulate(
|
||||
state_.begin(), state_.end(), std::size_t(0),
|
||||
[](std::size_t current, unsigned char info) { return current + ((info & active_) != 0); });
|
||||
}
|
||||
|
||||
private:
|
||||
void flip(std::size_t idx) {
|
||||
void flip(std::size_t idx)
|
||||
{
|
||||
state_[idx] = state_[idx] ^ active_;
|
||||
int delta = ((state_[idx] & active_) == active_) ? 1 : -1;
|
||||
std::size_t row = idx / width_;
|
||||
std::size_t col = idx % width_;
|
||||
for (std::size_t r = std::max(std::size_t(1), row) - 1;
|
||||
r < std::min(width_, row + 2); ++r) {
|
||||
for (std::size_t c = std::max(std::size_t(1), col) - 1;
|
||||
c < std::min(width_, col + 2); ++c) {
|
||||
for (std::size_t r = std::max(std::size_t(1), row) - 1; r < std::min(width_, row + 2); ++r) {
|
||||
for (std::size_t c = std::max(std::size_t(1), col) - 1; c < std::min(width_, col + 2); ++c) {
|
||||
if (r == row && c == col) {
|
||||
continue;
|
||||
}
|
||||
@@ -65,10 +66,11 @@ private:
|
||||
std::vector<unsigned char> state_;
|
||||
|
||||
static constexpr unsigned char active_ = 0x80;
|
||||
friend std::ostream &operator<<(std::ostream &os, ConwayState const &state);
|
||||
friend std::ostream& operator<<(std::ostream& os, ConwayState const& state);
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, ConwayState const &state) {
|
||||
std::ostream& operator<<(std::ostream& os, ConwayState const& state)
|
||||
{
|
||||
std::size_t c = 0;
|
||||
for (auto s : state.state_) {
|
||||
os << (s & ConwayState::active_ ? '#' : '.');
|
||||
@@ -82,7 +84,8 @@ std::ostream &operator<<(std::ostream &os, ConwayState const &state) {
|
||||
return os;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
std::size_t width = 0;
|
||||
std::string init;
|
||||
|
@@ -10,9 +10,10 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
struct ConwayState {
|
||||
ConwayState(std::size_t width, std::string const &s)
|
||||
: width_(width), state_(width_ * width_, 0) {
|
||||
struct ConwayState
|
||||
{
|
||||
ConwayState(std::size_t width, std::string const& s) : width_(width), state_(width_ * width_, 0)
|
||||
{
|
||||
assert(s.size() == width_ * width_);
|
||||
|
||||
flip(0);
|
||||
@@ -27,11 +28,11 @@ struct ConwayState {
|
||||
}
|
||||
}
|
||||
|
||||
ConwayState next_state() const {
|
||||
ConwayState next_state() const
|
||||
{
|
||||
ConwayState next(*this);
|
||||
for (std::size_t i = 0; i < state_.size(); ++i) {
|
||||
if (i == 0 || i == width_ - 1 || i == width_ * (width_ - 1) ||
|
||||
i == width_ * width_ - 1) {
|
||||
if (i == 0 || i == width_ - 1 || i == width_ * (width_ - 1) || i == width_ * width_ - 1) {
|
||||
continue;
|
||||
}
|
||||
if (state_[i] == (2 | active_) || state_[i] == (3 | active_)) {
|
||||
@@ -45,23 +46,22 @@ struct ConwayState {
|
||||
return next;
|
||||
}
|
||||
|
||||
std::size_t num_active() const {
|
||||
return std::accumulate(state_.begin(), state_.end(), std::size_t(0),
|
||||
[](std::size_t current, unsigned char info) {
|
||||
return current + ((info & active_) != 0);
|
||||
});
|
||||
std::size_t num_active() const
|
||||
{
|
||||
return std::accumulate(
|
||||
state_.begin(), state_.end(), std::size_t(0),
|
||||
[](std::size_t current, unsigned char info) { return current + ((info & active_) != 0); });
|
||||
}
|
||||
|
||||
private:
|
||||
void flip(std::size_t idx) {
|
||||
void flip(std::size_t idx)
|
||||
{
|
||||
state_[idx] = state_[idx] ^ active_;
|
||||
int delta = ((state_[idx] & active_) == active_) ? 1 : -1;
|
||||
std::size_t row = idx / width_;
|
||||
std::size_t col = idx % width_;
|
||||
for (std::size_t r = std::max(std::size_t(1), row) - 1;
|
||||
r < std::min(width_, row + 2); ++r) {
|
||||
for (std::size_t c = std::max(std::size_t(1), col) - 1;
|
||||
c < std::min(width_, col + 2); ++c) {
|
||||
for (std::size_t r = std::max(std::size_t(1), row) - 1; r < std::min(width_, row + 2); ++r) {
|
||||
for (std::size_t c = std::max(std::size_t(1), col) - 1; c < std::min(width_, col + 2); ++c) {
|
||||
if (r == row && c == col) {
|
||||
continue;
|
||||
}
|
||||
@@ -74,10 +74,11 @@ private:
|
||||
std::vector<unsigned char> state_;
|
||||
|
||||
static constexpr unsigned char active_ = 0x80;
|
||||
friend std::ostream &operator<<(std::ostream &os, ConwayState const &state);
|
||||
friend std::ostream& operator<<(std::ostream& os, ConwayState const& state);
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, ConwayState const &state) {
|
||||
std::ostream& operator<<(std::ostream& os, ConwayState const& state)
|
||||
{
|
||||
std::size_t c = 0;
|
||||
for (auto s : state.state_) {
|
||||
os << (s & ConwayState::active_ ? '#' : '.');
|
||||
@@ -91,7 +92,8 @@ std::ostream &operator<<(std::ostream &os, ConwayState const &state) {
|
||||
return os;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string line;
|
||||
std::size_t width = 0;
|
||||
std::string init;
|
||||
|
@@ -10,30 +10,31 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::multimap<std::string, std::string> replacements;
|
||||
bool collecting_replacements = true;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
if (line.empty()) {
|
||||
collecting_replacements = false;
|
||||
} else if (collecting_replacements) {
|
||||
}
|
||||
else if (collecting_replacements) {
|
||||
auto sep = line.find(" => ");
|
||||
replacements.insert({line.substr(0, sep), line.substr(sep + 4)});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::set<std::string> new_molecules;
|
||||
for (unsigned pos = 0; pos < line.size(); ++pos) {
|
||||
auto [it, ite] = replacements.equal_range(line.substr(pos, 1));
|
||||
while (it != ite) {
|
||||
new_molecules.insert(line.substr(0, pos) + it->second +
|
||||
line.substr(pos + 1));
|
||||
new_molecules.insert(line.substr(0, pos) + it->second + line.substr(pos + 1));
|
||||
++it;
|
||||
}
|
||||
if (pos < line.size() - 1) {
|
||||
auto [it, ite] = replacements.equal_range(line.substr(pos, 2));
|
||||
while (it != ite) {
|
||||
new_molecules.insert(line.substr(0, pos) + it->second +
|
||||
line.substr(pos + 2));
|
||||
new_molecules.insert(line.substr(0, pos) + it->second + line.substr(pos + 2));
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
@@ -13,10 +13,11 @@
|
||||
#include <unordered_set>
|
||||
#include <variant>
|
||||
|
||||
template <typename Map>
|
||||
std::size_t dedup(Map const &replacements, std::string &molecule) {
|
||||
template<typename Map>
|
||||
std::size_t dedup(Map const& replacements, std::string& molecule)
|
||||
{
|
||||
std::size_t steps = 0;
|
||||
for (auto const &kv : replacements) {
|
||||
for (auto const& kv : replacements) {
|
||||
if (kv.first != kv.second + kv.second) {
|
||||
continue;
|
||||
}
|
||||
@@ -24,8 +25,7 @@ std::size_t dedup(Map const &replacements, std::string &molecule) {
|
||||
do {
|
||||
pos = molecule.find(kv.first);
|
||||
if (pos != std::string::npos) {
|
||||
molecule = molecule.substr(0, pos) + kv.second +
|
||||
molecule.substr(pos + kv.first.size());
|
||||
molecule = molecule.substr(0, pos) + kv.second + molecule.substr(pos + kv.first.size());
|
||||
++steps;
|
||||
}
|
||||
} while (pos != std::string::npos);
|
||||
@@ -143,21 +143,22 @@ find_molecule(std::unordered_map<std::string, std::string> const &replacements,
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Map>
|
||||
bool is_good_replacement(Map const &replacements, std::string const &nm,
|
||||
std::size_t pos, std::size_t replace_len) {
|
||||
for (auto const &kv : replacements) {
|
||||
template<typename Map>
|
||||
bool is_good_replacement(Map const& replacements, std::string const& nm, std::size_t pos,
|
||||
std::size_t replace_len)
|
||||
{
|
||||
for (auto const& kv : replacements) {
|
||||
auto left = std::max(kv.first.size(), pos) - kv.first.size();
|
||||
if (nm.substr(left, kv.first.size() * 2 + replace_len).find(kv.first) !=
|
||||
std::string::npos) {
|
||||
if (nm.substr(left, kv.first.size() * 2 + replace_len).find(kv.first) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Map>
|
||||
std::size_t find_molecule(Map &replacements, std::string const &molecule) {
|
||||
template<typename Map>
|
||||
std::size_t find_molecule(Map& replacements, std::string const& molecule)
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 g(rd());
|
||||
while (true) {
|
||||
@@ -167,7 +168,7 @@ std::size_t find_molecule(Map &replacements, std::string const &molecule) {
|
||||
std::size_t steps = 0;
|
||||
do {
|
||||
changed = false;
|
||||
for (auto const &kv : replacements) {
|
||||
for (auto const& kv : replacements) {
|
||||
auto pos = m.find(kv.first);
|
||||
if (pos != std::string::npos) {
|
||||
m = m.substr(0, pos) + kv.second + m.substr(pos + kv.first.length());
|
||||
@@ -185,17 +186,20 @@ std::size_t find_molecule(Map &replacements, std::string const &molecule) {
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::vector<std::pair<std::string, std::string>> replacements;
|
||||
bool collecting_replacements = true;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
if (line.empty()) {
|
||||
collecting_replacements = false;
|
||||
} else if (collecting_replacements) {
|
||||
}
|
||||
else if (collecting_replacements) {
|
||||
auto sep = line.find(" => ");
|
||||
replacements.push_back({line.substr(sep + 4), line.substr(0, sep)});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << line << "\n";
|
||||
auto time = find_molecule(replacements, line);
|
||||
std::cout << "Solution: " << time << "\n";
|
||||
|
@@ -1,37 +1,39 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main() {
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
int main()
|
||||
{
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
|
||||
auto target{std::stoul(line)};
|
||||
auto target{std::stoul(line)};
|
||||
|
||||
/* This is a really stupid way to do this in terms of effort, but it produces the right answer and doesn't involve
|
||||
* thinking too much:
|
||||
*
|
||||
* n is the current house we're at.
|
||||
/* This is a really stupid way to do this in terms of effort, but it produces the right answer and
|
||||
* doesn't involve thinking too much:
|
||||
*
|
||||
* n is the current house we're at.
|
||||
*/
|
||||
for (auto n{2UL}; true; ++n) {
|
||||
auto amt{0UL};
|
||||
/* Find the number of presents delivered to house `n`. We do this by walking through all
|
||||
* numbers <= sqrt(n) and seeing if they are a factor. If so we add presents for that number
|
||||
* (i) and also (n/i), being careful not to double count for square roots. This reduces the
|
||||
* amount of work we have to do significantly.
|
||||
*/
|
||||
for (auto n{2UL}; true; ++n) {
|
||||
auto amt{0UL};
|
||||
/* Find the number of presents delivered to house `n`. We do this by walking through all numbers <= sqrt(n) and
|
||||
* seeing if they are a factor. If so we add presents for that number (i) and also (n/i), being careful not to
|
||||
* double count for square roots. This reduces the amount of work we have to do significantly.
|
||||
*/
|
||||
for (auto i{1UL}; i <= (n / i); ++i) {
|
||||
if (n % i == 0) {
|
||||
amt += i * 10;
|
||||
if (i != n / i) {
|
||||
amt += (n / i) * 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (amt >= target) {
|
||||
std::cout << "Target: " << target << " met at: " << n << " with amount: " << amt << '\n';
|
||||
return EXIT_SUCCESS;
|
||||
for (auto i{1UL}; i <= (n / i); ++i) {
|
||||
if (n % i == 0) {
|
||||
amt += i * 10;
|
||||
if (i != n / i) {
|
||||
amt += (n / i) * 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (amt >= target) {
|
||||
std::cout << "Target: " << target << " met at: " << n << " with amount: " << amt << '\n';
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_FAILURE;
|
||||
}
|
@@ -1,42 +1,45 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main() {
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
int main()
|
||||
{
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
|
||||
auto target{std::stoul(line)};
|
||||
auto target{std::stoul(line)};
|
||||
|
||||
/* This is a really stupid way to do this in terms of effort, but it produces the right answer and doesn't involve
|
||||
* thinking too much:
|
||||
/* This is a really stupid way to do this in terms of effort, but it produces the right answer and
|
||||
* doesn't involve thinking too much:
|
||||
*
|
||||
* n is the current house we're at.
|
||||
*/
|
||||
for (auto n{2UL}; true; ++n) {
|
||||
auto amt{0UL};
|
||||
/* Find the number of presents delivered to house `n`. We do this by walking through all
|
||||
* numbers <= sqrt(n) and seeing if they are a factor. If so we add presents for that number
|
||||
* (i) and also (n/i), being careful not to double count for square roots. This reduces the
|
||||
* amount of work we have to do significantly.
|
||||
*
|
||||
* n is the current house we're at.
|
||||
* For the second part we also check to ensure we've not at the 51st delivery or greater for
|
||||
* this elf.
|
||||
*/
|
||||
for (auto n{2UL}; true; ++n) {
|
||||
auto amt{0UL};
|
||||
/* Find the number of presents delivered to house `n`. We do this by walking through all numbers <= sqrt(n) and
|
||||
* seeing if they are a factor. If so we add presents for that number (i) and also (n/i), being careful not to
|
||||
* double count for square roots. This reduces the amount of work we have to do significantly.
|
||||
*
|
||||
* For the second part we also check to ensure we've not at the 51st delivery or greater for this elf.
|
||||
*/
|
||||
for (auto i{1UL}; i <= (n / i); ++i) {
|
||||
if (n % i == 0) {
|
||||
auto i2{n / i};
|
||||
if (i2 <= 50) {
|
||||
amt += i * 11;
|
||||
}
|
||||
if (i <= 50 && i != i2) {
|
||||
amt += i2 * 11;
|
||||
}
|
||||
}
|
||||
for (auto i{1UL}; i <= (n / i); ++i) {
|
||||
if (n % i == 0) {
|
||||
auto i2{n / i};
|
||||
if (i2 <= 50) {
|
||||
amt += i * 11;
|
||||
}
|
||||
if (amt >= target) {
|
||||
std::cout << "Target: " << target << " met at: " << n << " with amount: " << amt << '\n';
|
||||
return EXIT_SUCCESS;
|
||||
if (i <= 50 && i != i2) {
|
||||
amt += i2 * 11;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (amt >= target) {
|
||||
std::cout << "Target: " << target << " met at: " << n << " with amount: " << amt << '\n';
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_FAILURE;
|
||||
}
|
@@ -1,127 +1,136 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <numeric>
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
struct Item {
|
||||
std::string name_;
|
||||
unsigned long cost_;
|
||||
unsigned long damage_;
|
||||
unsigned long armour_;
|
||||
struct Item
|
||||
{
|
||||
std::string name_;
|
||||
unsigned long cost_;
|
||||
unsigned long damage_;
|
||||
unsigned long armour_;
|
||||
|
||||
bool operator==(Item const& rhs) const { return name_ == rhs.name_; }
|
||||
bool operator==(Item const& rhs) const { return name_ == rhs.name_; }
|
||||
};
|
||||
|
||||
struct Person {
|
||||
Person(unsigned long hp, unsigned long damage, unsigned long armour) : name_("Enemy"), hp_(hp),
|
||||
cost_(std::numeric_limits<unsigned>::max()),
|
||||
damage_(damage),
|
||||
armour_(armour) {}
|
||||
struct Person
|
||||
{
|
||||
Person(unsigned long hp, unsigned long damage, unsigned long armour)
|
||||
: name_("Enemy"), hp_(hp), cost_(std::numeric_limits<unsigned>::max()), damage_(damage),
|
||||
armour_(armour)
|
||||
{
|
||||
}
|
||||
|
||||
Person(Item const &weapon, Item const &armour, Item const &left_ring, Item const &right_ring) :
|
||||
name_("Player: "s + weapon.name_ + ", "s + armour.name_ + ", "s + left_ring.name_ + ", " +
|
||||
right_ring.name_),
|
||||
hp_(100),
|
||||
cost_(weapon.cost_ + armour.cost_ + left_ring.cost_ + right_ring.cost_),
|
||||
damage_(weapon.damage_ + armour.damage_ + left_ring.damage_ + right_ring.damage_),
|
||||
armour_(weapon.armour_ + armour.armour_ + left_ring.armour_ + right_ring.armour_) {}
|
||||
Person(Item const& weapon, Item const& armour, Item const& left_ring, Item const& right_ring)
|
||||
: name_("Player: "s + weapon.name_ + ", "s + armour.name_ + ", "s + left_ring.name_ + ", " +
|
||||
right_ring.name_),
|
||||
hp_(100), cost_(weapon.cost_ + armour.cost_ + left_ring.cost_ + right_ring.cost_),
|
||||
damage_(weapon.damage_ + armour.damage_ + left_ring.damage_ + right_ring.damage_),
|
||||
armour_(weapon.armour_ + armour.armour_ + left_ring.armour_ + right_ring.armour_)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned get_attacked(Person const &attacker) {
|
||||
auto damage{(attacker.damage_ > armour_) ? attacker.damage_ - armour_ : 1};
|
||||
hp_ = (hp_ > damage) ? hp_ - damage : 0;
|
||||
return hp_;
|
||||
}
|
||||
unsigned get_attacked(Person const& attacker)
|
||||
{
|
||||
auto damage{(attacker.damage_ > armour_) ? attacker.damage_ - armour_ : 1};
|
||||
hp_ = (hp_ > damage) ? hp_ - damage : 0;
|
||||
return hp_;
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
unsigned long hp_;
|
||||
unsigned long cost_;
|
||||
unsigned long damage_;
|
||||
unsigned long armour_;
|
||||
std::string name_;
|
||||
unsigned long hp_;
|
||||
unsigned long cost_;
|
||||
unsigned long damage_;
|
||||
unsigned long armour_;
|
||||
};
|
||||
|
||||
unsigned long get_value(std::string const &begin) {
|
||||
std::string line;
|
||||
if (!std::getline(std::cin, line)) {
|
||||
std::cerr << "Missing line in input\n";
|
||||
std::exit(1);
|
||||
}
|
||||
if (line.substr(0, begin.length()) != begin) {
|
||||
std::cerr << "Line doesn't begin with: " << begin << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
return std::stoul(line.substr(begin.length()));
|
||||
unsigned long get_value(std::string const& begin)
|
||||
{
|
||||
std::string line;
|
||||
if (!std::getline(std::cin, line)) {
|
||||
std::cerr << "Missing line in input\n";
|
||||
std::exit(1);
|
||||
}
|
||||
if (line.substr(0, begin.length()) != begin) {
|
||||
std::cerr << "Line doesn't begin with: " << begin << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
return std::stoul(line.substr(begin.length()));
|
||||
}
|
||||
|
||||
bool me_beats_enemy(Person me, Person enemy) {
|
||||
while (true) {
|
||||
enemy.get_attacked(me);
|
||||
if (enemy.hp_ == 0) { return true; }
|
||||
me.get_attacked(enemy);
|
||||
if (me.hp_ == 0) { return false; }
|
||||
bool me_beats_enemy(Person me, Person enemy)
|
||||
{
|
||||
while (true) {
|
||||
enemy.get_attacked(me);
|
||||
if (enemy.hp_ == 0) {
|
||||
return true;
|
||||
}
|
||||
me.get_attacked(enemy);
|
||||
if (me.hp_ == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
const std::string hp_begin{"Hit Points: "};
|
||||
const std::string d_begin{"Damage: "};
|
||||
const std::string a_begin{"Armor: "};
|
||||
int main()
|
||||
{
|
||||
const std::string hp_begin{"Hit Points: "};
|
||||
const std::string d_begin{"Damage: "};
|
||||
const std::string a_begin{"Armor: "};
|
||||
|
||||
const std::vector<Item> weapons{
|
||||
{"Dagger", 8, 4, 0},
|
||||
{"Shortsword", 10, 5, 0},
|
||||
{"Warhammer", 25, 6, 0},
|
||||
{"Longsword", 40, 7, 0},
|
||||
{"Greataxe", 74, 8, 0},
|
||||
};
|
||||
const std::vector<Item> weapons{
|
||||
{"Dagger", 8, 4, 0}, {"Shortsword", 10, 5, 0}, {"Warhammer", 25, 6, 0},
|
||||
{"Longsword", 40, 7, 0}, {"Greataxe", 74, 8, 0},
|
||||
};
|
||||
|
||||
const std::vector<Item> armours{
|
||||
{"Nothing", 0, 0, 0},
|
||||
{"Leather", 13, 0, 1},
|
||||
{"Chainmail", 31, 0, 2},
|
||||
{"Splintmail", 53, 0, 3},
|
||||
{"Bandedmail", 75, 0, 4},
|
||||
{"Platedmail", 102, 0, 5},
|
||||
};
|
||||
const std::vector<Item> armours{
|
||||
{"Nothing", 0, 0, 0}, {"Leather", 13, 0, 1}, {"Chainmail", 31, 0, 2},
|
||||
{"Splintmail", 53, 0, 3}, {"Bandedmail", 75, 0, 4}, {"Platedmail", 102, 0, 5},
|
||||
};
|
||||
|
||||
const std::vector<Item> rings{
|
||||
{"Empty", 0, 0, 0},
|
||||
{"Damage +1", 25, 1, 0},
|
||||
{"Damage +2", 50, 2, 0},
|
||||
{"Damage +3", 100, 3, 0},
|
||||
{"Defense +1", 20, 0, 1},
|
||||
{"Defense +2", 40, 0, 2},
|
||||
{"Defense +3", 80, 0, 3},
|
||||
};
|
||||
const std::vector<Item> rings{
|
||||
{"Empty", 0, 0, 0}, {"Damage +1", 25, 1, 0}, {"Damage +2", 50, 2, 0},
|
||||
{"Damage +3", 100, 3, 0}, {"Defense +1", 20, 0, 1}, {"Defense +2", 40, 0, 2},
|
||||
{"Defense +3", 80, 0, 3},
|
||||
};
|
||||
|
||||
auto enemy_hp{get_value(hp_begin)};
|
||||
auto enemy_damage{get_value(d_begin)};
|
||||
auto enemy_armour{get_value(a_begin)};
|
||||
|
||||
auto enemy_hp{get_value(hp_begin)};
|
||||
auto enemy_damage{get_value(d_begin)};
|
||||
auto enemy_armour{get_value(a_begin)};
|
||||
Person best_result{0, 0, 0};
|
||||
Person enemy{enemy_hp, enemy_damage, enemy_armour};
|
||||
|
||||
Person best_result{0, 0, 0};
|
||||
Person enemy{enemy_hp, enemy_damage, enemy_armour};
|
||||
|
||||
for (auto const &weapon: weapons) {
|
||||
if (weapon.cost_ > best_result.cost_) { continue; }
|
||||
for (auto const &armour: armours) {
|
||||
if (weapon.cost_ + armour.cost_ > best_result.cost_) { continue; }
|
||||
for (auto const &left_ring: rings) {
|
||||
if (weapon.cost_ + armour.cost_ + left_ring.cost_ > best_result.cost_) { continue; }
|
||||
for (auto const &right_ring: rings) {
|
||||
if (weapon.cost_ + armour.cost_ + left_ring.cost_ + right_ring.cost_ >
|
||||
best_result.cost_) { continue; }
|
||||
if (left_ring == right_ring) continue;
|
||||
Person me{weapon, armour, left_ring, right_ring};
|
||||
if (me_beats_enemy(me, enemy) && me.cost_ < best_result.cost_) {
|
||||
best_result = me;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto const& weapon : weapons) {
|
||||
if (weapon.cost_ > best_result.cost_) {
|
||||
continue;
|
||||
}
|
||||
for (auto const& armour : armours) {
|
||||
if (weapon.cost_ + armour.cost_ > best_result.cost_) {
|
||||
continue;
|
||||
}
|
||||
for (auto const& left_ring : rings) {
|
||||
if (weapon.cost_ + armour.cost_ + left_ring.cost_ > best_result.cost_) {
|
||||
continue;
|
||||
}
|
||||
for (auto const& right_ring : rings) {
|
||||
if (weapon.cost_ + armour.cost_ + left_ring.cost_ + right_ring.cost_ >
|
||||
best_result.cost_) {
|
||||
continue;
|
||||
}
|
||||
if (left_ring == right_ring)
|
||||
continue;
|
||||
Person me{weapon, armour, left_ring, right_ring};
|
||||
if (me_beats_enemy(me, enemy) && me.cost_ < best_result.cost_) {
|
||||
best_result = me;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Best person: " << best_result.name_ << " at cost of " << best_result.cost_ << '\n';
|
||||
std::cout << "Best person: " << best_result.name_ << " at cost of " << best_result.cost_ << '\n';
|
||||
}
|
@@ -1,130 +1,132 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <numeric>
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
struct Item {
|
||||
std::string name_;
|
||||
unsigned long cost_;
|
||||
unsigned long damage_;
|
||||
unsigned long armour_;
|
||||
struct Item
|
||||
{
|
||||
std::string name_;
|
||||
unsigned long cost_;
|
||||
unsigned long damage_;
|
||||
unsigned long armour_;
|
||||
|
||||
bool operator==(Item const& rhs) const { return name_ == rhs.name_; }
|
||||
bool operator==(Item const& rhs) const { return name_ == rhs.name_; }
|
||||
};
|
||||
|
||||
struct Person {
|
||||
Person(unsigned long hp, unsigned long damage, unsigned long armour) : name_("Enemy"), hp_(hp),
|
||||
cost_(std::numeric_limits<unsigned>::max()),
|
||||
damage_(damage),
|
||||
armour_(armour) {}
|
||||
struct Person
|
||||
{
|
||||
Person(unsigned long hp, unsigned long damage, unsigned long armour)
|
||||
: name_("Enemy"), hp_(hp), cost_(std::numeric_limits<unsigned>::max()), damage_(damage),
|
||||
armour_(armour)
|
||||
{
|
||||
}
|
||||
|
||||
Person(Item const &weapon, Item const &armour, Item const &left_ring, Item const &right_ring) :
|
||||
name_("Player: "s + weapon.name_ + ", "s + armour.name_ + ", "s + left_ring.name_ + ", " +
|
||||
right_ring.name_),
|
||||
hp_(100),
|
||||
cost_(weapon.cost_ + armour.cost_ + left_ring.cost_ + right_ring.cost_),
|
||||
damage_(weapon.damage_ + armour.damage_ + left_ring.damage_ + right_ring.damage_),
|
||||
armour_(weapon.armour_ + armour.armour_ + left_ring.armour_ + right_ring.armour_) {}
|
||||
Person(Item const& weapon, Item const& armour, Item const& left_ring, Item const& right_ring)
|
||||
: name_("Player: "s + weapon.name_ + ", "s + armour.name_ + ", "s + left_ring.name_ + ", " +
|
||||
right_ring.name_),
|
||||
hp_(100), cost_(weapon.cost_ + armour.cost_ + left_ring.cost_ + right_ring.cost_),
|
||||
damage_(weapon.damage_ + armour.damage_ + left_ring.damage_ + right_ring.damage_),
|
||||
armour_(weapon.armour_ + armour.armour_ + left_ring.armour_ + right_ring.armour_)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned get_attacked(Person const &attacker) {
|
||||
auto damage{(attacker.damage_ > armour_) ? attacker.damage_ - armour_ : 1};
|
||||
hp_ = (hp_ > damage) ? hp_ - damage : 0;
|
||||
return hp_;
|
||||
}
|
||||
unsigned get_attacked(Person const& attacker)
|
||||
{
|
||||
auto damage{(attacker.damage_ > armour_) ? attacker.damage_ - armour_ : 1};
|
||||
hp_ = (hp_ > damage) ? hp_ - damage : 0;
|
||||
return hp_;
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
unsigned long hp_;
|
||||
unsigned long cost_;
|
||||
unsigned long damage_;
|
||||
unsigned long armour_;
|
||||
std::string name_;
|
||||
unsigned long hp_;
|
||||
unsigned long cost_;
|
||||
unsigned long damage_;
|
||||
unsigned long armour_;
|
||||
};
|
||||
|
||||
unsigned long get_value(std::string const &begin) {
|
||||
std::string line;
|
||||
if (!std::getline(std::cin, line)) {
|
||||
std::cerr << "Missing line in input\n";
|
||||
std::exit(1);
|
||||
}
|
||||
if (line.substr(0, begin.length()) != begin) {
|
||||
std::cerr << "Line doesn't begin with: " << begin << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
return std::stoul(line.substr(begin.length()));
|
||||
unsigned long get_value(std::string const& begin)
|
||||
{
|
||||
std::string line;
|
||||
if (!std::getline(std::cin, line)) {
|
||||
std::cerr << "Missing line in input\n";
|
||||
std::exit(1);
|
||||
}
|
||||
if (line.substr(0, begin.length()) != begin) {
|
||||
std::cerr << "Line doesn't begin with: " << begin << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
return std::stoul(line.substr(begin.length()));
|
||||
}
|
||||
|
||||
bool me_beats_enemy(Person me, Person enemy) {
|
||||
while (true) {
|
||||
enemy.get_attacked(me);
|
||||
if (enemy.hp_ == 0) { return true; }
|
||||
me.get_attacked(enemy);
|
||||
if (me.hp_ == 0) { return false; }
|
||||
bool me_beats_enemy(Person me, Person enemy)
|
||||
{
|
||||
while (true) {
|
||||
enemy.get_attacked(me);
|
||||
if (enemy.hp_ == 0) {
|
||||
return true;
|
||||
}
|
||||
me.get_attacked(enemy);
|
||||
if (me.hp_ == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
const std::string hp_begin{"Hit Points: "};
|
||||
const std::string d_begin{"Damage: "};
|
||||
const std::string a_begin{"Armor: "};
|
||||
int main()
|
||||
{
|
||||
const std::string hp_begin{"Hit Points: "};
|
||||
const std::string d_begin{"Damage: "};
|
||||
const std::string a_begin{"Armor: "};
|
||||
|
||||
const std::vector<Item> weapons{
|
||||
{"Dagger", 8, 4, 0},
|
||||
{"Shortsword", 10, 5, 0},
|
||||
{"Warhammer", 25, 6, 0},
|
||||
{"Longsword", 40, 7, 0},
|
||||
{"Greataxe", 74, 8, 0},
|
||||
};
|
||||
const std::vector<Item> weapons{
|
||||
{"Dagger", 8, 4, 0}, {"Shortsword", 10, 5, 0}, {"Warhammer", 25, 6, 0},
|
||||
{"Longsword", 40, 7, 0}, {"Greataxe", 74, 8, 0},
|
||||
};
|
||||
|
||||
const std::vector<Item> armours{
|
||||
{"Nothing", 0, 0, 0},
|
||||
{"Leather", 13, 0, 1},
|
||||
{"Chainmail", 31, 0, 2},
|
||||
{"Splintmail", 53, 0, 3},
|
||||
{"Bandedmail", 75, 0, 4},
|
||||
{"Platedmail", 102, 0, 5},
|
||||
};
|
||||
const std::vector<Item> armours{
|
||||
{"Nothing", 0, 0, 0}, {"Leather", 13, 0, 1}, {"Chainmail", 31, 0, 2},
|
||||
{"Splintmail", 53, 0, 3}, {"Bandedmail", 75, 0, 4}, {"Platedmail", 102, 0, 5},
|
||||
};
|
||||
|
||||
const std::vector<Item> rings{
|
||||
{"Empty", 0, 0, 0},
|
||||
{"Damage +1", 25, 1, 0},
|
||||
{"Damage +2", 50, 2, 0},
|
||||
{"Damage +3", 100, 3, 0},
|
||||
{"Defense +1", 20, 0, 1},
|
||||
{"Defense +2", 40, 0, 2},
|
||||
{"Defense +3", 80, 0, 3},
|
||||
};
|
||||
const std::vector<Item> rings{
|
||||
{"Empty", 0, 0, 0}, {"Damage +1", 25, 1, 0}, {"Damage +2", 50, 2, 0},
|
||||
{"Damage +3", 100, 3, 0}, {"Defense +1", 20, 0, 1}, {"Defense +2", 40, 0, 2},
|
||||
{"Defense +3", 80, 0, 3},
|
||||
};
|
||||
|
||||
auto enemy_hp{get_value(hp_begin)};
|
||||
auto enemy_damage{get_value(d_begin)};
|
||||
auto enemy_armour{get_value(a_begin)};
|
||||
|
||||
auto enemy_hp{get_value(hp_begin)};
|
||||
auto enemy_damage{get_value(d_begin)};
|
||||
auto enemy_armour{get_value(a_begin)};
|
||||
Person best_result{0, 0, 0};
|
||||
Person worst_result{0, 0, 0};
|
||||
worst_result.cost_ = 0;
|
||||
Person enemy{enemy_hp, enemy_damage, enemy_armour};
|
||||
|
||||
Person best_result{0, 0, 0};
|
||||
Person worst_result{0, 0, 0};
|
||||
worst_result.cost_ = 0;
|
||||
Person enemy{enemy_hp, enemy_damage, enemy_armour};
|
||||
|
||||
for (auto const &weapon: weapons) {
|
||||
for (auto const &armour: armours) {
|
||||
for (auto const &left_ring: rings) {
|
||||
for (auto const &right_ring: rings) {
|
||||
if (left_ring == right_ring) continue;
|
||||
Person me{weapon, armour, left_ring, right_ring};
|
||||
if (me_beats_enemy(me, enemy)) {
|
||||
if (me.cost_ < best_result.cost_) {
|
||||
best_result = me;
|
||||
}
|
||||
}
|
||||
else if (me.cost_ > worst_result.cost_) {
|
||||
worst_result = me;
|
||||
}
|
||||
}
|
||||
for (auto const& weapon : weapons) {
|
||||
for (auto const& armour : armours) {
|
||||
for (auto const& left_ring : rings) {
|
||||
for (auto const& right_ring : rings) {
|
||||
if (left_ring == right_ring)
|
||||
continue;
|
||||
Person me{weapon, armour, left_ring, right_ring};
|
||||
if (me_beats_enemy(me, enemy)) {
|
||||
if (me.cost_ < best_result.cost_) {
|
||||
best_result = me;
|
||||
}
|
||||
}
|
||||
else if (me.cost_ > worst_result.cost_) {
|
||||
worst_result = me;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Best person: " << best_result.name_ << " at cost of " << best_result.cost_ << '\n';
|
||||
std::cout << "Worst person: " << worst_result.name_ << " at cost of " << worst_result.cost_ << '\n';
|
||||
std::cout << "Best person: " << best_result.name_ << " at cost of " << best_result.cost_ << '\n';
|
||||
std::cout << "Worst person: " << worst_result.name_ << " at cost of " << worst_result.cost_
|
||||
<< '\n';
|
||||
}
|
@@ -1,127 +1,143 @@
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
struct State {
|
||||
State(unsigned long enemy_hp, unsigned long enemy_damage) : enemy_hp_(enemy_hp), enemy_damage_(enemy_damage) {}
|
||||
struct State
|
||||
{
|
||||
State(unsigned long enemy_hp, unsigned long enemy_damage)
|
||||
: enemy_hp_(enemy_hp), enemy_damage_(enemy_damage)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long my_hp_{50};
|
||||
unsigned long my_mana_{500};
|
||||
unsigned long my_armour_{0};
|
||||
unsigned long enemy_hp_;
|
||||
unsigned long enemy_damage_;
|
||||
unsigned long shield_counter_{0};
|
||||
unsigned long poison_counter_{0};
|
||||
unsigned long recharge_counter_{0};
|
||||
unsigned long cost_{0};
|
||||
unsigned long my_hp_{50};
|
||||
unsigned long my_mana_{500};
|
||||
unsigned long my_armour_{0};
|
||||
unsigned long enemy_hp_;
|
||||
unsigned long enemy_damage_;
|
||||
unsigned long shield_counter_{0};
|
||||
unsigned long poison_counter_{0};
|
||||
unsigned long recharge_counter_{0};
|
||||
unsigned long cost_{0};
|
||||
|
||||
bool operator==(State const &rhs) const {
|
||||
return my_hp_ == rhs.my_hp_ && my_mana_ == rhs.my_mana_ && my_armour_ == rhs.my_armour_ &&
|
||||
enemy_hp_ == rhs.enemy_hp_ && enemy_damage_ == rhs.enemy_damage_ &&
|
||||
shield_counter_ == rhs.shield_counter_ && poison_counter_ == rhs.poison_counter_ &&
|
||||
recharge_counter_ == rhs.recharge_counter_;
|
||||
bool operator==(State const& rhs) const
|
||||
{
|
||||
return my_hp_ == rhs.my_hp_ && my_mana_ == rhs.my_mana_ && my_armour_ == rhs.my_armour_ &&
|
||||
enemy_hp_ == rhs.enemy_hp_ && enemy_damage_ == rhs.enemy_damage_ &&
|
||||
shield_counter_ == rhs.shield_counter_ && poison_counter_ == rhs.poison_counter_ &&
|
||||
recharge_counter_ == rhs.recharge_counter_;
|
||||
}
|
||||
|
||||
bool apply_effects()
|
||||
{
|
||||
if (shield_counter_ > 0) {
|
||||
if (--shield_counter_ == 0) {
|
||||
my_armour_ -= 7;
|
||||
}
|
||||
}
|
||||
|
||||
bool apply_effects() {
|
||||
if (shield_counter_ > 0) {
|
||||
if (--shield_counter_ == 0) {
|
||||
my_armour_ -= 7;
|
||||
}
|
||||
}
|
||||
if (poison_counter_ > 0) {
|
||||
hit_enemy(3);
|
||||
--poison_counter_;
|
||||
}
|
||||
if (recharge_counter_ > 0) {
|
||||
my_mana_ += 101;
|
||||
--recharge_counter_;
|
||||
}
|
||||
return enemy_hp_ == 0;
|
||||
if (poison_counter_ > 0) {
|
||||
hit_enemy(3);
|
||||
--poison_counter_;
|
||||
}
|
||||
|
||||
void hit_enemy(unsigned long damage) {
|
||||
enemy_hp_ = (damage > enemy_hp_) ? 0 : enemy_hp_ - damage;
|
||||
if (recharge_counter_ > 0) {
|
||||
my_mana_ += 101;
|
||||
--recharge_counter_;
|
||||
}
|
||||
return enemy_hp_ == 0;
|
||||
}
|
||||
|
||||
void hit_me() {
|
||||
auto amt{my_armour_ >= enemy_damage_ ? 1 : enemy_damage_ - my_armour_};
|
||||
my_hp_ = (amt > my_hp_) ? 0 : my_hp_ - amt;
|
||||
}
|
||||
void hit_enemy(unsigned long damage)
|
||||
{
|
||||
enemy_hp_ = (damage > enemy_hp_) ? 0 : enemy_hp_ - damage;
|
||||
}
|
||||
|
||||
void spend_mana(unsigned long amt) {
|
||||
assert(my_mana_ >= amt);
|
||||
my_mana_ -= amt;
|
||||
cost_ += amt;
|
||||
}
|
||||
void hit_me()
|
||||
{
|
||||
auto amt{my_armour_ >= enemy_damage_ ? 1 : enemy_damage_ - my_armour_};
|
||||
my_hp_ = (amt > my_hp_) ? 0 : my_hp_ - amt;
|
||||
}
|
||||
|
||||
void enemy_turn() {
|
||||
if (!apply_effects()) {
|
||||
hit_me();
|
||||
}
|
||||
}
|
||||
void spend_mana(unsigned long amt)
|
||||
{
|
||||
assert(my_mana_ >= amt);
|
||||
my_mana_ -= amt;
|
||||
cost_ += amt;
|
||||
}
|
||||
|
||||
[[nodiscard]] State magic_missile() const {
|
||||
State next{*this};
|
||||
next.spend_mana(53);
|
||||
next.hit_enemy(4);
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
void enemy_turn()
|
||||
{
|
||||
if (!apply_effects()) {
|
||||
hit_me();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] State drain() const {
|
||||
State next{*this};
|
||||
next.spend_mana(73);
|
||||
next.hit_enemy(2);
|
||||
next.my_hp_ += 2;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
[[nodiscard]] State magic_missile() const
|
||||
{
|
||||
State next{*this};
|
||||
next.spend_mana(53);
|
||||
next.hit_enemy(4);
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
|
||||
[[nodiscard]] State shield() const {
|
||||
State next{*this};
|
||||
assert(shield_counter_ == 0);
|
||||
next.spend_mana(113);
|
||||
next.my_armour_ += 7;
|
||||
next.shield_counter_ = 6;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
[[nodiscard]] State drain() const
|
||||
{
|
||||
State next{*this};
|
||||
next.spend_mana(73);
|
||||
next.hit_enemy(2);
|
||||
next.my_hp_ += 2;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
|
||||
[[nodiscard]] State poison() const {
|
||||
State next{*this};
|
||||
assert(poison_counter_ == 0);
|
||||
next.spend_mana(173);
|
||||
next.poison_counter_ = 6;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
[[nodiscard]] State shield() const
|
||||
{
|
||||
State next{*this};
|
||||
assert(shield_counter_ == 0);
|
||||
next.spend_mana(113);
|
||||
next.my_armour_ += 7;
|
||||
next.shield_counter_ = 6;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
|
||||
[[nodiscard]] State recharge() const {
|
||||
State next{*this};
|
||||
assert(recharge_counter_ == 0);
|
||||
next.spend_mana(229);
|
||||
next.recharge_counter_ = 5;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
[[nodiscard]] State poison() const
|
||||
{
|
||||
State next{*this};
|
||||
assert(poison_counter_ == 0);
|
||||
next.spend_mana(173);
|
||||
next.poison_counter_ = 6;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
|
||||
[[nodiscard]] State recharge() const
|
||||
{
|
||||
State next{*this};
|
||||
assert(recharge_counter_ == 0);
|
||||
next.spend_mana(229);
|
||||
next.recharge_counter_ = 5;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
};
|
||||
|
||||
unsigned long get_value(std::string const &begin) {
|
||||
std::string line;
|
||||
if (!std::getline(std::cin, line)) {
|
||||
std::cerr << "Missing line in input\n";
|
||||
std::exit(1);
|
||||
}
|
||||
if (line.substr(0, begin.length()) != begin) {
|
||||
std::cerr << "Line doesn't begin with: " << begin << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
return std::stoul(line.substr(begin.length()));
|
||||
unsigned long get_value(std::string const& begin)
|
||||
{
|
||||
std::string line;
|
||||
if (!std::getline(std::cin, line)) {
|
||||
std::cerr << "Missing line in input\n";
|
||||
std::exit(1);
|
||||
}
|
||||
if (line.substr(0, begin.length()) != begin) {
|
||||
std::cerr << "Line doesn't begin with: " << begin << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
return std::stoul(line.substr(begin.length()));
|
||||
}
|
||||
|
||||
/** \brief Add \a state to \a states.
|
||||
@@ -129,51 +145,55 @@ unsigned long get_value(std::string const &begin) {
|
||||
* @param states Vector of states
|
||||
* @param state State to add.
|
||||
*
|
||||
* If there is already an element in \a states that is the same as \a state we don't add a new state, instead we just
|
||||
* update the cost to the minimum.
|
||||
* If there is already an element in \a states that is the same as \a state we don't add a new
|
||||
* state, instead we just update the cost to the minimum.
|
||||
*/
|
||||
void add_state(std::vector<State> &states, State const &state) {
|
||||
auto it = std::find(states.begin(), states.end(), state);
|
||||
if (it == states.end()) {
|
||||
states.push_back(state);
|
||||
} else if (it->cost_ > state.cost_) {
|
||||
it->cost_ = state.cost_;
|
||||
}
|
||||
void add_state(std::vector<State>& states, State const& state)
|
||||
{
|
||||
auto it = std::find(states.begin(), states.end(), state);
|
||||
if (it == states.end()) {
|
||||
states.push_back(state);
|
||||
}
|
||||
else if (it->cost_ > state.cost_) {
|
||||
it->cost_ = state.cost_;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
const std::string hp_begin{"Hit Points: "};
|
||||
const std::string d_begin{"Damage: "};
|
||||
int main()
|
||||
{
|
||||
const std::string hp_begin{"Hit Points: "};
|
||||
const std::string d_begin{"Damage: "};
|
||||
|
||||
auto enemy_hp{get_value(hp_begin)};
|
||||
auto enemy_damage{get_value(d_begin)};
|
||||
auto enemy_hp{get_value(hp_begin)};
|
||||
auto enemy_damage{get_value(d_begin)};
|
||||
|
||||
/* States - list of states we've generated. */
|
||||
std::vector<State> states;
|
||||
states.emplace_back(enemy_hp, enemy_damage);
|
||||
/* States - list of states we've generated. */
|
||||
std::vector<State> states;
|
||||
states.emplace_back(enemy_hp, enemy_damage);
|
||||
|
||||
/* Cost of the cheapest winning state so far. */
|
||||
auto best_cost{std::numeric_limits<unsigned long>::max()};
|
||||
/* Cost of the cheapest winning state so far. */
|
||||
auto best_cost{std::numeric_limits<unsigned long>::max()};
|
||||
|
||||
while (!states.empty()) {
|
||||
/* Get the lowest cost element in the list of states and process that. */
|
||||
auto it = std::min_element(states.begin(), states.end(),
|
||||
[](State const &lhs, State const &rhs) { return lhs.cost_ < rhs.cost_; });
|
||||
State candidate{*it};
|
||||
states.erase(it);
|
||||
if (candidate.cost_ >= best_cost) {
|
||||
/* Because we've searched for the minimum element above we know that all future candidates are going to
|
||||
* cost more than the current best cost for winning - so just stop here. */
|
||||
break;
|
||||
}
|
||||
while (!states.empty()) {
|
||||
/* Get the lowest cost element in the list of states and process that. */
|
||||
auto it =
|
||||
std::min_element(states.begin(), states.end(),
|
||||
[](State const& lhs, State const& rhs) { return lhs.cost_ < rhs.cost_; });
|
||||
State candidate{*it};
|
||||
states.erase(it);
|
||||
if (candidate.cost_ >= best_cost) {
|
||||
/* Because we've searched for the minimum element above we know that all future candidates are
|
||||
* going to cost more than the current best cost for winning - so just stop here. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Someone has died so this is a winning state - deal with it. */
|
||||
if (candidate.my_hp_ == 0 || candidate.enemy_hp_ == 0) {
|
||||
if (candidate.enemy_hp_ == 0 && candidate.cost_ < best_cost) {
|
||||
best_cost = candidate.cost_;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* Someone has died so this is a winning state - deal with it. */
|
||||
if (candidate.my_hp_ == 0 || candidate.enemy_hp_ == 0) {
|
||||
if (candidate.enemy_hp_ == 0 && candidate.cost_ < best_cost) {
|
||||
best_cost = candidate.cost_;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Part two's addition. */
|
||||
@@ -182,35 +202,35 @@ int main() {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Apply effects at start of our turn. If someone dies push this state back on the queue. */
|
||||
if (candidate.apply_effects()) {
|
||||
states.push_back(candidate);
|
||||
}
|
||||
|
||||
/* Handle each of our options (followed by the enemy's turn). Making sure that when we add the state we
|
||||
* don't duplicate ourselves.
|
||||
*/
|
||||
if (candidate.my_mana_ >= 53) {
|
||||
add_state(states, candidate.magic_missile());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 73) {
|
||||
add_state(states, candidate.drain());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 113 && candidate.shield_counter_ == 0) {
|
||||
add_state(states, candidate.shield());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 173 && candidate.poison_counter_ == 0) {
|
||||
add_state(states, candidate.poison());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 229 && candidate.recharge_counter_ == 0) {
|
||||
add_state(states, candidate.recharge());
|
||||
}
|
||||
/* Apply effects at start of our turn. If someone dies push this state back on the queue. */
|
||||
if (candidate.apply_effects()) {
|
||||
states.push_back(candidate);
|
||||
}
|
||||
|
||||
std::cout << "Best cost " << best_cost << "\n";
|
||||
return 1;
|
||||
/* Handle each of our options (followed by the enemy's turn). Making sure that when we add the
|
||||
* state we don't duplicate ourselves.
|
||||
*/
|
||||
if (candidate.my_mana_ >= 53) {
|
||||
add_state(states, candidate.magic_missile());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 73) {
|
||||
add_state(states, candidate.drain());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 113 && candidate.shield_counter_ == 0) {
|
||||
add_state(states, candidate.shield());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 173 && candidate.poison_counter_ == 0) {
|
||||
add_state(states, candidate.poison());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 229 && candidate.recharge_counter_ == 0) {
|
||||
add_state(states, candidate.recharge());
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Best cost " << best_cost << "\n";
|
||||
return 1;
|
||||
}
|
@@ -1,127 +1,143 @@
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
struct State {
|
||||
State(unsigned long enemy_hp, unsigned long enemy_damage) : enemy_hp_(enemy_hp), enemy_damage_(enemy_damage) {}
|
||||
struct State
|
||||
{
|
||||
State(unsigned long enemy_hp, unsigned long enemy_damage)
|
||||
: enemy_hp_(enemy_hp), enemy_damage_(enemy_damage)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long my_hp_{50};
|
||||
unsigned long my_mana_{500};
|
||||
unsigned long my_armour_{0};
|
||||
unsigned long enemy_hp_;
|
||||
unsigned long enemy_damage_;
|
||||
unsigned long shield_counter_{0};
|
||||
unsigned long poison_counter_{0};
|
||||
unsigned long recharge_counter_{0};
|
||||
unsigned long cost_{0};
|
||||
unsigned long my_hp_{50};
|
||||
unsigned long my_mana_{500};
|
||||
unsigned long my_armour_{0};
|
||||
unsigned long enemy_hp_;
|
||||
unsigned long enemy_damage_;
|
||||
unsigned long shield_counter_{0};
|
||||
unsigned long poison_counter_{0};
|
||||
unsigned long recharge_counter_{0};
|
||||
unsigned long cost_{0};
|
||||
|
||||
bool operator==(State const &rhs) const {
|
||||
return my_hp_ == rhs.my_hp_ && my_mana_ == rhs.my_mana_ && my_armour_ == rhs.my_armour_ &&
|
||||
enemy_hp_ == rhs.enemy_hp_ && enemy_damage_ == rhs.enemy_damage_ &&
|
||||
shield_counter_ == rhs.shield_counter_ && poison_counter_ == rhs.poison_counter_ &&
|
||||
recharge_counter_ == rhs.recharge_counter_;
|
||||
bool operator==(State const& rhs) const
|
||||
{
|
||||
return my_hp_ == rhs.my_hp_ && my_mana_ == rhs.my_mana_ && my_armour_ == rhs.my_armour_ &&
|
||||
enemy_hp_ == rhs.enemy_hp_ && enemy_damage_ == rhs.enemy_damage_ &&
|
||||
shield_counter_ == rhs.shield_counter_ && poison_counter_ == rhs.poison_counter_ &&
|
||||
recharge_counter_ == rhs.recharge_counter_;
|
||||
}
|
||||
|
||||
bool apply_effects()
|
||||
{
|
||||
if (shield_counter_ > 0) {
|
||||
if (--shield_counter_ == 0) {
|
||||
my_armour_ -= 7;
|
||||
}
|
||||
}
|
||||
|
||||
bool apply_effects() {
|
||||
if (shield_counter_ > 0) {
|
||||
if (--shield_counter_ == 0) {
|
||||
my_armour_ -= 7;
|
||||
}
|
||||
}
|
||||
if (poison_counter_ > 0) {
|
||||
hit_enemy(3);
|
||||
--poison_counter_;
|
||||
}
|
||||
if (recharge_counter_ > 0) {
|
||||
my_mana_ += 101;
|
||||
--recharge_counter_;
|
||||
}
|
||||
return enemy_hp_ == 0;
|
||||
if (poison_counter_ > 0) {
|
||||
hit_enemy(3);
|
||||
--poison_counter_;
|
||||
}
|
||||
|
||||
void hit_enemy(unsigned long damage) {
|
||||
enemy_hp_ = (damage > enemy_hp_) ? 0 : enemy_hp_ - damage;
|
||||
if (recharge_counter_ > 0) {
|
||||
my_mana_ += 101;
|
||||
--recharge_counter_;
|
||||
}
|
||||
return enemy_hp_ == 0;
|
||||
}
|
||||
|
||||
void hit_me() {
|
||||
auto amt{my_armour_ >= enemy_damage_ ? 1 : enemy_damage_ - my_armour_};
|
||||
my_hp_ = (amt > my_hp_) ? 0 : my_hp_ - amt;
|
||||
}
|
||||
void hit_enemy(unsigned long damage)
|
||||
{
|
||||
enemy_hp_ = (damage > enemy_hp_) ? 0 : enemy_hp_ - damage;
|
||||
}
|
||||
|
||||
void spend_mana(unsigned long amt) {
|
||||
assert(my_mana_ >= amt);
|
||||
my_mana_ -= amt;
|
||||
cost_ += amt;
|
||||
}
|
||||
void hit_me()
|
||||
{
|
||||
auto amt{my_armour_ >= enemy_damage_ ? 1 : enemy_damage_ - my_armour_};
|
||||
my_hp_ = (amt > my_hp_) ? 0 : my_hp_ - amt;
|
||||
}
|
||||
|
||||
void enemy_turn() {
|
||||
if (!apply_effects()) {
|
||||
hit_me();
|
||||
}
|
||||
}
|
||||
void spend_mana(unsigned long amt)
|
||||
{
|
||||
assert(my_mana_ >= amt);
|
||||
my_mana_ -= amt;
|
||||
cost_ += amt;
|
||||
}
|
||||
|
||||
[[nodiscard]] State magic_missile() const {
|
||||
State next{*this};
|
||||
next.spend_mana(53);
|
||||
next.hit_enemy(4);
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
void enemy_turn()
|
||||
{
|
||||
if (!apply_effects()) {
|
||||
hit_me();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] State drain() const {
|
||||
State next{*this};
|
||||
next.spend_mana(73);
|
||||
next.hit_enemy(2);
|
||||
next.my_hp_ += 2;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
[[nodiscard]] State magic_missile() const
|
||||
{
|
||||
State next{*this};
|
||||
next.spend_mana(53);
|
||||
next.hit_enemy(4);
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
|
||||
[[nodiscard]] State shield() const {
|
||||
State next{*this};
|
||||
assert(shield_counter_ == 0);
|
||||
next.spend_mana(113);
|
||||
next.my_armour_ += 7;
|
||||
next.shield_counter_ = 6;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
[[nodiscard]] State drain() const
|
||||
{
|
||||
State next{*this};
|
||||
next.spend_mana(73);
|
||||
next.hit_enemy(2);
|
||||
next.my_hp_ += 2;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
|
||||
[[nodiscard]] State poison() const {
|
||||
State next{*this};
|
||||
assert(poison_counter_ == 0);
|
||||
next.spend_mana(173);
|
||||
next.poison_counter_ = 6;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
[[nodiscard]] State shield() const
|
||||
{
|
||||
State next{*this};
|
||||
assert(shield_counter_ == 0);
|
||||
next.spend_mana(113);
|
||||
next.my_armour_ += 7;
|
||||
next.shield_counter_ = 6;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
|
||||
[[nodiscard]] State recharge() const {
|
||||
State next{*this};
|
||||
assert(recharge_counter_ == 0);
|
||||
next.spend_mana(229);
|
||||
next.recharge_counter_ = 5;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
[[nodiscard]] State poison() const
|
||||
{
|
||||
State next{*this};
|
||||
assert(poison_counter_ == 0);
|
||||
next.spend_mana(173);
|
||||
next.poison_counter_ = 6;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
|
||||
[[nodiscard]] State recharge() const
|
||||
{
|
||||
State next{*this};
|
||||
assert(recharge_counter_ == 0);
|
||||
next.spend_mana(229);
|
||||
next.recharge_counter_ = 5;
|
||||
next.enemy_turn();
|
||||
return next;
|
||||
}
|
||||
};
|
||||
|
||||
unsigned long get_value(std::string const &begin) {
|
||||
std::string line;
|
||||
if (!std::getline(std::cin, line)) {
|
||||
std::cerr << "Missing line in input\n";
|
||||
std::exit(1);
|
||||
}
|
||||
if (line.substr(0, begin.length()) != begin) {
|
||||
std::cerr << "Line doesn't begin with: " << begin << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
return std::stoul(line.substr(begin.length()));
|
||||
unsigned long get_value(std::string const& begin)
|
||||
{
|
||||
std::string line;
|
||||
if (!std::getline(std::cin, line)) {
|
||||
std::cerr << "Missing line in input\n";
|
||||
std::exit(1);
|
||||
}
|
||||
if (line.substr(0, begin.length()) != begin) {
|
||||
std::cerr << "Line doesn't begin with: " << begin << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
return std::stoul(line.substr(begin.length()));
|
||||
}
|
||||
|
||||
/** \brief Add \a state to \a states.
|
||||
@@ -129,86 +145,90 @@ unsigned long get_value(std::string const &begin) {
|
||||
* @param states Vector of states
|
||||
* @param state State to add.
|
||||
*
|
||||
* If there is already an element in \a states that is the same as \a state we don't add a new state, instead we just
|
||||
* update the cost to the minimum.
|
||||
* If there is already an element in \a states that is the same as \a state we don't add a new
|
||||
* state, instead we just update the cost to the minimum.
|
||||
*/
|
||||
void add_state(std::vector<State> &states, State const &state) {
|
||||
auto it = std::find(states.begin(), states.end(), state);
|
||||
if (it == states.end()) {
|
||||
states.push_back(state);
|
||||
} else if (it->cost_ > state.cost_) {
|
||||
it->cost_ = state.cost_;
|
||||
}
|
||||
void add_state(std::vector<State>& states, State const& state)
|
||||
{
|
||||
auto it = std::find(states.begin(), states.end(), state);
|
||||
if (it == states.end()) {
|
||||
states.push_back(state);
|
||||
}
|
||||
else if (it->cost_ > state.cost_) {
|
||||
it->cost_ = state.cost_;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
const std::string hp_begin{"Hit Points: "};
|
||||
const std::string d_begin{"Damage: "};
|
||||
int main()
|
||||
{
|
||||
const std::string hp_begin{"Hit Points: "};
|
||||
const std::string d_begin{"Damage: "};
|
||||
|
||||
auto enemy_hp{get_value(hp_begin)};
|
||||
auto enemy_damage{get_value(d_begin)};
|
||||
auto enemy_hp{get_value(hp_begin)};
|
||||
auto enemy_damage{get_value(d_begin)};
|
||||
|
||||
/* States - list of states we've generated. */
|
||||
std::vector<State> states;
|
||||
states.emplace_back(enemy_hp, enemy_damage);
|
||||
/* States - list of states we've generated. */
|
||||
std::vector<State> states;
|
||||
states.emplace_back(enemy_hp, enemy_damage);
|
||||
|
||||
/* Cost of the cheapest winning state so far. */
|
||||
auto best_cost{std::numeric_limits<unsigned long>::max()};
|
||||
/* Cost of the cheapest winning state so far. */
|
||||
auto best_cost{std::numeric_limits<unsigned long>::max()};
|
||||
|
||||
while (!states.empty()) {
|
||||
/* Get the lowest cost element in the list of states and process that. */
|
||||
auto it = std::min_element(states.begin(), states.end(),
|
||||
[](State const &lhs, State const &rhs) { return lhs.cost_ < rhs.cost_; });
|
||||
State candidate{*it};
|
||||
states.erase(it);
|
||||
if (candidate.cost_ >= best_cost) {
|
||||
/* Because we've searched for the minimum element above we know that all future candidates are going to
|
||||
* cost more than the current best cost for winning - so just stop here. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Someone has died so this is a winning state - deal with it. */
|
||||
if (candidate.my_hp_ == 0 || candidate.enemy_hp_ == 0) {
|
||||
if (candidate.enemy_hp_ == 0 && candidate.cost_ < best_cost) {
|
||||
best_cost = candidate.cost_;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Part two's addition - we lose health at the start of our turn. */
|
||||
if (--candidate.my_hp_ == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Apply effects at start of our turn. If someone dies push this state back on the queue. */
|
||||
if (candidate.apply_effects()) {
|
||||
states.push_back(candidate);
|
||||
}
|
||||
|
||||
/* Handle each of our options (followed by the enemy's turn). Making sure that when we add the state we
|
||||
* don't duplicate ourselves.
|
||||
*/
|
||||
if (candidate.my_mana_ >= 53) {
|
||||
add_state(states, candidate.magic_missile());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 73) {
|
||||
add_state(states, candidate.drain());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 113 && candidate.shield_counter_ == 0) {
|
||||
add_state(states, candidate.shield());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 173 && candidate.poison_counter_ == 0) {
|
||||
add_state(states, candidate.poison());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 229 && candidate.recharge_counter_ == 0) {
|
||||
add_state(states, candidate.recharge());
|
||||
}
|
||||
while (!states.empty()) {
|
||||
/* Get the lowest cost element in the list of states and process that. */
|
||||
auto it =
|
||||
std::min_element(states.begin(), states.end(),
|
||||
[](State const& lhs, State const& rhs) { return lhs.cost_ < rhs.cost_; });
|
||||
State candidate{*it};
|
||||
states.erase(it);
|
||||
if (candidate.cost_ >= best_cost) {
|
||||
/* Because we've searched for the minimum element above we know that all future candidates are
|
||||
* going to cost more than the current best cost for winning - so just stop here. */
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << "Best cost " << best_cost << "\n";
|
||||
return 1;
|
||||
/* Someone has died so this is a winning state - deal with it. */
|
||||
if (candidate.my_hp_ == 0 || candidate.enemy_hp_ == 0) {
|
||||
if (candidate.enemy_hp_ == 0 && candidate.cost_ < best_cost) {
|
||||
best_cost = candidate.cost_;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Part two's addition - we lose health at the start of our turn. */
|
||||
if (--candidate.my_hp_ == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Apply effects at start of our turn. If someone dies push this state back on the queue. */
|
||||
if (candidate.apply_effects()) {
|
||||
states.push_back(candidate);
|
||||
}
|
||||
|
||||
/* Handle each of our options (followed by the enemy's turn). Making sure that when we add the
|
||||
* state we don't duplicate ourselves.
|
||||
*/
|
||||
if (candidate.my_mana_ >= 53) {
|
||||
add_state(states, candidate.magic_missile());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 73) {
|
||||
add_state(states, candidate.drain());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 113 && candidate.shield_counter_ == 0) {
|
||||
add_state(states, candidate.shield());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 173 && candidate.poison_counter_ == 0) {
|
||||
add_state(states, candidate.poison());
|
||||
}
|
||||
|
||||
if (candidate.my_mana_ >= 229 && candidate.recharge_counter_ == 0) {
|
||||
add_state(states, candidate.recharge());
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Best cost " << best_cost << "\n";
|
||||
return 1;
|
||||
}
|
@@ -1,129 +1,138 @@
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
enum class Op {
|
||||
hlf, tpl, inc, jmp, jie, jio
|
||||
};
|
||||
enum class Reg {
|
||||
a, b
|
||||
enum class Op { hlf, tpl, inc, jmp, jie, jio };
|
||||
enum class Reg { a, b };
|
||||
|
||||
struct Instr
|
||||
{
|
||||
static Op get_opcode(std::string const& str)
|
||||
{
|
||||
static std::map<std::string, Op> ops{{"hlf ", Op::hlf}, {"tpl ", Op::tpl}, {"inc ", Op::inc},
|
||||
{"jmp ", Op::jmp}, {"jie ", Op::jie}, {"jio ", Op::jio}};
|
||||
auto it = ops.find(str.substr(0, 4));
|
||||
assert(it != ops.end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
static Reg get_register(std::string const& str)
|
||||
{
|
||||
assert(str.size() >= 1);
|
||||
if (str[0] == 'a') {
|
||||
return Reg::a;
|
||||
}
|
||||
else if (str[0] == 'b') {
|
||||
return Reg::b;
|
||||
}
|
||||
else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static long get_offset(std::string const& str) { return std::stol(str); }
|
||||
|
||||
explicit Instr(std::string const& str)
|
||||
{
|
||||
op_ = get_opcode(str);
|
||||
switch (op_) {
|
||||
case Op::hlf:
|
||||
case Op::tpl:
|
||||
case Op::inc:
|
||||
reg_ = get_register(str.substr(4));
|
||||
pc_add_ = 1;
|
||||
assert(str.length() == 5);
|
||||
break;
|
||||
case Op::jmp:
|
||||
reg_ = Reg::a;
|
||||
pc_add_ = get_offset(str.substr(4));
|
||||
break;
|
||||
case Op::jie:
|
||||
case Op::jio:
|
||||
reg_ = get_register(str.substr(4));
|
||||
assert(str.at(5) == ',');
|
||||
assert(str.at(6) == ' ');
|
||||
pc_add_ = get_offset(str.substr(7));
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
Op op_;
|
||||
Reg reg_;
|
||||
long pc_add_;
|
||||
};
|
||||
|
||||
struct Instr {
|
||||
static Op get_opcode(std::string const &str) {
|
||||
static std::map<std::string, Op> ops{
|
||||
{"hlf ", Op::hlf},
|
||||
{"tpl ", Op::tpl},
|
||||
{"inc ", Op::inc},
|
||||
{"jmp ", Op::jmp},
|
||||
{"jie ", Op::jie},
|
||||
{"jio ", Op::jio}
|
||||
};
|
||||
auto it = ops.find(str.substr(0, 4));
|
||||
assert(it != ops.end());
|
||||
return it->second;
|
||||
}
|
||||
struct State
|
||||
{
|
||||
unsigned long a_{0};
|
||||
unsigned long b_{0};
|
||||
unsigned long pc_{0};
|
||||
|
||||
static Reg get_register(std::string const &str) {
|
||||
assert(str.size() >= 1);
|
||||
if (str[0] == 'a') { return Reg::a; }
|
||||
else if (str[0] == 'b') { return Reg::b; }
|
||||
else { abort(); }
|
||||
unsigned long& reg(Reg r)
|
||||
{
|
||||
switch (r) {
|
||||
case Reg::a:
|
||||
return a_;
|
||||
case Reg::b:
|
||||
return b_;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static long get_offset(std::string const &str) {
|
||||
return std::stol(str);
|
||||
void execute(Instr const& instruction)
|
||||
{
|
||||
switch (instruction.op_) {
|
||||
case Op::hlf:
|
||||
reg(instruction.reg_) /= 2;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::tpl:
|
||||
reg(instruction.reg_) *= 3;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::inc:
|
||||
reg(instruction.reg_) += 1;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::jmp:
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::jie:
|
||||
if (reg(instruction.reg_) % 2 == 0)
|
||||
pc_ += instruction.pc_add_;
|
||||
else
|
||||
pc_ += 1;
|
||||
break;
|
||||
case Op::jio:
|
||||
if (reg(instruction.reg_) == 1)
|
||||
pc_ += instruction.pc_add_;
|
||||
else
|
||||
pc_ += 1;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
explicit Instr(std::string const &str) {
|
||||
op_ = get_opcode(str);
|
||||
switch (op_) {
|
||||
case Op::hlf:
|
||||
case Op::tpl:
|
||||
case Op::inc:
|
||||
reg_ = get_register(str.substr(4));
|
||||
pc_add_ = 1;
|
||||
assert(str.length() == 5);
|
||||
break;
|
||||
case Op::jmp:
|
||||
reg_ = Reg::a;
|
||||
pc_add_ = get_offset(str.substr(4));
|
||||
break;
|
||||
case Op::jie:
|
||||
case Op::jio:
|
||||
reg_ = get_register(str.substr(4));
|
||||
assert(str.at(5) == ',');
|
||||
assert(str.at(6) == ' ');
|
||||
pc_add_ = get_offset(str.substr(7));
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
Op op_;
|
||||
Reg reg_;
|
||||
long pc_add_;
|
||||
}
|
||||
};
|
||||
|
||||
struct State {
|
||||
unsigned long a_{0};
|
||||
unsigned long b_{0};
|
||||
unsigned long pc_{0};
|
||||
int main()
|
||||
{
|
||||
std::vector<Instr> instructions;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
instructions.emplace_back(line);
|
||||
}
|
||||
|
||||
unsigned long& reg(Reg r) {
|
||||
switch (r) {
|
||||
case Reg::a: return a_;
|
||||
case Reg::b: return b_;
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
void execute(Instr const &instruction) {
|
||||
switch (instruction.op_) {
|
||||
case Op::hlf:
|
||||
reg(instruction.reg_) /= 2;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::tpl:
|
||||
reg(instruction.reg_) *= 3;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::inc:
|
||||
reg(instruction.reg_) += 1;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::jmp:
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::jie:
|
||||
if (reg(instruction.reg_) % 2 == 0) pc_ += instruction.pc_add_;
|
||||
else pc_ += 1;
|
||||
break;
|
||||
case Op::jio:
|
||||
if (reg(instruction.reg_) == 1) pc_ += instruction.pc_add_;
|
||||
else pc_ += 1;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::vector<Instr> instructions;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
instructions.emplace_back(line);
|
||||
}
|
||||
|
||||
State state;
|
||||
while (state.pc_ < instructions.size()) {
|
||||
state.execute(instructions[state.pc_]);
|
||||
}
|
||||
std::cout << "a = " << state.a_ << "\nb = " << state.b_ << '\n';
|
||||
State state;
|
||||
while (state.pc_ < instructions.size()) {
|
||||
state.execute(instructions[state.pc_]);
|
||||
}
|
||||
std::cout << "a = " << state.a_ << "\nb = " << state.b_ << '\n';
|
||||
}
|
@@ -1,129 +1,138 @@
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
enum class Op {
|
||||
hlf, tpl, inc, jmp, jie, jio
|
||||
};
|
||||
enum class Reg {
|
||||
a, b
|
||||
enum class Op { hlf, tpl, inc, jmp, jie, jio };
|
||||
enum class Reg { a, b };
|
||||
|
||||
struct Instr
|
||||
{
|
||||
static Op get_opcode(std::string const& str)
|
||||
{
|
||||
static std::map<std::string, Op> ops{{"hlf ", Op::hlf}, {"tpl ", Op::tpl}, {"inc ", Op::inc},
|
||||
{"jmp ", Op::jmp}, {"jie ", Op::jie}, {"jio ", Op::jio}};
|
||||
auto it = ops.find(str.substr(0, 4));
|
||||
assert(it != ops.end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
static Reg get_register(std::string const& str)
|
||||
{
|
||||
assert(str.size() >= 1);
|
||||
if (str[0] == 'a') {
|
||||
return Reg::a;
|
||||
}
|
||||
else if (str[0] == 'b') {
|
||||
return Reg::b;
|
||||
}
|
||||
else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static long get_offset(std::string const& str) { return std::stol(str); }
|
||||
|
||||
explicit Instr(std::string const& str)
|
||||
{
|
||||
op_ = get_opcode(str);
|
||||
switch (op_) {
|
||||
case Op::hlf:
|
||||
case Op::tpl:
|
||||
case Op::inc:
|
||||
reg_ = get_register(str.substr(4));
|
||||
pc_add_ = 1;
|
||||
assert(str.length() == 5);
|
||||
break;
|
||||
case Op::jmp:
|
||||
reg_ = Reg::a;
|
||||
pc_add_ = get_offset(str.substr(4));
|
||||
break;
|
||||
case Op::jie:
|
||||
case Op::jio:
|
||||
reg_ = get_register(str.substr(4));
|
||||
assert(str.at(5) == ',');
|
||||
assert(str.at(6) == ' ');
|
||||
pc_add_ = get_offset(str.substr(7));
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
Op op_;
|
||||
Reg reg_;
|
||||
long pc_add_;
|
||||
};
|
||||
|
||||
struct Instr {
|
||||
static Op get_opcode(std::string const &str) {
|
||||
static std::map<std::string, Op> ops{
|
||||
{"hlf ", Op::hlf},
|
||||
{"tpl ", Op::tpl},
|
||||
{"inc ", Op::inc},
|
||||
{"jmp ", Op::jmp},
|
||||
{"jie ", Op::jie},
|
||||
{"jio ", Op::jio}
|
||||
};
|
||||
auto it = ops.find(str.substr(0, 4));
|
||||
assert(it != ops.end());
|
||||
return it->second;
|
||||
}
|
||||
struct State
|
||||
{
|
||||
unsigned long a_{1};
|
||||
unsigned long b_{0};
|
||||
unsigned long pc_{0};
|
||||
|
||||
static Reg get_register(std::string const &str) {
|
||||
assert(str.size() >= 1);
|
||||
if (str[0] == 'a') { return Reg::a; }
|
||||
else if (str[0] == 'b') { return Reg::b; }
|
||||
else { abort(); }
|
||||
unsigned long& reg(Reg r)
|
||||
{
|
||||
switch (r) {
|
||||
case Reg::a:
|
||||
return a_;
|
||||
case Reg::b:
|
||||
return b_;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static long get_offset(std::string const &str) {
|
||||
return std::stol(str);
|
||||
void execute(Instr const& instruction)
|
||||
{
|
||||
switch (instruction.op_) {
|
||||
case Op::hlf:
|
||||
reg(instruction.reg_) /= 2;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::tpl:
|
||||
reg(instruction.reg_) *= 3;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::inc:
|
||||
reg(instruction.reg_) += 1;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::jmp:
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::jie:
|
||||
if (reg(instruction.reg_) % 2 == 0)
|
||||
pc_ += instruction.pc_add_;
|
||||
else
|
||||
pc_ += 1;
|
||||
break;
|
||||
case Op::jio:
|
||||
if (reg(instruction.reg_) == 1)
|
||||
pc_ += instruction.pc_add_;
|
||||
else
|
||||
pc_ += 1;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
explicit Instr(std::string const &str) {
|
||||
op_ = get_opcode(str);
|
||||
switch (op_) {
|
||||
case Op::hlf:
|
||||
case Op::tpl:
|
||||
case Op::inc:
|
||||
reg_ = get_register(str.substr(4));
|
||||
pc_add_ = 1;
|
||||
assert(str.length() == 5);
|
||||
break;
|
||||
case Op::jmp:
|
||||
reg_ = Reg::a;
|
||||
pc_add_ = get_offset(str.substr(4));
|
||||
break;
|
||||
case Op::jie:
|
||||
case Op::jio:
|
||||
reg_ = get_register(str.substr(4));
|
||||
assert(str.at(5) == ',');
|
||||
assert(str.at(6) == ' ');
|
||||
pc_add_ = get_offset(str.substr(7));
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
Op op_;
|
||||
Reg reg_;
|
||||
long pc_add_;
|
||||
}
|
||||
};
|
||||
|
||||
struct State {
|
||||
unsigned long a_{1};
|
||||
unsigned long b_{0};
|
||||
unsigned long pc_{0};
|
||||
int main()
|
||||
{
|
||||
std::vector<Instr> instructions;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
instructions.emplace_back(line);
|
||||
}
|
||||
|
||||
unsigned long& reg(Reg r) {
|
||||
switch (r) {
|
||||
case Reg::a: return a_;
|
||||
case Reg::b: return b_;
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
void execute(Instr const &instruction) {
|
||||
switch (instruction.op_) {
|
||||
case Op::hlf:
|
||||
reg(instruction.reg_) /= 2;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::tpl:
|
||||
reg(instruction.reg_) *= 3;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::inc:
|
||||
reg(instruction.reg_) += 1;
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::jmp:
|
||||
pc_ += instruction.pc_add_;
|
||||
break;
|
||||
case Op::jie:
|
||||
if (reg(instruction.reg_) % 2 == 0) pc_ += instruction.pc_add_;
|
||||
else pc_ += 1;
|
||||
break;
|
||||
case Op::jio:
|
||||
if (reg(instruction.reg_) == 1) pc_ += instruction.pc_add_;
|
||||
else pc_ += 1;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::vector<Instr> instructions;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
instructions.emplace_back(line);
|
||||
}
|
||||
|
||||
State state;
|
||||
while (state.pc_ < instructions.size()) {
|
||||
state.execute(instructions[state.pc_]);
|
||||
}
|
||||
std::cout << "a = " << state.a_ << "\nb = " << state.b_ << '\n';
|
||||
State state;
|
||||
while (state.pc_ < instructions.size()) {
|
||||
state.execute(instructions[state.pc_]);
|
||||
}
|
||||
std::cout << "a = " << state.a_ << "\nb = " << state.b_ << '\n';
|
||||
}
|
@@ -1,78 +1,87 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct State {
|
||||
std::set<unsigned long> weights_;
|
||||
struct State
|
||||
{
|
||||
std::set<unsigned long> weights_;
|
||||
|
||||
explicit State(unsigned long w) { weights_.insert(w); }
|
||||
explicit State(unsigned long w) { weights_.insert(w); }
|
||||
|
||||
std::size_t cost() const { return weights_.size(); }
|
||||
std::size_t cost() const { return weights_.size(); }
|
||||
|
||||
unsigned long qe() const {
|
||||
return std::accumulate(weights_.begin(), weights_.end(), 1UL,
|
||||
[](unsigned long l, unsigned long w) { return l * w; });
|
||||
unsigned long qe() const
|
||||
{
|
||||
return std::accumulate(weights_.begin(), weights_.end(), 1UL,
|
||||
[](unsigned long l, unsigned long w) { return l * w; });
|
||||
}
|
||||
|
||||
unsigned long weight() const
|
||||
{
|
||||
return std::accumulate(weights_.begin(), weights_.end(), 0UL,
|
||||
[](unsigned long l, unsigned long w) { return l + w; });
|
||||
}
|
||||
|
||||
bool operator==(State const& rhs) const { return weights_ == rhs.weights_; }
|
||||
|
||||
bool operator<(State const& rhs) const
|
||||
{
|
||||
if (cost() < rhs.cost()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long weight() const {
|
||||
return std::accumulate(weights_.begin(), weights_.end(), 0UL,
|
||||
[](unsigned long l, unsigned long w) { return l + w; });
|
||||
}
|
||||
|
||||
bool operator==(State const &rhs) const { return weights_ == rhs.weights_; }
|
||||
|
||||
bool operator<(State const &rhs) const {
|
||||
if (cost() < rhs.cost()) { return true; }
|
||||
if (cost() == rhs.cost()) { return qe() < rhs.qe(); }
|
||||
return false;
|
||||
if (cost() == rhs.cost()) {
|
||||
return qe() < rhs.qe();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::vector<unsigned long> weights;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
weights.emplace_back(std::stoul(line));
|
||||
int main()
|
||||
{
|
||||
std::vector<unsigned long> weights;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
weights.emplace_back(std::stoul(line));
|
||||
}
|
||||
|
||||
std::set<State> states;
|
||||
unsigned long target_weight;
|
||||
for (auto w : weights) {
|
||||
states.insert(State{w});
|
||||
target_weight += w;
|
||||
}
|
||||
target_weight /= 3;
|
||||
|
||||
while (!states.empty()) {
|
||||
auto it = states.begin();
|
||||
State current(*it);
|
||||
states.erase(it);
|
||||
|
||||
if (current.weight() == target_weight) {
|
||||
std::cout << "Cost " << current.cost() << ", qe " << current.qe() << '\n';
|
||||
return 0;
|
||||
}
|
||||
if (current.weight() > target_weight) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::set<State> states;
|
||||
unsigned long target_weight;
|
||||
for (auto w: weights) {
|
||||
states.insert(State{w});
|
||||
target_weight += w;
|
||||
for (auto w : weights) {
|
||||
if (current.weights_.find(w) == current.weights_.end()) {
|
||||
auto next{current};
|
||||
next.weights_.insert(w);
|
||||
if (states.find(next) == states.end()) {
|
||||
states.insert(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
target_weight /= 3;
|
||||
}
|
||||
|
||||
while (!states.empty()) {
|
||||
auto it = states.begin();
|
||||
State current(*it);
|
||||
states.erase(it);
|
||||
|
||||
if (current.weight() == target_weight) {
|
||||
std::cout << "Cost " << current.cost() << ", qe " << current.qe() << '\n';
|
||||
return 0;
|
||||
}
|
||||
if (current.weight() > target_weight) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto w: weights) {
|
||||
if (current.weights_.find(w) == current.weights_.end()) {
|
||||
auto next{current};
|
||||
next.weights_.insert(w);
|
||||
if (states.find(next) == states.end()) {
|
||||
states.insert(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "It went wrong somewhere!\n";
|
||||
return 1;
|
||||
std::cout << "It went wrong somewhere!\n";
|
||||
return 1;
|
||||
}
|
@@ -1,78 +1,87 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct State {
|
||||
std::set<unsigned long> weights_;
|
||||
struct State
|
||||
{
|
||||
std::set<unsigned long> weights_;
|
||||
|
||||
explicit State(unsigned long w) { weights_.insert(w); }
|
||||
explicit State(unsigned long w) { weights_.insert(w); }
|
||||
|
||||
std::size_t cost() const { return weights_.size(); }
|
||||
std::size_t cost() const { return weights_.size(); }
|
||||
|
||||
unsigned long qe() const {
|
||||
return std::accumulate(weights_.begin(), weights_.end(), 1UL,
|
||||
[](unsigned long l, unsigned long w) { return l * w; });
|
||||
unsigned long qe() const
|
||||
{
|
||||
return std::accumulate(weights_.begin(), weights_.end(), 1UL,
|
||||
[](unsigned long l, unsigned long w) { return l * w; });
|
||||
}
|
||||
|
||||
unsigned long weight() const
|
||||
{
|
||||
return std::accumulate(weights_.begin(), weights_.end(), 0UL,
|
||||
[](unsigned long l, unsigned long w) { return l + w; });
|
||||
}
|
||||
|
||||
bool operator==(State const& rhs) const { return weights_ == rhs.weights_; }
|
||||
|
||||
bool operator<(State const& rhs) const
|
||||
{
|
||||
if (cost() < rhs.cost()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long weight() const {
|
||||
return std::accumulate(weights_.begin(), weights_.end(), 0UL,
|
||||
[](unsigned long l, unsigned long w) { return l + w; });
|
||||
}
|
||||
|
||||
bool operator==(State const &rhs) const { return weights_ == rhs.weights_; }
|
||||
|
||||
bool operator<(State const &rhs) const {
|
||||
if (cost() < rhs.cost()) { return true; }
|
||||
if (cost() == rhs.cost()) { return qe() < rhs.qe(); }
|
||||
return false;
|
||||
if (cost() == rhs.cost()) {
|
||||
return qe() < rhs.qe();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::vector<unsigned long> weights;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
weights.emplace_back(std::stoul(line));
|
||||
int main()
|
||||
{
|
||||
std::vector<unsigned long> weights;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
weights.emplace_back(std::stoul(line));
|
||||
}
|
||||
|
||||
std::set<State> states;
|
||||
unsigned long target_weight;
|
||||
for (auto w : weights) {
|
||||
states.insert(State{w});
|
||||
target_weight += w;
|
||||
}
|
||||
target_weight /= 4;
|
||||
|
||||
while (!states.empty()) {
|
||||
auto it = states.begin();
|
||||
State current(*it);
|
||||
states.erase(it);
|
||||
|
||||
if (current.weight() == target_weight) {
|
||||
std::cout << "Cost " << current.cost() << ", qe " << current.qe() << '\n';
|
||||
return 0;
|
||||
}
|
||||
if (current.weight() > target_weight) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::set<State> states;
|
||||
unsigned long target_weight;
|
||||
for (auto w: weights) {
|
||||
states.insert(State{w});
|
||||
target_weight += w;
|
||||
for (auto w : weights) {
|
||||
if (current.weights_.find(w) == current.weights_.end()) {
|
||||
auto next{current};
|
||||
next.weights_.insert(w);
|
||||
if (states.find(next) == states.end()) {
|
||||
states.insert(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
target_weight /= 4;
|
||||
}
|
||||
|
||||
while (!states.empty()) {
|
||||
auto it = states.begin();
|
||||
State current(*it);
|
||||
states.erase(it);
|
||||
|
||||
if (current.weight() == target_weight) {
|
||||
std::cout << "Cost " << current.cost() << ", qe " << current.qe() << '\n';
|
||||
return 0;
|
||||
}
|
||||
if (current.weight() > target_weight) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto w: weights) {
|
||||
if (current.weights_.find(w) == current.weights_.end()) {
|
||||
auto next{current};
|
||||
next.weights_.insert(w);
|
||||
if (states.find(next) == states.end()) {
|
||||
states.insert(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "It went wrong somewhere!\n";
|
||||
return 1;
|
||||
std::cout << "It went wrong somewhere!\n";
|
||||
return 1;
|
||||
}
|
@@ -1,49 +1,47 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
std::uint64_t lcg(std::uint64_t val)
|
||||
{
|
||||
return (val * 252533) % 33554393;
|
||||
}
|
||||
std::uint64_t lcg(std::uint64_t val) { return (val * 252533) % 33554393; }
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
|
||||
using namespace std::string_literals;
|
||||
auto line_begin{"To continue, please consult the code grid in the manual. Enter the code at row "s};
|
||||
auto line_middle{", column "s};
|
||||
auto line_end{"."s};
|
||||
using namespace std::string_literals;
|
||||
auto line_begin{
|
||||
"To continue, please consult the code grid in the manual. Enter the code at row "s};
|
||||
auto line_middle{", column "s};
|
||||
auto line_end{"."s};
|
||||
|
||||
assert(line.substr(0, line_begin.size()) == line_begin);
|
||||
line = line.substr(line_begin.size());
|
||||
std::size_t idx = 0;
|
||||
unsigned long target_row = std::stoul(line, &idx);
|
||||
line = line.substr(idx);
|
||||
assert(line.substr(0, line_middle.size()) == line_middle);
|
||||
line = line.substr(line_middle.size());
|
||||
unsigned long target_column = std::stoul(line, &idx);
|
||||
line = line.substr(idx);
|
||||
assert(line == line_end);
|
||||
assert(line.substr(0, line_begin.size()) == line_begin);
|
||||
line = line.substr(line_begin.size());
|
||||
std::size_t idx = 0;
|
||||
unsigned long target_row = std::stoul(line, &idx);
|
||||
line = line.substr(idx);
|
||||
assert(line.substr(0, line_middle.size()) == line_middle);
|
||||
line = line.substr(line_middle.size());
|
||||
unsigned long target_column = std::stoul(line, &idx);
|
||||
line = line.substr(idx);
|
||||
assert(line == line_end);
|
||||
|
||||
unsigned long row{1};
|
||||
unsigned long column{1};
|
||||
std::uint64_t num{20151125};
|
||||
while (row != target_row || column != target_column) {
|
||||
if (row == 1) {
|
||||
row = column + 1;
|
||||
column = 1;
|
||||
}
|
||||
else {
|
||||
--row;
|
||||
++column;
|
||||
}
|
||||
num = lcg(num);
|
||||
unsigned long row{1};
|
||||
unsigned long column{1};
|
||||
std::uint64_t num{20151125};
|
||||
while (row != target_row || column != target_column) {
|
||||
if (row == 1) {
|
||||
row = column + 1;
|
||||
column = 1;
|
||||
}
|
||||
else {
|
||||
--row;
|
||||
++column;
|
||||
}
|
||||
num = lcg(num);
|
||||
}
|
||||
|
||||
std::cout << "Target row " << target_row << " column " << target_column << '\n';
|
||||
std::cout << "Row " << row << " column " << column << " num " << num << '\n';
|
||||
return 0;
|
||||
std::cout << "Target row " << target_row << " column " << target_column << '\n';
|
||||
std::cout << "Row " << row << " column " << column << " num " << num << '\n';
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user