diff --git a/julia/PolyCube.jl b/julia/PolyCube.jl new file mode 100644 index 0000000..b45c925 --- /dev/null +++ b/julia/PolyCube.jl @@ -0,0 +1,53 @@ +include("tuple_tools.jl") + +import Combinatorics: powerset + +Coord = Tuple{Number, Number, Number} + +struct PolyCube + cubes::Vector{Coord} + oriented_difference::Vector{Vector{Coord}} + last_added::Vector{Coord} +end + +function PolyCube(cubes::Vector{Coord}, last_added::Vector{Coord}) + return PolyCube(sort!(cubes), _calculate_oriented_differences(cubes), last_added) +end + +# possible improvement: since reorientation[1] == cubes, skip the insertion sterp, and benefit from having cubes sorted. +# then skip sorting in constructor + +function _calculate_oriented_differences(cubes::Vector{Coord}) + n_orientations = 24 + n_cubes = length(cubes) + reorientation = Vector{Coord}(undef, n_cubes) + oriented_differences = Vector{Vector{Coord}}(undef, n_orientations) + for i ∈ 1:n_orientations + for j ∈ 1:n_cubes + reorientation[j] = orient_tuple(cubes[j], i) + end + sort!(reorientation) + reference_cube = reorientation[1] + oriented_differences[i] = Vector{Coord}(undef, n_cubes-1) + for j ∈ 1:n_cubes-1 + oriented_differences[j] = reference_cube - reorientation[j+1] + end + end + return oriented_differences +end + +function generate_children(pcube::PolyCube, n_max::Int) + cubes = pcube.cubes + allowed_growth = n_max - length(cubes) + growth_candidates = Vector{Coord}(undef, 0) + for root_cube ∈ pcube.last_added + for neighbor ∈ neighbors(root_cube...) + pos_growth_candidates = searchsortedfirst(growth_candidates, neighbor) + # consider flipping following ||, it MAY imrove performance + if growth_candidates[pos_growth_candidates] != neighbor || !isempty(searchsorted(cubes, neighbor)) + insert!(growth_candidates, pos_growth_candidates, neighbor) + end + end + end + return Iterators.map(x -> PolyCube(vcat(cubes, x), x), powerset(growth_candidates, 1, allowed_growth)) +end diff --git a/julia/main.jl b/julia/main.jl index e69de29..1108362 100644 --- a/julia/main.jl +++ b/julia/main.jl @@ -0,0 +1,6 @@ + +function main(maxsize::int): + +end + +main(7) diff --git a/julia/tuple_tools.jl b/julia/tuple_tools.jl new file mode 100644 index 0000000..ce12d18 --- /dev/null +++ b/julia/tuple_tools.jl @@ -0,0 +1,47 @@ +Coord = Tuple{Number,Number,Number} + +function Base.:-(u::Coord, v::Coord) + return (u[1] - v[1], u[2] - v[2], u[3] - v[3]) +end + +function neighbors(x::Int, y::Int, z::Int) + return [ + (x+1, y, z), + (x-1, y, z), + (x, y+1, z), + (x, y-1, z), + (x, y, z+1), + (x, y, z-1) + ] +end + +function orient_tuple(t::Coord, o::Int) + return _shift_tuple(_flip_tuple(_mirror_tuple(t..., o-1)...)...) +end + +function _shift_tuple(t::Coord, o::Int) + funcs = [ + (x, y, z) -> (x, y, z), + (x, y, z) -> (y, z, x), + (x, y, z) -> (z, x, y), + ] + return (funcs[o%3+1](t...), div(o, 3)) +end + +function _flip_tuple(t::Coord, o::Int) + funcs = [ + (x, y, z) -> (x, y, z), + (x, y, z) -> (-x, -y, z), + (x, y, z) -> (-x, y, -z), + (x, y, z) -> (x, -y, -z) + ] + return (funcs[o%4+1](t...), div(o, 4)) +end + +function _mirror_tuple(t::Coord, o::Int) + funcs = [ + (x, y, z) -> (x, y, z), + (x, y, z) -> (-z, -x, -y) + ] + return (funcs[o%2+1](t...), div(o, 2)) +end