diff --git a/d12.cc b/d12.cc new file mode 100644 index 0000000..697698e --- /dev/null +++ b/d12.cc @@ -0,0 +1,161 @@ +#include +#include +#include +#include + +//#define ANIMATE + +using namespace std; + +struct Input { + vector> map; + unsigned width; + unsigned height; + complex start; + complex end; +}; + +complex dirs[] = { + complex(1, 0), + complex(0, 1), + complex(-1, 0), + complex(0, -1) +}; + +Input parse() +{ + Input data; + auto &map = data.map; + for (string line; getline(cin, line);) { + vector row; + for (auto x : line) { + switch (x) { + case 'S': + data.start = complex(row.size(), map.size()); + row.push_back('a' - 'a'); + break; + case 'E': + data.end = complex(row.size(), map.size()); + row.push_back('z' - 'a'); + break; + default: row.push_back(x - 'a'); break; + } + } + data.map.push_back(row); + } + data.width = map.front().size(); + data.height = map.size(); + return data; +} + +#ifdef ANIMATE +#include +unsigned render_frame = 0; +void render(const Input &input, vector> &dist, deque> &scan) +{ + auto scan_map = (bool (*)[input.width])new bool[input.width * input.height](); + for (auto &x : scan) { + scan_map[x.imag()][x.real()] = true; + } + + char fname[] = "img/00000.pam"; + sprintf(fname, "img/%05u.pam", render_frame++); + auto file = ofstream(fname); + file << "P7\n"; + file << "WIDTH " << input.width << '\n'; + file << "HEIGHT " << input.height << '\n'; + file << "DEPTH 3\nMAXVAL 255\nTUPLTYPE RGB\nENDHDR\n"; + + unsigned maxdist = 0; + for (unsigned y = 0; y < input.height; y++) { + for (unsigned x = 0; x < input.width; x++) { + unsigned d = dist[y][x]; + if (d > maxdist) maxdist = d; + } + } + + for (unsigned y = 0; y < input.height; y++) { + for (unsigned x = 0; x < input.width; x++) { + uint32_t color = 0; + color |= ((dist[y][x] * 0xFF / maxdist) & 0xFF) << 8; + color |= input.map[y][x] * 0xFF / 26; + if (scan_map[y][x]) color = 0xFF0000; + file.write((char *)&color, 3); + } + } + file.close(); + delete scan_map; +} +#endif + +vector> calc_dist(const Input &input) +{ + vector> dist(input.height, vector(input.width)); + auto &map = input.map; + + deque> scan; + scan.push_back(input.end); + dist[input.end.imag()][input.end.real()] = 1; + + while (!scan.empty()) { + auto pos = scan.front(); + unsigned pos_d = dist[pos.imag()][pos.real()]; + unsigned pos_h = map[pos.imag()][pos.real()]; + scan.pop_front(); + + for (auto dir : dirs) { + auto newpos = pos + dir; + + // Make sure the new position is in-bounds + if (newpos.imag() < 0 || newpos.imag() >= (int)input.height) continue; + if (newpos.real() < 0 || newpos.real() >= (int)input.width) continue; + + // If the distance for this position has already been calculated, + // and is smaller than the current pos' distance, skip it. + unsigned &newpos_d = dist[newpos.imag()][newpos.real()]; + if (newpos_d && newpos_d <= pos_d + 1) continue; + + // Make sure the height difference isn't too big + unsigned newpos_h = map[newpos.imag()][newpos.real()]; + if ((int)pos_h - (int)newpos_h > 1) continue; + + // Otherwise, continue down this path + newpos_d = pos_d + 1; + scan.push_back(newpos); + } +#ifdef ANIMATE + render(input, dist, scan); +#endif + } + return dist; +} + +unsigned p1(const Input &input, const vector> &dist) +{ + unsigned end_dist = dist[input.start.imag()][input.start.real()]; + if (end_dist) end_dist--; + return end_dist; +} + +unsigned p2(const Input &input, const vector> &dist) +{ + unsigned smallest = dist[input.start.imag()][input.start.real()]; + for (unsigned y = 0; y < input.height; y++) { + for (unsigned x = 0; x < input.width; x++) { + if (input.map[y][x] == 0) { + unsigned d = dist[y][x]; + if (d && d < smallest) smallest = d; + } + } + } + if (smallest) smallest--; + return smallest; +} + +int main() +{ + auto input = parse(); + auto dist = calc_dist(input); + cout << p1(input, dist) << endl; + cout << p2(input, dist) << endl; +} diff --git a/d12_anim.webm b/d12_anim.webm new file mode 100644 index 0000000..5a85745 Binary files /dev/null and b/d12_anim.webm differ diff --git a/d12_input.txt b/d12_input.txt new file mode 100644 index 0000000..1fb4f0a --- /dev/null +++ b/d12_input.txt @@ -0,0 +1,41 @@ +abcccccccccccccccccaaccccccccccccaaaaaaaacccccccccccaaaaaccccaaaaaaccaaaaaaaaaaaaaaaaaccccccccccccccccaaacccccaaaaaaaacccaaaccccccccccccccccccccccccccccccccccccccccccccccccccaaaaa +abccccccccccccccccaaacaacccccccccccaaaacccccccccccccaaaaaacccaaaaaaccaaaaaaaaaaaaaaaaaaaacccccccccaaacaaacccccaaaaaaaaaccaaaaccccccccccccccccccccccccccccccccccccccccccccccccaaaaaa +abcccccccccccccccccaaaaacccccccccccaaaaaccccccccccccaaaaaaccccaaaacccaaaacccaaaaaaaaaaaaacccccccccaaaaaaaaaacccaaaaaaaaccaaaaccccccccccccccccccccccccccccccccccaaacccccccccccaaaaaa +abcccccccccccccccaaaaaacccccccccccaaacaaccaaccccccccaaaaaaccccaaaacccaaaccccaaaaaaaaaaaaaccccccccccaaaaaaaaaccaaaaaacccccaaacccccccccccccccccccccccccccccccccccaaaccccccccccccccaaa +abcccccccccccccccaaaaaaaacccccccccaacccacaaacaacccccccaaccccccaccaccccccccaaaaaaaaaaaaccccccccccccccaaaaaaacccaaaaaaacccccccccccccaacccccccccccccccccccccccccccaaaccccccccccccccaaa +abcccccccccccccccaacaaaaacccccccccccccccccaaaaacccccccccccccccccccccccccccaaaaaaaaaaaaccccccccccccccaaaaaaccccaaccaaacccccccccccaaaaaaccccccccccccccccccccccccccdccccccccccccccccaa +abccaacccccccaaacccaaacaccccccccccaaacccaaaaaaccccccccccccccccccccccccccccaaacccaaaaaacaaaaccccccccaaaaaaaccccccccaaacccccccccccaaaaaacccccccccccccccccllllllcccdddddcccccccccccccc +abaaaacccacccaaccccaacccccccccccccaaacccaaaaaaaacccccccccccccccccaaccccccccacccaaaaccccaaaaccccccccaaacaaaccccccccccccccccccccccaaaaaaccccccccccccccccllllllllldddddddddddccaaccccc +abaaaaccaaaaaaaacccccccccccccccaaaaaaaacaacaaaaacccccccccccccccccaaacccccccaaacaaccccccaaaacccccccccccccaaccccccccccccccccccccccaaaaaccccccccccccccccclllllllllldddddddddeeaaaccccc +abaaaccccaaaaaaaaccccccccaaacccaaaaaaaacccaaacccccccccccccccccaaaaaaaaccccccaaaaacccccccaacccccccccccccccccccccccccccccccccccccccaaaaccccaaaccccccccckllppppplllmmmmmmmdeeeeaaccccc +abaaaacccaaaaaaaaacccccaaaaaaccccaaaaaccccaaccccccccccccccccccaaaaaaaaccccccaaaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccaaaacccccccckklpppppppplmmmmmmmmmeeeeaccccc +abaaaacccaaaaaaaaacccccaaaaaacccaaaaaaccccccccaacccccccccccccccaaaaaaccccccaaaaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccaaaacccccccckkkppppppppqmmmmmmmmmmeeeaacccc +abaaaaaccaaaaaaaaccccccaaaaaacccaaaaaaccccccacaaaacccccccccccccaaaaaaccccccaaaaaaaaccccccccaaaaccccccccaaacccccccccccccccccccccccccccccccaaacccccccckkkpppuuuppqqqqqqqqmmmeeeeacccc +abacccccaaaaaaaccccccccaaaaaccccaccaaaccccccaaaaaacccccacccccccaaaaaaccccccaaaaaacaaaccccccaaaaccccccccaaaacccccccccccccccccccccccccccccccccccccccckkkpppuuuuuuqqqqqqqqqnnneeeccccc +abcccccccaccaaaccccccccaaaaacccccccccccccccccaaaacccaaaacccccccaacaaacccccccccaaacaaaaaccccaaaaccccccccaaaaccccccccccccccccccccccccccccccccccccccckkkkpppuuuuuuuqvvvvqqqnnneeeccccc +abcccccccccccaaacaaccccccccccccccccccccccccccaaaacccaaaaaacccccccccccccccccccccccaaaaaaccccaaacccccccccaaaccccccccccccccccccccccccccccccccccccccckkkkrrpuuuxxxuvvvvvvvqqnnneeeccccc +abcccccccccccccccaacaaaccccccccccccccccccccccaacaacccaaaaacccccccccccccccccccccccaaaaaaccccccccccccccccccccccccccccccccccccccccccccccccccccccccckkkkrrrruuxxxxuvvvvvvvqqnnneeeccccc +abcccccccccccccccaaaaacccccccccccccccccccccccccccaccaaaaacccccaaccccccccccccccccccaaaaaccccccccccccccccaaaccccccccccccccaaacccccccccccccccccccckkkkrrrruuuxxxxyyyyyvvvqqnnneecccccc +abcccccccccccccaaaaaacccccccccccaacaacccccccccccaaaaaaaaacccacaaaacaaccaaccccccccaaacaaccccccccccaaccccaaaaaacccaacaacccaaacacccccccccccccccccjjkkrrrruuuuuxxxyyyyyvvqrqnneffcccccc +abcccccccccccccaaaaaaaacccaaacccaaaaaccccccaacccaaaaaaaaacccaaaaaacaaaaaaccccccccaaacaaacccccccaaaaaacaaaaaaacccaaaaacaaaaaaaaccccccccccccccccjjjrrrtttuuxxxxxyyyyyvvrrnnnfffcccccc +SbccccccccccccccccaaaaacccaaaaccaaaaaaccccaaaaaacaaaaaaaaacccaaaacccaaaaaccccccccaaaaaaacccccccaaaaaaaaaaaaaaccaaaaaccaaaaaaaaccccccccccccccccjjjrrrtttxxxEzzzzyyyvvrrrnnnfffcccccc +abccccccccccaaaccaaccaacccaaaaccaaaaaacccccaaaaacaaaaaaaaacccaaaaccaaaaaacccccccccaaaaaaccccccccaaaacaaaaaaacccaaaaaaccaaaaaacccccccccccccccccjjjrrrtttxxxxxyyyyyyvvrrrnnnfffcccccc +abcccccccccaaaaccaacccccccaaacccaaaaaacccaaaaaaaaaaaaaaaaacccaacacaaaaaaaacccccaaaaaaaacccccccccaaaacccaaaaaaccccaaaacccaaaaacccccccccccccccccjjjrrrtttxxxxxyyyyyyywvrrnnnfffcccccc +abcccccccccaaaacccccccccccccccccccaaaccccaaaaaaaaaaaaaaaaaacccccccaaaaaaaacccccaaaaaaaaaccccccccaccacccaaaaaaccccacccccaaaaaacccccccccccccccccjjjrrrrttttxxxyyyyyyywwrrroooffcccccc +abccccccccccaaaccccccccccccccccccccccccccaaaaaaaaaccaaaaaaaccccccccccaaccccccccaaaaaaaaaaccccccccccccccaacccccccccccccccaaccccccccccccccccccccjjjjqqqqttttxxyywwwwwwwwrrooofffccccc +abcccccccccccccccccccccccccccccccccccccccccaaacacccccaaaaccccccccccccaacccccccccccaaacaaacccccccccccccccccccccccccccccaaacccccccccccccccccccaacjjjjqqqqqttwwwwwwwwwwwrrrooofffccccc +abcccccccccccccccccccccccccccccccccccccccccaaccccccccccaacccccccccccccccccccccccccaaacccccccccccccccccccccccccccccccccaaacccccccccccccccccaaaaaajjjjqqqqttwwwwwwsswwrrrrooofffccccc +abcccccaaaaccccccccccccccaacaaccccccccccccccccccccccccccccccccccccccccccccccccccccaacccccccccccccccccccccccccccccccaaaaaaaaccaaaacccccccccaaaaaacjjjiqqqtttwwwwsssssrrrrooofffccccc +abccccaaaaaccccccccccccccaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaaaaccaaaaacccccccccaaaaacciiiiqqttswwwssssssrrroooogffccccc +abccccaaaaaacccccccccccccaaaaaacccaaaccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaccaaaaaaccccccccaaaaacccciiiqqqssssssspppooooooogggaccccc +abccccaaaaaaccccccccaacccaaaaaaccccaacccccccccccccccccccccccccccccccccaaaaccccccccccccccccccccccccccccccccccccccccccaaaaaaccaaaaaaccccccccaaaaaccccciiiqqsssssspppppoooooggggaacccc +abccccaaaaaccccccaaaaacccaaaaaacaacaaaaaccccccccccccccccccccaacccccccaaaaacccccccccccaaaccccccccccccccccccccccccccccaaaaaacccaaaaacccccccccacccccccciiiqqqpssspppppgggggggggaaacccc +abccccccaaacccccccaaaaaccccaaaccaaaaaaaacccccccaacccccccaaccaacccccccaaaaaacccccccccaaaacccccccccccaaaaccccccccccccaaccaaacccaaacccccaaacaaaccccccccciiqqppppppphhhggggggggaaaacccc +abccccccccccccccccaaaaaccccccccccaaaaaccccccccaaacaaccccaaaaaacccccccaaaaaaaccccccccaaaacccccccccccaaaacccccccccaaaaaacccccccccccccccaaaaaaaccccccccciiippppppphhhhggggggcaaacccccc +abaacccccccccccccaaaaaccccccccccccaaaaaccccccccaaaaacccccaaaaaaacccccaaaaacaaacccccccaaacccccccccccaaaacccccccccaaaaacccccccccccccccccaaaaaacccccccccciiiippphhhhhhcccccccaaacccccc +abaacccccccccccccccaaacccccccccccaaacaaccccccaaaaaaccccccaaaaaaacccaaccaaacaaaaccaaaccccccccccccccccaaacccccccccaaaaaaacccccccccccccccaaaaaaaacccccccciiihhhhhhhhaaaccccccccccccccc +abaaccccccccccccccccccccccccccccccaacccccccccaaaaaaaacccaaaaaaccaaaaaacccccaaaacaaaaaccccccccccccccccccccccccccaaaaaaaaccccccccccccccaaaaaaaaaccccccccciihhhhhhcaaaacccccccccccccca +abaaccccccccccccccccccccccccccccccccaacccccccaacaaaaacccaaaaaaccaaaaacccccccaaaaaaaacccccccccccccccccccccccccccaaaaaaaacccccccccaaacaaaaaaaaaacccccccccccchhhaccccaacccccccccccccca +abaaccccccccccccccccccccccccccccccccaaaaaaccccccaaccccccccccaaccaaaaaaacccccaaaaaaaccccccccccccccccccccccccaaaccacaaacccccccccccaaaaaaacaaacaaaaaacccccccccaaacccccccccccccccaaaaaa +abccccccccccccccccccccccccccccccccccaaaaaccccccaaccccccccccccccaaaaaaaacaaaaaaaaaaccccccccccccccccccccccccaaaaaaccaaaccccccccccccaaaaaacaaacaaaaaacccccccccaaaccccccccccccccccaaaaa +abccccccccccccccccccccccccccccccccaaaaaaaacccccccccccccccccccccaaaaaaaacaaaaaaaaaaaaacccccccccccccccccccccaaaaaacccccccccccccccaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccaaaaa diff --git a/d12_output.txt b/d12_output.txt new file mode 100644 index 0000000..df250eb --- /dev/null +++ b/d12_output.txt @@ -0,0 +1,2 @@ +484 +478 diff --git a/makeanim.sh b/makeanim.sh index 06c8db4..21e7837 100755 --- a/makeanim.sh +++ b/makeanim.sh @@ -1,13 +1,4 @@ #!/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 +ffmpeg -threads 0 -pattern_type glob -i "img/*.pam" -r 60 \ + -filter:v "setpts=0.05*PTS,scale=iw*4:ih*4:flags=neighbor" \ + anim.webm