176 lines
4.4 KiB
Zig
176 lines
4.4 KiB
Zig
|
const std = @import("std");
|
||
|
|
||
|
const stdout = std.io.getStdOut().writer();
|
||
|
|
||
|
fn println(comptime str: []const u8, args: anytype) void {
|
||
|
print(str ++ "\n", args);
|
||
|
}
|
||
|
|
||
|
fn print(comptime str: []const u8, args: anytype) void {
|
||
|
stdout.print(str, args) catch {};
|
||
|
}
|
||
|
|
||
|
fn parse(comptime str: []const u8) [10]u8 {
|
||
|
var new = std.mem.zeroes([10]u8);
|
||
|
for (0..10) |i| {
|
||
|
new[i] = str[i] - 65;
|
||
|
}
|
||
|
return new;
|
||
|
}
|
||
|
|
||
|
var p1 = parse("VRDTOUAPZX");
|
||
|
var p2 = parse("JSXCKEAGDE");
|
||
|
|
||
|
var count: u64 = 0;
|
||
|
|
||
|
const ArrayListU8 = std.ArrayList(u8);
|
||
|
|
||
|
const Node = struct {
|
||
|
value: u8,
|
||
|
depth: u8,
|
||
|
tree: *Tree,
|
||
|
};
|
||
|
|
||
|
const Tree = struct {
|
||
|
alloc: std.mem.Allocator,
|
||
|
nodes: std.AutoHashMap(u8, *Node),
|
||
|
|
||
|
const Self = @This();
|
||
|
|
||
|
fn init(alloc: std.mem.Allocator) !*Self {
|
||
|
var new = try alloc.create(Tree);
|
||
|
new.alloc = alloc;
|
||
|
new.nodes = std.AutoHashMap(u8, *Node).init(alloc);
|
||
|
return new;
|
||
|
}
|
||
|
|
||
|
fn add_word(self: *Self, word: []const u8) !void {
|
||
|
var tree_ptr: *Self = self;
|
||
|
var depth: u8 = 0;
|
||
|
for (word) |cu| {
|
||
|
const c = cu - 65;
|
||
|
if (tree_ptr.*.nodes.get(c)) |node| {
|
||
|
tree_ptr = node.tree;
|
||
|
} else {
|
||
|
var new_node = try self.alloc.create(Node);
|
||
|
new_node.value = c;
|
||
|
new_node.depth = depth;
|
||
|
new_node.tree = try Self.init(self.alloc);
|
||
|
try tree_ptr.*.nodes.put(c, new_node);
|
||
|
tree_ptr = new_node.tree;
|
||
|
}
|
||
|
depth += 1;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
pub fn main() !void {
|
||
|
var allocator = std.heap.GeneralPurposeAllocator(.{}){};
|
||
|
var alloc = allocator.allocator();
|
||
|
|
||
|
const args = try std.process.argsAlloc(alloc);
|
||
|
|
||
|
if (args.len == 3) {
|
||
|
if (args[1].len != 10 and args[2].len != 10) {
|
||
|
println("Invalid args", .{});
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
println("Using c1={s} c2={s}", .{ args[1], args[2] });
|
||
|
|
||
|
for (0..10) |i| {
|
||
|
p1[i] = args[1][i] - 65;
|
||
|
p2[i] = args[2][i] - 65;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var words = @embedFile("./10letterwordslist.txt");
|
||
|
|
||
|
var root = try Tree.init(alloc);
|
||
|
|
||
|
var split = std.mem.split(u8, words, "\r\n");
|
||
|
|
||
|
while (split.next()) |item| {
|
||
|
if (item.len == 10) {
|
||
|
try root.add_word(item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var sr = try search3(0, root, root);
|
||
|
|
||
|
if (sr.items.len == 0) {
|
||
|
println("No results found \n", .{});
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
println("items: {}", .{sr.items.len});
|
||
|
|
||
|
var r = sr.items[0];
|
||
|
|
||
|
var r1 = [10]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||
|
var r2 = [10]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||
|
|
||
|
for (p1, p2, r, 0..) |p_1, p_2, k, i| {
|
||
|
r1[i] = ((p_1 + (26 - k)) % 26) + 65;
|
||
|
r2[i] = ((p_2 + (26 - k)) % 26) + 65;
|
||
|
r[i] = k + 65;
|
||
|
}
|
||
|
|
||
|
println("k: {s}", .{r});
|
||
|
println("r1: {s}", .{r1});
|
||
|
println("r2: {s}", .{r2});
|
||
|
println("Checked: {}", .{count});
|
||
|
}
|
||
|
|
||
|
fn search3(depth: u8, tree1: *Tree, tree2: *Tree) !std.ArrayList([]u8) {
|
||
|
var list = std.ArrayList([]u8).init(tree1.alloc);
|
||
|
for (0..26) |validChari| {
|
||
|
var validChar: u8 = @intCast(validChari);
|
||
|
count += 1;
|
||
|
var inv = 26 - validChar;
|
||
|
var v1 = (p1[depth] + inv) % 26;
|
||
|
var v2 = (p2[depth] + inv) % 26;
|
||
|
var new_tree1 = tree1.nodes.get(v1);
|
||
|
var new_tree2 = tree2.nodes.get(v2);
|
||
|
if (new_tree1 == null or new_tree2 == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
var sr = try search2(depth + 1, new_tree1.?.tree, new_tree2.?.tree);
|
||
|
if (sr == null) {
|
||
|
continue;
|
||
|
}
|
||
|
var r = sr.?;
|
||
|
r[depth] = validChar;
|
||
|
try list.append(r);
|
||
|
}
|
||
|
return list;
|
||
|
}
|
||
|
|
||
|
fn search2(depth: u8, tree1: *Tree, tree2: *Tree) !?[]u8 {
|
||
|
if (depth == 10) {
|
||
|
return try tree1.alloc.alloc(u8, 10);
|
||
|
}
|
||
|
for (0..26) |validChari| {
|
||
|
var validChar: u8 = @intCast(validChari);
|
||
|
count += 1;
|
||
|
var inv = 26 - validChar;
|
||
|
var v1 = (p1[depth] + inv) % 26;
|
||
|
var v2 = (p2[depth] + inv) % 26;
|
||
|
var new_tree1 = tree1.nodes.get(v1);
|
||
|
var new_tree2 = tree2.nodes.get(v2);
|
||
|
if (new_tree1 == null or new_tree2 == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
var sr = try search2(depth + 1, new_tree1.?.tree, new_tree2.?.tree);
|
||
|
if (sr == null) {
|
||
|
continue;
|
||
|
}
|
||
|
var r = sr.?;
|
||
|
r[depth] = validChar;
|
||
|
return r;
|
||
|
}
|
||
|
return null;
|
||
|
}
|