Skip to content

Commit 24ce9b9

Browse files
committed
Add 2017 day 20 cpp
1 parent 5e84b44 commit 24ce9b9

File tree

4 files changed

+302
-1
lines changed

4 files changed

+302
-1
lines changed

2017/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ This folder contains solutions to each of the problems in Advent of Code 2017 in
2727
| <nobr> [Day 17: Spinlock](https://adventofcode.com/2017/day/17) </nobr> | <nobr> [Part 1](/2017/cpp/day_17a.cpp) [Part 2](/2017/cpp/day_17b.cpp) </nobr> |[Link](/2017/input/day_17_input)|[Link](/2017/sample_input/day_17_sample_input)|[Link](/2017/puzzles/day_17_puzzle)|
2828
| <nobr> [Day 18: Duet](https://adventofcode.com/2017/day/18) </nobr> | <nobr> [Part 1](/2017/cpp/day_18a.cpp) [Part 2](/2017/cpp/day_18b.cpp) </nobr> |[Link](/2017/input/day_18_input)|[Link](/2017/sample_input/day_18_sample_input)|[Link](/2017/puzzles/day_18_puzzle)|
2929
| <nobr> [Day 19: A Series of Tubes](https://adventofcode.com/2017/day/19) </nobr> | <nobr> [Part 1](/2017/cpp/day_19a.cpp) [Part 2](/2017/cpp/day_19b.cpp) </nobr> |[Link](/2017/input/day_19_input)|[Link](/2017/sample_input/day_19_sample_input)|[Link](/2017/puzzles/day_19_puzzle)|
30+
| <nobr> [Day 20: Particle Swarm](https://adventofcode.com/2017/day/20) </nobr> | <nobr> [Part 1](/2017/cpp/day_20a.cpp) [Part 2](/2017/cpp/day_20b.cpp) </nobr> |[Link](/2017/input/day_20_input)|[Link](/2017/sample_input/day_20_sample_input)|[Link](/2017/puzzles/day_20_puzzle)|
3031

3132
#### TODO ####
3233

3334
|Puzzle|C++ Solutions|Input|Sample Input|Puzzle page with solutions|
3435
|:---:|:---:|:---:|:---:|:---:|
35-
| <nobr> [Day 20: ](https://adventofcode.com/2017/day/20) </nobr> | <nobr> [Part 1](/2017/cpp/day_20a.cpp) [Part 2](/2017/cpp/day_20b.cpp) </nobr> |[Link](/2017/input/day_20_input)|[Link](/2017/sample_input/day_20_sample_input)|[Link](/2017/puzzles/day_20_puzzle)|
3636
| <nobr> [Day 21: ](https://adventofcode.com/2017/day/21) </nobr> | <nobr> [Part 1](/2017/cpp/day_21a.cpp) [Part 2](/2017/cpp/day_21b.cpp) </nobr> |[Link](/2017/input/day_21_input)|[Link](/2017/sample_input/day_21_sample_input)|[Link](/2017/puzzles/day_21_puzzle)|
3737
| <nobr> [Day 22: ](https://adventofcode.com/2017/day/22) </nobr> | <nobr> [Part 1](/2017/cpp/day_22a.cpp) [Part 2](/2017/cpp/day_22b.cpp) </nobr> |[Link](/2017/input/day_22_input)|[Link](/2017/sample_input/day_22_sample_input)|[Link](/2017/puzzles/day_22_puzzle)|
3838
| <nobr> [Day 23: ](https://adventofcode.com/2017/day/23) </nobr> | <nobr> [Part 1](/2017/cpp/day_23a.cpp) [Part 2](/2017/cpp/day_23b.cpp) </nobr> |[Link](/2017/input/day_23_input)|[Link](/2017/sample_input/day_23_sample_input)|[Link](/2017/puzzles/day_23_puzzle)|

2017/cpp/day_20a.cpp

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#include <algorithm>
2+
#include <fstream>
3+
#include <iostream>
4+
#include <string>
5+
#include <limits>
6+
#include <unordered_map>
7+
#include <unordered_set>
8+
#include <vector>
9+
#include <regex>
10+
11+
struct Coord3D {
12+
int x;
13+
int y;
14+
int z;
15+
16+
int dist () const {
17+
return std::abs(x) + std::abs(y) + std::abs(z);
18+
}
19+
20+
int sum () const {
21+
return x + y + z;
22+
}
23+
24+
Coord3D operator + (const Coord3D& c) {
25+
Coord3D ans;
26+
ans.x = x + c.x;
27+
ans.y = y + c.y;
28+
ans.z = z + c.z;
29+
return ans;
30+
}
31+
32+
Coord3D operator += (const Coord3D& c) {
33+
x += c.x;
34+
y += c.y;
35+
z += c.z;
36+
return *this;
37+
}
38+
};
39+
40+
int dot_product(const Coord3D& v0, const Coord3D& v1) {
41+
return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
42+
}
43+
44+
struct Particle {
45+
Coord3D p;
46+
Coord3D v;
47+
Coord3D a;
48+
};
49+
50+
int main(int argc, char* argv[]) {
51+
const std::string input = (argc > 1) ? argv[1] : "../input/day_20_input" ;
52+
std::ifstream file(input);
53+
std::string line;
54+
const std::regex pattern(R"(p=<(-?[0-9]+),(-?[0-9]+),(-?[0-9]+)>, v=<(-?[0-9]+),(-?[0-9]+),(-?[0-9]+)>, a=<(-?[0-9]+),(-?[0-9]+),(-?[0-9]+)>)");
55+
std::vector<Particle> particles;
56+
int min_acc = std::numeric_limits<int>::max();
57+
std::vector<int> particles_with_min_acc;
58+
// Find all particles with the minimum acceleration
59+
// as at t-> infinity, those will be the closest
60+
while(std::getline(file, line)) {
61+
std::smatch match;
62+
std::regex_search(line, match, pattern);
63+
Particle particle;
64+
particle.p.x = std::stoi(match[1]);
65+
particle.p.y = std::stoi(match[2]);
66+
particle.p.z = std::stoi(match[3]);
67+
particle.v.x = std::stoi(match[4]);
68+
particle.v.y = std::stoi(match[5]);
69+
particle.v.z = std::stoi(match[6]);
70+
particle.a.x = std::stoi(match[7]);
71+
particle.a.y = std::stoi(match[8]);
72+
particle.a.z = std::stoi(match[9]);
73+
particles.push_back(particle);
74+
if (particle.a.dist() < min_acc) {
75+
particles_with_min_acc.clear();
76+
particles_with_min_acc.push_back(particles.size()-1);
77+
min_acc = particle.a.dist();
78+
} else if (particle.a.dist() == min_acc) {
79+
particles_with_min_acc.push_back(particles.size()-1);
80+
}
81+
}
82+
83+
// If particles have the same acceleration,
84+
// Find the time at which each is closest to the origin
85+
// Get the latest time
86+
// Check the other particles' distances
87+
// Lowest distance at the final time
88+
89+
int ans = particles_with_min_acc[0];
90+
int min_dist = std::numeric_limits<int>::max();
91+
int time = 0;
92+
while (std::any_of(
93+
std::begin(particles_with_min_acc),
94+
std::end(particles_with_min_acc),
95+
[&particles](const int idx) {
96+
const auto& particle = particles[idx];
97+
return dot_product(particle.p, particle.v) < 0 || dot_product(particle.p, particle.a) < 0;
98+
})) {
99+
for (const auto idx : particles_with_min_acc) {
100+
auto& particle = particles[idx];
101+
if (min_dist > particle.p.dist()) {
102+
// std::cout << idx << " is closest at time " << time << '\n';
103+
min_dist = particle.p.dist();
104+
ans = idx;
105+
}
106+
particle.p = particle.p + particle.v;
107+
particle.v = particle.v + particle.a;
108+
}
109+
time++;
110+
}
111+
std::cout << ans << '\n';
112+
return 0;
113+
}

2017/cpp/day_20b.cpp

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#include <algorithm>
2+
#include <fstream>
3+
#include <iostream>
4+
#include <string>
5+
#include <limits>
6+
#include <unordered_map>
7+
#include <unordered_set>
8+
#include <vector>
9+
#include <cmath>
10+
#include <regex>
11+
12+
// Note: increment velocity first, then position (mentioned in part 1 i.e. part a)
13+
// time: position(time)
14+
// 0: p(0) = p0
15+
// 1: p(1) = p0 + v + a
16+
// 2: p(2) = p0 + v + a + v + 2a
17+
// n: p(n) = p0 + v + a + ... + v + na = p0 + n * v + n(n+1)/2 * a
18+
// p(t) = (a * t^2 + (a + 2v) * t + 2 * p0) / 2
19+
20+
struct Coord3D {
21+
long long x;
22+
long long y;
23+
long long z;
24+
25+
long long dist () const {
26+
return std::abs(x) + std::abs(y) + std::abs(z);
27+
}
28+
29+
long long sum () const {
30+
return x + y + z;
31+
}
32+
33+
Coord3D operator + (const Coord3D& c) const {
34+
Coord3D ans;
35+
ans.x = x + c.x;
36+
ans.y = y + c.y;
37+
ans.z = z + c.z;
38+
return ans;
39+
}
40+
41+
Coord3D operator - (const Coord3D& c) const {
42+
Coord3D ans;
43+
ans.x = x - c.x;
44+
ans.y = y - c.y;
45+
ans.z = z - c.z;
46+
return ans;
47+
}
48+
49+
Coord3D operator += (const Coord3D& c) {
50+
x += c.x;
51+
y += c.y;
52+
z += c.z;
53+
return *this;
54+
}
55+
};
56+
57+
long long dot_product(const Coord3D& v0, const Coord3D& v1) {
58+
return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
59+
}
60+
61+
struct Particle {
62+
Coord3D p;
63+
Coord3D v;
64+
Coord3D a;
65+
};
66+
67+
struct Collision {
68+
long long id0;
69+
long long id1;
70+
long long time;
71+
};
72+
73+
int find_position_at_time (const int p, const int v, const int a, const int time) {
74+
// std::cout << "Values: " << s << ' ' << v << ' ' << a << ' ' << time << '\n';
75+
// std::cout << "Position: " << s + (time + 1 ) * v + (time * time + 1 * a) / 2 << '\n';
76+
return (a * time * time + (a + 2 * v) * time + 2 * p) / 2;
77+
}
78+
79+
std::vector<long long> find_time_of_potential_collision(const int p0, const int p1, const int v0, const int v1, const int a0, const int a1) {
80+
const auto a = float(a1 - a0);
81+
float t0 = 0;
82+
float t1 = 0;
83+
if (a == 0) {
84+
t0 = -float(p1 -p0) / float(v1 - v0);
85+
t1 = -1;
86+
} else {
87+
const auto b = float((a1 - a0) + 2 * (v1 - v0));
88+
const auto c = float(2.f * (p1 - p0));
89+
// std::cout << "Quad equation values: " << a << ' ' << b << ' ' << c << '\n';
90+
const auto discriminent_2 = (b * b) - 4 * a *c;
91+
if (discriminent_2 < 0) {
92+
// std::cout << "No collision possible; negative b2-4ac" << '\n';
93+
return {-1, -1};
94+
}
95+
// TODO: improve this check
96+
const auto discriminent = std::sqrt(discriminent_2);
97+
if (discriminent != int(discriminent)) {
98+
// std::cout << "No collision possible, not a perfect square: " << discriminent << '\n';
99+
return {-1, -1};
100+
}
101+
t0 = (-b + discriminent) / (2 * a);
102+
t1 = (-b - discriminent) / (2 * a);
103+
}
104+
if (t0 < 0) t0 = -1;
105+
if (t1 < 0) t1 = -1;
106+
// std::cout << t0 << ' ' << t1 << '\n';
107+
if (t0 != int(t0)) t0 = -1;
108+
if (t1 != int(t1)) t1 = -1;
109+
// std::cout << "Possible times: " << t0 << ' ' << t1 << '\n';
110+
return {static_cast<long long>(t0), static_cast<long long>(t1)};
111+
}
112+
113+
int main(int argc, char* argv[]) {
114+
const std::string input = (argc > 1) ? argv[1] : "../input/day_20_input" ;
115+
std::ifstream file(input);
116+
std::string line;
117+
const std::regex pattern(R"(p=<(-?[0-9]+),(-?[0-9]+),(-?[0-9]+)>, v=<(-?[0-9]+),(-?[0-9]+),(-?[0-9]+)>, a=<(-?[0-9]+),(-?[0-9]+),(-?[0-9]+)>)");
118+
std::vector<Particle> particles;
119+
long long min_acc = std::numeric_limits<long long>::max();
120+
while(std::getline(file, line)) {
121+
std::smatch match;
122+
std::regex_search(line, match, pattern);
123+
Particle particle;
124+
particle.p.x = std::stoi(match[1]);
125+
particle.p.y = std::stoi(match[2]);
126+
particle.p.z = std::stoi(match[3]);
127+
particle.v.x = std::stoi(match[4]);
128+
particle.v.y = std::stoi(match[5]);
129+
particle.v.z = std::stoi(match[6]);
130+
particle.a.x = std::stoi(match[7]);
131+
particle.a.y = std::stoi(match[8]);
132+
particle.a.z = std::stoi(match[9]);
133+
particles.push_back(particle);
134+
}
135+
136+
std::vector<Collision> collisions;
137+
for (int i = 0; i < particles.size(); i++) {
138+
for (int j = i + 1; j < particles.size(); j++) {
139+
// std::cout << "\nPair: (" << i << "," << j << "): " << '\n';
140+
const auto times = find_time_of_potential_collision(particles[i].p.x, particles[j].p.x, particles[i].v.x, particles[j].v.x, particles[i].a.x, particles[j].a.x);
141+
for (const auto time : times) {
142+
// std::cout << "Time: " << time << '\n';
143+
if (time != -1 && find_position_at_time(particles[i].p.y, particles[i].v.y, particles[i].a.y, time)
144+
== find_position_at_time(particles[j].p.y, particles[j].v.y, particles[j].a.y, time) &&
145+
find_position_at_time(particles[i].p.z, particles[i].v.z, particles[i].a.z, time)
146+
== find_position_at_time(particles[j].p.z, particles[j].v.z, particles[j].a.z, time) ) {
147+
// std::cout << "Collision!!!!!!!!!! Time: " << time << '\n';
148+
Collision c;
149+
c.id0 = i;
150+
c.id1 = j;
151+
c.time = time;
152+
collisions.push_back(c);
153+
}
154+
}
155+
}
156+
}
157+
158+
std::sort(std::begin(collisions), std::end(collisions), [](const auto& c1, const auto& c2) {return c1.time < c2.time; });
159+
// for (const auto & c : collisions) {
160+
// std::cout << c.time << '\n';
161+
// }
162+
std::unordered_map<long long, long long> id_to_destruction_time;
163+
for (const auto& c : collisions) {
164+
if (id_to_destruction_time.find(c.id0) == id_to_destruction_time.end() && id_to_destruction_time.find(c.id1) == id_to_destruction_time.end()) {
165+
id_to_destruction_time[c.id0] = c.time;
166+
id_to_destruction_time[c.id1] = c.time;
167+
// std::cout << "Adding " << c.id0 << '\n';
168+
// std::cout << "Adding " << c.id1 << '\n';
169+
} else if (id_to_destruction_time.find(c.id0) != id_to_destruction_time.end() && id_to_destruction_time[c.id0] == c.time) {
170+
id_to_destruction_time[c.id1] = c.time;
171+
// std::cout << "Adding " << c.id1 << '\n';
172+
} else if (id_to_destruction_time.find(c.id1) != id_to_destruction_time.end() && id_to_destruction_time[c.id1] == c.time) {
173+
id_to_destruction_time[c.id0] = c.time;
174+
// std::cout << "Adding " << c.id0 << '\n';
175+
}
176+
}
177+
std::cout << particles.size() - id_to_destruction_time.size() << '\n';
178+
return 0;
179+
}
180+
181+

2017/sample_input/day_20_sample_input

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
p=< 3,0,0>, v=< 2,0,0>, a=<-1,0,0>
2+
p=< 4,0,0>, v=< 0,0,0>, a=<-2,0,0>
3+
4+
p=<-6,0,0>, v=<3,0,0>, a=<0,0,0>
5+
p=<-4,0,0>, v=<2,0,0>, a=<0,0,0>
6+
p=<-2,0,0>, v=<1,0,0>, a=<0,0,0>
7+
p=<4,0,0>, v=<-1,0,0>, a=<-1,0,0>

0 commit comments

Comments
 (0)