Skip to content

Instantly share code, notes, and snippets.

@mavam
Created March 2, 2017 05:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mavam/e88cbba30cdb3ae9993c572f2ddc8650 to your computer and use it in GitHub Desktop.
Save mavam/e88cbba30cdb3ae9993c572f2ddc8650 to your computer and use it in GitHub Desktop.
Advent of Code - Day 10 - Part One
#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