#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <vector>
#include <set>
#include <algorithm>
auto prime_table(size_t N) {
std::vector<bool> table(N + 1, true);
auto sqrt_N = static_cast<size_t>(floor(sqrt(N) + 1));
table[0] = false;
table[1] = false;
printf("generating primes...\n");
for (size_t p = 2; p < sqrt_N; p++) {
if (table[p]) {
for (size_t k = p; k * p < table.size(); k++) {
table[k * p] = false;
}
}
}
return table;
}
auto get_number(size_t x, size_t y, size_t N) {
auto X = ssize_t(x - (N - 1) / 2);
auto Y = ssize_t(y - N / 2);
auto mx = std::abs(X), my = std::abs(Y);
auto l = 2 * std::max(mx, my);
auto d = Y > X? l * 3 + X + Y: l - X - Y;
return static_cast<size_t>((l - 1) * (l - 1) + d);
}
auto ulam_spiral() {
auto N = 10;
auto M = size_t(1) << N;
auto&& is_prime = prime_table(1 << N * 2);
std::vector<std::vector<bool>> buffer(M, std::vector<bool>(M, false));
printf("mapping to ulam-spiral...\n");
for (size_t x = 0; x < M; x++) {
for (size_t y = 0; y < M; y++) {
auto v = get_number(x, y, M);
if (is_prime[v]) {
buffer[x][y] = true;
}
}
}
printf("washing...\n");
std::vector<std::pair<size_t, size_t>> buffer2 = {{0, 0}};
while (!buffer2.empty()) {
auto pair = buffer2.back();
buffer2.pop_back();
auto x = pair.first, y = pair.second;
if (!buffer[x][y]) {
buffer[x][y] = true;
if (x != 0 && !buffer[x - 1][y]) {
buffer2.push_back(std::make_pair(x - 1, y));
}
if (x != M - 1 && !buffer[x + 1][y]) {
buffer2.push_back(std::make_pair(x + 1, y));
}
if (y != 0 && !buffer[x][y - 1]) {
buffer2.push_back(std::make_pair(x, y - 1));
}
if (y != M - 1 && !buffer[x][y + 1]) {
buffer2.push_back(std::make_pair(x, y + 1));
}
}
}
printf("detecting...\n");
auto n = 0;
for (size_t x = 1; x < M - 1; x++) {
for (size_t y = 1; y < M - 1; y++) {
if (!buffer[x][y]) {
if (!buffer[x + 1][y] || !buffer[x - 1][y] || !buffer[x][y - 1] || !buffer[x][y + 1]) {
printf("detected![%d] x = %zu, y = %zu, n = %zu\n", n, x, y, get_number(x, y, N));
n++;
}
}
}
}
return buffer;
}
int main() {
auto&& table = ulam_spiral();
return 0;
}