aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorkaiwu <kaiwu2004@gmail.com>2022-03-17 16:22:06 +0800
committerkaiwu <kaiwu2004@gmail.com>2022-03-17 16:22:06 +0800
commit6d0df82c81a01cacc3551ab525468da3b875ce41 (patch)
treec234db63ea1aaf5a83c67c896dfce969b2ab7dd0 /src
parenta6764bdef008bbaae7d8e02c67fa62fdd709c9ae (diff)
downloadadvent-of-code-6d0df82c81a01cacc3551ab525468da3b875ce41.tar.gz
advent-of-code-6d0df82c81a01cacc3551ab525468da3b875ce41.zip
call graph
Diffstat (limited to 'src')
-rw-r--r--src/2015/day7/aoc.h140
-rw-r--r--src/common.h4
2 files changed, 143 insertions, 1 deletions
diff --git a/src/2015/day7/aoc.h b/src/2015/day7/aoc.h
index af98330..7d76546 100644
--- a/src/2015/day7/aoc.h
+++ b/src/2015/day7/aoc.h
@@ -1,5 +1,143 @@
#pragma once
+#include <functional>
+#include <map>
+
+#include "common.h"
namespace aoc2015 {
-}
+struct result {
+ enum {
+ c_unknown,
+ c_value,
+ } type;
+ uint16_t value;
+
+ result op_and(result other) {
+ if (type == c_value && other.type == c_value) {
+ return result{c_value, uint16_t(value & other.value)};
+ }
+ return {c_unknown, 0};
+ }
+
+ result op_or(result other) {
+ if (type == c_value && other.type == c_value) {
+ return result{c_value, uint16_t(value | other.value)};
+ }
+ return {c_unknown, 0};
+ }
+
+ result op_leftshift(result other) {
+ if (type == c_value && other.type == c_value) {
+ return result{c_value, uint16_t(value << other.value)};
+ }
+ return {c_unknown, 0};
+ }
+
+ result op_rightshift(result other) {
+ if (type == c_value && other.type == c_value) {
+ return result{c_value, uint16_t(value >> other.value)};
+ }
+ return {c_unknown, 0};
+ }
+
+ result op_not() {
+ if (type == c_value) {
+ return result{c_value, uint16_t(~value)};
+ }
+ return {c_unknown, 0};
+ }
+};
+
+struct cals {
+ std::map<line_view, std::function<result()>> calls;
+
+ bool is_value(line_view v, uint16_t* x) const noexcept {
+ const char* p = v.line;
+ while (p != v.line + v.length) {
+ if (*p >= '0' && *p <= '9') {
+ *x = *x * 10 + *p - '0';
+ p++;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ result compute(line_view w) const noexcept {
+ uint16_t x = 0;
+ if (is_value(w, &x)) {
+ return {result::c_value, x};
+ } else {
+ auto it = calls.find(w);
+ return it != calls.end() ? it->second() : result{result::c_unknown, 0};
+ }
+ }
+
+ std::function<result()> op_and(line_view x, line_view y) {
+ return [&x, &y, this]() -> result { return compute(x).op_and(compute(y)); };
+ }
+
+ std::function<result()> op_or(line_view x, line_view y) {
+ return [&x, &y, this]() -> result { return compute(x).op_or(compute(y)); };
+ }
+
+ std::function<result()> op_leftshift(line_view x, line_view y) {
+ return [&x, &y, this]() -> result { return compute(x).op_leftshift(compute(y)); };
+ }
+
+ std::function<result()> op_rightshift(line_view x, line_view y) {
+ return [&x, &y, this]() -> result { return compute(x).op_rightshift(compute(y)); };
+ }
+
+ std::function<result()> op_not(line_view x, line_view y) {
+ return [&x, this]() -> result { return compute(x).op_not(); };
+ }
+
+ std::function<result()> op_value(line_view x, line_view y) {
+ return [&x, this]() -> result { return compute(x); };
+ }
+
+ std::function<result()> parse(line_view line, line_view* x, line_view* y, line_view* w) {
+ struct _ {
+ std::function<result()> (cals::*op)(line_view, line_view);
+ const char* label;
+ } ops[] = {
+ {&cals::op_and, "AND"},
+ {&cals::op_or, "OR"},
+ {&cals::op_leftshift, "LSHIFT"},
+ {&cals::op_rightshift, "RSHIFT"},
+ };
+ const char* arrow = line.contains("->");
+ *w = line_view(arrow + 3, line.line + line.length);
+
+ for (auto op : ops) {
+ const char* p = line.contains(op.label);
+ if (p != nullptr) {
+ *x = line_view(line.line, p - 1);
+ *y = line_view(p + strlen(op.label) + 1, arrow - 1);
+ return (this->*op.op)(*x, *y);
+ }
+ }
+
+ const char* p = line.contains("NOT");
+ if (p != nullptr) {
+ *x = line_view(p + 4, arrow - 1);
+ return op_not(*x, *y);
+ }
+
+ *x = line_view(line.line, arrow - 1);
+ return op_value(*x, *y);
+ }
+
+ void parse(line_view line) {
+ line_view* x = new line_view();
+ line_view* y = new line_view();
+ line_view* w = new line_view();
+ auto f = parse(line, x, y, w);
+ calls.insert({*w, f});
+ }
+};
+
+} // namespace aoc2015
diff --git a/src/common.h b/src/common.h
index 8d358cb..a88e16e 100644
--- a/src/common.h
+++ b/src/common.h
@@ -21,6 +21,10 @@ struct line_view {
return o;
}
+ bool operator<(const line_view& lv) const noexcept {
+ return std::string(line, length) < std::string(lv.line, lv.length);
+ }
+
bool operator==(const line_view& lv) const noexcept {
const char* p1 = line;
const char* p2 = lv.line;