diff --git a/d09.cc b/d09.cc index aa97518..b38b724 100644 --- a/d09.cc +++ b/d09.cc @@ -2,6 +2,11 @@ #include #include +//#define ANIMATE +#ifdef ANIMATE +#include +#endif + using namespace std; enum Dir { @@ -71,6 +76,50 @@ Input parse() return data; } +#ifdef ANIMATE +bool animate; +int min_x, max_x, min_y, max_y; +unsigned frame; +void output_img(const vector &knot, const unordered_set &visited) +{ + enum Grid { + NONE, + VISITED, + TAIL, + HEAD + }; + unsigned width = max_x - min_x; + unsigned height = max_y - min_y; + auto map = vector(width * height); + + for (auto i : visited) map[(i.y - min_y) * width + (i.x - min_x)] = VISITED; + for (auto i : knot) map[(i.y - min_y) * width + (i.x - min_x)] = TAIL; + map[(knot.front().y - min_y) * width + (knot.front().x - min_x)] = HEAD; + + char fname[] = "img/00000.pam"; + sprintf(fname, "img/%05d.pam", frame++); + auto file = ofstream(fname); + file << "P7\n"; + file << "WIDTH " << width << "\n"; + file << "HEIGHT " << height << "\n"; + file << "DEPTH 3\n"; + file << "MAXVAL 255\n"; + file << "TUPLTYPE RGB\n"; + file << "ENDHDR\n"; + for (auto i : map) { + uint32_t color = 0; + switch (i) { + case NONE: color = 0x000000; break; + case VISITED: color = 0xFF0000; break; + case TAIL: color = 0x00FF00; break; + case HEAD: color = 0x0000FF; break; + } + file.write((char *)&color, 3); + } + file.close(); +} +#endif + unsigned p1(const Input &input, unsigned count = 2) { auto knot = vector(count); @@ -90,6 +139,18 @@ unsigned p1(const Input &input, unsigned count = 2) break; } visited.insert(knot.back()); +#ifdef ANIMATE + if (!animate) { + for (auto cur : knot) { + if (cur.x < min_x) min_x = cur.x; + if (cur.x > max_x) max_x = cur.x; + if (cur.y < min_y) min_y = cur.y; + if (cur.y > max_y) max_y = cur.y; + } + } else { + output_img(knot, visited); + } +#endif } } return visited.size(); @@ -103,6 +164,13 @@ unsigned p2(const Input &input) int main() { auto input = parse(); +#ifdef ANIMATE + animate = false; + p1(input, 10); + animate = true; + p1(input, 10); + return 0; +#endif cout << p1(input) << endl; cout << p2(input) << endl; } diff --git a/d09_anim.webm b/d09_anim.webm new file mode 100644 index 0000000..487a411 Binary files /dev/null and b/d09_anim.webm differ diff --git a/makeanim.sh b/makeanim.sh new file mode 100755 index 0000000..06c8db4 --- /dev/null +++ b/makeanim.sh @@ -0,0 +1,13 @@ +#!/bin/sh +rm img/*.gif +waitjobs() { + while [ "$(jobs -p | wc -l)" -ge "$1" ]; do wait; done +} +for x in img/*.pam; do + echo "$x" + pamtogif -quiet "$x" > "$x.gif" & + waitjobs "$(nproc)" +done +wait +gifsicle -d1 --verbose img/*.gif > anim.gif +ffmpeg -i anim.gif -filter:v "setpts=0.1*PTS,scale=iw*4:ih*4:flags=neighbor" -r 100 anim.webm