218 lines
6.1 KiB
Zig
218 lines
6.1 KiB
Zig
const std = @import("std");
|
|
|
|
const stdout = std.io.getStdOut().writer();
|
|
|
|
fn print(comptime str: []const u8, args: anytype) void {
|
|
stdout.print(str, args) catch unreachable;
|
|
}
|
|
|
|
fn println(comptime str: []const u8, args: anytype) void {
|
|
print(str ++ "\n", args);
|
|
}
|
|
|
|
//const n: u512 = 7405872386298001828045412304885395957447735855540402226273272018863616985100578690399814241980651881616439657049448993379923363875365701026162288146836853;
|
|
|
|
const n: u512 = 70666344586694209770041979947;
|
|
|
|
var sqrt: u512 = undefined;
|
|
|
|
const Pack = struct {
|
|
const Self = @This();
|
|
|
|
alloc: std.mem.Allocator,
|
|
n1: u512,
|
|
n2: u512,
|
|
|
|
fn init(alloc: std.mem.Allocator, n1: u512, n2: u512) !*Self {
|
|
const self = try alloc.create(Self);
|
|
self.n1 = n1;
|
|
self.n2 = n2;
|
|
self.alloc = alloc;
|
|
return self;
|
|
}
|
|
|
|
fn same(self: *Self, other: *Self) bool {
|
|
return (self.n1 == other.n1 and self.n2 == other.n2) or (self.n1 == other.n2 and self.n2 == other.n1);
|
|
}
|
|
fn sameNumbers(self: *Self, n1: u512, n2: u512) bool {
|
|
return (self.n1 == n1 and self.n2 == n2);
|
|
}
|
|
|
|
fn print(self: *Self) void {
|
|
println("{} {}", .{ self.n1, self.n2 });
|
|
}
|
|
|
|
fn deinit(self: *Self) void {
|
|
self.alloc.destroy(self);
|
|
}
|
|
};
|
|
|
|
const PackList = std.ArrayList(*Pack);
|
|
|
|
fn addPackNumbers(self: *PackList, n1: u512, n2: u512) !void {
|
|
for (self.items, 0..) |item, j| {
|
|
var i = item;
|
|
if (n1 == i.n1) {
|
|
if (n2 == i.n2) {
|
|
return;
|
|
} else if (n2 > i.n2) {
|
|
var pack = try Pack.init(self.allocator, n1, n2);
|
|
try self.insert(j + 1, pack);
|
|
}
|
|
}
|
|
if (n1 < i.n1) {
|
|
var pack = try Pack.init(self.allocator, n1, n2);
|
|
try self.insert(j, pack);
|
|
return;
|
|
}
|
|
}
|
|
var pack = try Pack.init(self.allocator, n1, n2);
|
|
try self.append(pack);
|
|
}
|
|
|
|
fn base3Mask(val: u512, size: usize) u512 {
|
|
return val % std.math.pow(u512, 10, size);
|
|
}
|
|
|
|
var nBase: u512 = undefined;
|
|
|
|
pub fn main() !void {
|
|
var alloctor = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
|
defer alloctor.deinit();
|
|
|
|
var alloc = alloctor.allocator();
|
|
|
|
sqrt = std.math.sqrt(n);
|
|
|
|
nBase = base3Mask(n, 1);
|
|
println("BaseMask {}", .{nBase});
|
|
var items = try searchAcc(alloc, 1);
|
|
|
|
var toRemove = std.ArrayList(usize).init(alloc);
|
|
defer toRemove.deinit();
|
|
|
|
var cpuCount = try std.Thread.getCpuCount();
|
|
var threads = try alloc.alloc(std.Thread, cpuCount);
|
|
defer alloc.free(threads);
|
|
var results = try alloc.alloc(PackList, cpuCount);
|
|
defer alloc.free(results);
|
|
|
|
for (2..512) |acc| {
|
|
nBase = base3Mask(n, acc);
|
|
toRemove.clearRetainingCapacity();
|
|
|
|
println("Stared threaded work on {}", .{acc});
|
|
for (0..cpuCount) |id| {
|
|
threads[id] = try std.Thread.spawn(.{
|
|
.stack_size = 1024 * 1024 * 1024,
|
|
.allocator = alloc,
|
|
}, threadSearch, .{ items, id, cpuCount, acc, results });
|
|
}
|
|
|
|
for (0..cpuCount) |id| {
|
|
threads[id].join();
|
|
}
|
|
var total: u64 = 0;
|
|
for (results) |result| {
|
|
total += result.items.len;
|
|
}
|
|
println("Finish threaded work on {} total {}", .{ acc, total });
|
|
|
|
for (items.items) |item| {
|
|
item.deinit();
|
|
}
|
|
|
|
items.clearRetainingCapacity();
|
|
|
|
for (results) |result| {
|
|
//for (result.items) |toAdd| {
|
|
//try addPack(&newToAdd, toAdd);
|
|
//}
|
|
try items.appendSlice(result.items);
|
|
result.deinit();
|
|
}
|
|
|
|
// println("results for {}", .{acc});
|
|
// for (items.items) |item| {
|
|
// item.print();
|
|
// }
|
|
if (acc == 10) {
|
|
println("For items: {}", .{items.items.len});
|
|
for (items.items) |item| {
|
|
item.print();
|
|
}
|
|
break;
|
|
} else {
|
|
println("For finished {}; items: {}", .{ acc, items.items.len });
|
|
}
|
|
}
|
|
}
|
|
|
|
fn threadSearch(items: PackList, id: usize, threadCount: usize, acc: u64, results: []PackList) !void {
|
|
const max = @max(items.items.len / threadCount, 1);
|
|
//var returned = PackList.init(items.allocator);
|
|
var returned = PackList.init(std.heap.page_allocator);
|
|
const len = items.items.len;
|
|
for (0..max) |_i| {
|
|
var i = id + _i * threadCount;
|
|
if (i >= len) {
|
|
break;
|
|
}
|
|
var item = items.items[i];
|
|
if (!verifyAccuracy(item, acc)) {
|
|
//println("{} {} does not hold for acc {}", .{ item.n1, item.n2, acc });
|
|
try searchPackAcc(&returned, acc, item);
|
|
} else {
|
|
try addPackNumbers(&returned, @min(item.n1, item.n2), @max(item.n1, item.n2));
|
|
}
|
|
}
|
|
results[id] = returned;
|
|
return;
|
|
}
|
|
|
|
fn searchPackAcc(packList: *PackList, acc: u64, pack: *Pack) !void {
|
|
var size_n1: u512 = std.math.pow(u512, 10, std.math.log10_int(pack.n1) + 1);
|
|
var size_n2: u512 = std.math.pow(u512, 10, std.math.log10_int(pack.n2) + 1);
|
|
|
|
for (0..10) |_i| {
|
|
var i = _i * size_n1 + pack.n1;
|
|
for (0..10) |_j| {
|
|
var j = _j * size_n2 + pack.n2;
|
|
var mul: u512 = i * j;
|
|
if (mul == n) {
|
|
println("Found them {} {}!", .{ j, i });
|
|
std.os.exit(1);
|
|
}
|
|
if (mul > n) break;
|
|
var mulMask = base3Mask(mul, acc);
|
|
|
|
if (mulMask == nBase) {
|
|
try addPackNumbers(packList, @min(i, j), @max(i, j));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn searchAcc(alloc: std.mem.Allocator, acc: u64) !PackList {
|
|
var packList = PackList.init(alloc);
|
|
|
|
for (0..10) |i| {
|
|
for (0..10) |j| {
|
|
var mul: u512 = i * j;
|
|
if (mul > n) break;
|
|
var mulMask = base3Mask(mul, acc);
|
|
|
|
if (mulMask == nBase) {
|
|
try addPackNumbers(&packList, @min(i, j), @max(i, j));
|
|
}
|
|
}
|
|
}
|
|
|
|
return packList;
|
|
}
|
|
|
|
fn verifyAccuracy(pack: *Pack, acc: u64) bool {
|
|
var mulMask = base3Mask(pack.n1 * pack.n2, acc);
|
|
return mulMask == nBase;
|
|
}
|