diff --git a/2019-10-18-maze/maze.cc b/2019-10-18-maze/maze.cc new file mode 100644 index 0000000..ef7181f --- /dev/null +++ b/2019-10-18-maze/maze.cc @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include + +constexpr const size_t SIZE = 10; +std::array, SIZE> maze = {std::array{6, 2, 1, 3, 6, 1, 7, 7, 4, 3}, + std::array{2, 3, 4, 5, 7, 8, 1, 5, 2, 3}, + std::array{1, 6, 1, 2, 5, 1, 6, 3, 6, 2}, + std::array{5, 3, 5, 5, 1, 6, 7, 3, 7, 3}, + std::array{1, 2, 6, 4, 1, 3, 3, 5, 5, 5}, + std::array{2, 4, 6, 6, 6, 2, 1, 3, 8, 8}, + std::array{2, 4, 0, 2, 3, 6, 5, 2, 4, 6}, + std::array{3, 1, 7, 6, 2, 3, 1, 5, 7, 7}, + std::array{6, 1, 3, 6, 4, 5, 4, 2, 2, 7}, + std::array{6, 7, 5, 7, 6, 2, 4, 1, 9, 1}}; + +struct P { + int i; + int j; + + bool operator==(const auto& rhs) const { + return i == rhs.i && j == rhs.j; + } + + friend std::ostream& operator<<(std::ostream& stream, const auto& p) { + stream << p.i << " " << p.j; + return stream; + } +}; + +std::vector

s(const P& p) { + std::vector

results; + for (int jprime = 0; jprime < SIZE; jprime++) { + if (jprime == p.j) continue; + + if (maze[p.i][jprime] == std::abs(jprime - p.j)) { + results.push_back({p.i, jprime}); + } + } + + for (int iprime = 0; iprime < SIZE; iprime++) { + if (iprime == p.i) continue; + + if (maze[iprime][p.j] == std::abs(iprime - p.i)) { + results.push_back({iprime, p.j}); + } + } + + return results; +} + +void print_path(const auto& backp) { + P curr {SIZE - 1, 0}; + while (maze[curr.i][curr.j] != 0) { + std::cout << curr << std::endl; + curr = backp[curr.i][curr.j]; + } + std::cout << curr << std::endl; +} + +int main() { + std::array, SIZE> closed; + for (size_t i = 0; i < SIZE; i++) { + for (size_t j = 0; j < SIZE; j++) { + closed[i][j] = false; + } + } + + std::array, SIZE> backp; + for (size_t i = 0; i < SIZE; i++) { + for (size_t j = 0; j < SIZE; j++) { + backp[i][j] = {-1, -1}; + } + } + + std::deque

open; + open.push_back({6, 2}); + + if (maze[open.front().i][open.front().j] != 0) { + throw std::runtime_error("Wrong start"); + } + + while (!open.empty()) { + const auto p = open.front(); + open.pop_front(); + + if (p == P{SIZE - 1, 0}) { + print_path(backp); + return 0; + } + + for (const auto& pprime : s(p)) { + if (!closed[pprime.i][pprime.j]) { + open.push_back(pprime); + backp[pprime.i][pprime.j] = p; + } + closed[pprime.i][pprime.j] = true; + } + } + + return 1; +} diff --git a/2019-12-06-song-shuffle/value-iteration.py b/2019-12-06-song-shuffle/value-iteration.py new file mode 100755 index 0000000..04b48fc --- /dev/null +++ b/2019-12-06-song-shuffle/value-iteration.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import decimal +import math +import numpy as np + +def k(N): + bellman_eps = 1e-10 + V = np.arange(N, dtype=decimal.Decimal) + while True: + + new_V = decimal.Decimal(1) + np.minimum(np.roll(V, 1), sum(V, decimal.Decimal(0)) / decimal.Decimal(N)) + new_V[0] = decimal.Decimal(0) + if np.all(np.abs(V - new_V) < bellman_eps): + break + V = new_V + for i in range(N): + if V[i] < i: + return V, i - 1 + +def vtwiddle(N, k): + return N/(k+1) + k/2 + +def argmin_vtwiddle(N): + k = (2*N)**0.5 - 1 + k1 = math.floor(k) + k2 = math.ceil(k) + return k1 if vtwiddle(N, k1) < vtwiddle(N, k2) else k2 + + +for N in range(1, 101): + vi_k = k(N) + analytic_k = argmin_vtwiddle(N) + print(N, vi_k, analytic_k, vi_k == analytic_k) + +print('Answer:', argmin_vtwiddle(100)) +print('Average presses:', np.mean(k(100)[0])) diff --git a/2020-01-24-pennies/pennies.py b/2020-01-24-pennies/pennies.py new file mode 100755 index 0000000..8a50f59 --- /dev/null +++ b/2020-01-24-pennies/pennies.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +import functools + +@functools.lru_cache(maxsize=100000) +def win(x, y): + if x == 0: + return True + if y == 0: + return True + if x == y: + return True + + for i in range(1, max(x, y) + 1): + if i <= x: + if win(x - i, y) is False: + return True + if i <= y: + if win(x - i, y - i) is False: + return True + if i <= y: + if win(x, y - i) is False: + return True + return False + +PRINT_ALL = False + +for n in range(20, 31): + for x in range(0, n + 1): + y = n - x + + i_win = not win(x, y) + + if PRINT_ALL: + print(x, y, win(x, y)) + else: + if i_win: + print(x, y) diff --git a/2020-01-31-pyramids/pyramid.py b/2020-01-31-pyramids/pyramid.py new file mode 100644 index 0000000..0c386b8 --- /dev/null +++ b/2020-01-31-pyramids/pyramid.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 + +import math +import numpy as np + +''' +n is number of sides + +a is triangle base, b is triangle height +h is pyramid height +d is distance from midpoint of triangle base to center of pyramid base + +Volume of the pyramid is nadh/6 +d = a / (2 tan (pi/n)) +h^2 = b^2 - d^2 +''' + +def V(n, a, b): + d = a / 2 / math.tan(math.pi / n) + h_squared = b**2 - d**2 + if h_squared <= 0: + return math.nan + h = math.sqrt(b**2 - d**2) + return n * a * d * h / 6 + +def sweep(a, b): + n = 3 + v = [] + while True: + v_n = V(n, a, b) + if math.isnan(v_n): + break + v.append(v_n) + n += 1 + n_opt = np.argmax(v) + 3 + v_opt = np.max(v) + return n_opt, v_opt + +def example_triangle(): + a = 1 + b = a / 2 / math.tan(30 / 2 * math.pi / 180) + return a, b + +print(sweep(*example_triangle()))