Skip to content

Commit

Permalink
Merge pull request #196 from th-ch/skasch/day24-3
Browse files Browse the repository at this point in the history
Optimize day 24
  • Loading branch information
skasch authored Dec 27, 2023
2 parents f033826 + f12d25f commit e66660d
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 105 deletions.
93 changes: 12 additions & 81 deletions day-24/part-1/skasch.cpp
Original file line number Diff line number Diff line change
@@ -1,110 +1,41 @@
#include <chrono>
#include <cstdint>
#include <iostream>
#include <span>
#include <sstream>
#include <string>

static constexpr __int128_t kMinTestArea = 200000000000000;
static constexpr __int128_t kMaxTestArea = 400000000000000;
static constexpr std::int64_t kMinTestArea = 200000000000000;
static constexpr std::int64_t kMaxTestArea = 400000000000000;
static constexpr int kNHails = 300;

__int128_t gcd(__int128_t a, __int128_t b) {
if (b < 0) b = -b;
if (a < 0) a = -a;
if (a < b) std::swap(a, b);
if (b == 0) return a;
__int128_t r;
while (a % b > 0) {
r = a % b;
a = b;
b = r;
}
return b;
}

class Frac {
public:
Frac(__int128_t n) : num_(n), den_(1) {}
Frac() : Frac(0) {}
Frac(__int128_t n, __int128_t d) {
if (d < 0) {
n = -n;
d = -d;
}
__int128_t g = gcd(n, d);
num_ = n / g;
den_ = d / g;
}

__int128_t n() const { return num_; }
__int128_t d() const { return den_; }

Frac operator+(const Frac& o) const {
__int128_t g = gcd(d(), o.d());
__int128_t d1 = d() / g;
__int128_t d2 = o.d() / g;
return Frac(n() * d2 + d1 * o.n(), g * d1 * d2);
}
Frac operator-() const { return Frac(-n(), d()); }
Frac operator-(const Frac& o) const { return *this + (-o); }

Frac operator*(const Frac& o) const {
__int128_t g1 = gcd(n(), o.d());
__int128_t g2 = gcd(o.n(), d());
return Frac((n() / g1) * (o.n() / g2), (d() / g2) * (o.d() / g1));
}
Frac operator/(__int128_t k) const {
__int128_t g = gcd(n(), k);
return Frac(n() / g, d() * (k / g));
}
friend Frac operator/(__int128_t k, const Frac& o) {
__int128_t g = gcd(k, o.n());
return Frac((k / g) * o.d(), o.n() / g);
}
Frac operator/(const Frac& o) const { return *this * (1 / o); }

Frac operator*(__int128_t k) {
__int128_t g = gcd(k, d());
return Frac((k / g) * n(), d() / g);
}
friend Frac operator*(__int128_t k, const Frac& o) { return o * k; }

bool operator==(const Frac& o) const { return n() == o.n() && d() == o.d(); }
auto operator<=>(const Frac& o) const { return n() * o.d() <=> d() * o.n(); }
auto operator<=>(__int128_t k) const { return n() <=> d() * k; }
friend auto operator<=>(__int128_t k, const Frac& o) {
return k * o.d() <=> o.n();
}

private:
__int128_t num_;
__int128_t den_;
};

struct Vec {
Frac x;
Frac y;
long double x;
long double y;

bool InTestArea() {
return kMinTestArea <= x && x <= kMaxTestArea && kMinTestArea <= y &&
y <= kMaxTestArea;
}

Vec operator+(const Vec& o) const { return {x + o.x, y + o.y}; }
friend Vec operator*(Frac k, const Vec& v) { return {k * v.x, k * v.y}; }
friend Vec operator*(long double k, const Vec& v) {
return {k * v.x, k * v.y};
}
};

struct Hail {
Vec p;
Vec v;

std::optional<Vec> Intersect(const Hail& o) const {
Frac delta = v.x * o.v.y - v.y * o.v.x;
long double delta = v.x * o.v.y - v.y * o.v.x;
if (delta == 0) {
return std::nullopt;
}
Frac a = o.v.y / delta * (o.p.x - p.x) - o.v.x / delta * (o.p.y - p.y);
Frac b = v.y / delta * (o.p.x - p.x) - v.x / delta * (o.p.y - p.y);
long double a =
o.v.y / delta * (o.p.x - p.x) - o.v.x / delta * (o.p.y - p.y);
long double b = v.y / delta * (o.p.x - p.x) - v.x / delta * (o.p.y - p.y);
if (a < 0.0 || b < 0.0) {
return std::nullopt;
}
Expand Down
35 changes: 11 additions & 24 deletions day-24/part-2/skasch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,23 @@
#include <unordered_map>
#include <unordered_set>

static constexpr std::int64_t kMaxVelocity = 1024;
static constexpr std::int64_t kMaxVelocity = 512;
static constexpr int kNHails = 300;
static std::unordered_map<int, std::vector<int>> kIndexesByVx;
static std::unordered_map<int, std::vector<int>> kIndexesByVy;
static std::unordered_map<int, std::vector<int>> kIndexesByVz;

__int128_t gcd(__int128_t a, __int128_t b) {
if (b < 0) b = -b;
if (a < 0) a = -a;
if (a < b) std::swap(a, b);
if (b == 0) return a;
__int128_t r;
while (a % b > 0) {
r = a % b;
a = b;
b = r;
}
return b;
}

struct Vec {
__int128_t x;
__int128_t y;
__int128_t z;
std::int64_t x;
std::int64_t y;
std::int64_t z;

Vec operator+(const Vec& o) const { return {x + o.x, y + o.y, z + o.z}; }
Vec operator-() const { return {-x, -y, -z}; }
Vec operator-(const Vec& o) const { return *this + (-o); }
Vec operator*(__int128_t k) const { return {k * x, k * y, k * z}; }
friend Vec operator*(__int128_t k, const Vec& v) { return v * k; }
__int128_t operator*(const Vec& o) const {
Vec operator*(std::int64_t k) const { return {k * x, k * y, k * z}; }
friend Vec operator*(std::int64_t k, const Vec& v) { return v * k; }
std::int64_t operator*(const Vec& o) const {
return x * o.x + y * o.y + z * o.z;
}
Vec operator^(const Vec& o) const {
Expand All @@ -52,9 +38,10 @@ struct Hail {
Vec v;
};

std::optional<__int128_t> solve(__int128_t x11, __int128_t x12, __int128_t x21,
__int128_t x22, __int128_t b1, __int128_t b2) {
__int128_t delta = x11 * x22 - x21 * x12;
std::optional<std::int64_t> solve(std::int64_t x11, std::int64_t x12,
std::int64_t x21, std::int64_t x22,
std::int64_t b1, std::int64_t b2) {
std::int64_t delta = x11 * x22 - x21 * x12;
if (delta == 0) return std::nullopt;
return (x22 * b1 - x12 * b2) / delta;
}
Expand Down

0 comments on commit e66660d

Please sign in to comment.