Created
March 2, 2017 05:11
-
-
Save mavam/e88cbba30cdb3ae9993c572f2ddc8650 to your computer and use it in GitHub Desktop.
Advent of Code - Day 10 - Part One
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cassert> | |
#include <iostream> | |
#include <vector> | |
#include <caf/all.hpp> | |
using namespace std; | |
using namespace caf; | |
// Predicate to check whether a particular bot is the puzzle solution. | |
bool i_am_the_one(int x, int y) { | |
return (x == 61 && y == 17) || (x == 17 && y == 61); | |
} | |
// The state of every bot: a high and a low value. | |
struct bot_state { | |
actor low; | |
actor high; | |
int first = -1; | |
int second = -1; | |
}; | |
// A naive implementation of the bot actor. We don't use this one, but it's | |
// just an example of what you would do with a single behavior consisting of | |
// two message handlers. | |
behavior naive_bot(stateful_actor<bot_state>* self, int id) { | |
auto state = &self->state; // Convenience only; saves us some writing. | |
return { | |
[=](const actor& low, const actor& high) { | |
if (state->first != -1 && state->second != -1) { | |
self->send(low, std::min(state->first, state->second)); | |
self->send(high, std::max(state->first, state->second)); | |
self->quit(); | |
} else { | |
state->low = low; | |
state->high = high; | |
} | |
}, | |
[=](int value) { | |
if (state->first == -1) { | |
state->first = value; | |
} else { | |
assert(state->second == -1); | |
state->second = value; | |
if (i_am_the_one(state->first, state->second)) { | |
cout << id << endl; | |
self->quit(); | |
} else if (state->low) { | |
self->send(state->low, std::min(state->first, state->second)); | |
self->send(state->high, std::max(state->first, state->second)); | |
self->quit(); | |
} | |
} | |
} | |
}; | |
} | |
// The same bot actor as above, semantically, but implemented with behavior | |
// changes. | |
behavior bot(event_based_actor* self, int id) { | |
self->set_default_handler(skip); | |
return { | |
[=](int first) { | |
self->become( | |
[=](int second) { | |
if (i_am_the_one(first, second)) { | |
cout << id << endl; | |
self->quit(); | |
} else { | |
self->become( | |
[=](const actor& low, const actor& high) { | |
self->send(low, std::min(first, second)); | |
self->send(high, std::max(first, second)); | |
self->quit(); | |
} | |
); | |
} | |
} | |
); | |
} | |
}; | |
} | |
// The output actor. | |
behavior output(event_based_actor* self, int id) { | |
return { | |
[=](int) { | |
self->quit(); // Not much to do here for the first part... | |
} | |
}; | |
} | |
int main() { | |
// CAF's state. | |
actor_system_config cfg; | |
actor_system sys{cfg}; | |
// Initialize bots and outputs. | |
auto n = 512; | |
auto bots = vector<actor>{}; | |
auto outputs = vector<actor>{}; | |
bots.reserve(n); | |
outputs.reserve(n); | |
for (auto id = 0; id < n; ++id) { | |
bots.push_back(sys.spawn(bot, id)); | |
outputs.push_back(sys.spawn(output, id)); | |
} | |
// Read tokens from standard input and parse instructions. | |
string t; | |
while (cin) { | |
cin >> t; | |
if (t == "bot") { | |
// Example: bot 2 gives low to bot 1 and high to bot 0 | |
int source, sink; | |
string type; | |
cin >> source; | |
auto& sender = bots[source]; | |
cin >> t >> t >> t >> type >> sink; | |
auto& low = type == "bot" ? bots[sink] : outputs[sink]; | |
cin >> t >> t >> t >> type >> sink; | |
auto& high = type == "bot" ? bots[sink] : outputs[sink]; | |
anon_send(bots[source], low, high); // deliver instructions. | |
} else if (t == "value") { | |
// Example: value 5 goes to bot 2 | |
int value, sink; | |
cin >> value >> t >> t >> t >> sink; | |
anon_send(bots[sink], value); | |
} else if (cin) { | |
cerr << "unexpected token: " << t << endl; | |
return 1; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment