This commit is contained in:
Maxime Vorwerk
2023-08-29 14:53:25 +02:00
parent 6ecf660cde
commit d836aa5c1a
9 changed files with 352 additions and 85 deletions

View File

@@ -1,6 +1,117 @@
include("Shape.jl")
include("ImmutableOrientedShape.jl")
include("Powerset.jl")
include("TupleMisc.jl")
include("plot.jl")
using XXhash
using Serialization
using DataStructures
using ArgParse
function main(i::Int64)
D = Dict{ImmutableOrientedShape}()
S = Stack{Int64}();
function main()
s = ArgParseSettings()
@add_arg_table s begin
"-g"
help = "generator"
arg_type = Int
"-l"
help = "list"
action = :store_true
"-p"
help = "plot n_cubes i_shape"
nargs = '+'
arg_type = Int
end
parsed_args = parse_args(s)
generate = get(parsed_args, "g", nothing)
if generate !== nothing && generate > 0
scanForShapes(generate)
end
if get(parsed_args, "l", false)
listShapes()
end
plot = get(parsed_args, "p", nothing)
if length(plot) == 1
plotShapes(plot)
elseif length(plot) == 2
plotShape(plot)
end
end
function scanForShapes(MaxSize::Int64)
D = Dict{UInt, ImmutableOrientedShape}()
S = Stack{Shape}();
cube = getCube()
immutableCube = getImmutableOrientedShape(cube)
D[immutableCube.hash] = immutableCube
push!(S, cube)
while !isempty(S)
cube = pop!(S)
growableSpaces = collect(getPossibleNeighbors(cube))
acceptable_growth = MaxSize - length(cube.cubes)
for i 1:acceptable_growth
possibleGrowth = Powerset.getPowerSubSet(length(growableSpaces), i)
for j axes(possibleGrowth, 1)
cubesToAdd = growableSpaces[possibleGrowth[j, :]]
newShape = deepcopy(cube)
for c cubesToAdd
push!(newShape, c)
end
collision = checkForCollision(newShape, D)
if !collision
push!(S, newShape)
immutableNewShape = getImmutableOrientedShape(newShape)
D[immutableNewShape.hash] = immutableNewShape
end
end
end
end
sanitizedData = sanitize(D, MaxSize)
serialize("results.bin", sanitizedData)
end
function listShapes()
T = deserialize("results.bin")
print("size: ")
println(T[1])
for V T[2]
for v V
println(v)
end
end
end
function checkForCollision(S::Shape, D::Dict{UInt, ImmutableOrientedShape})
for i 1:24
hash = hashList(S.orderedLists[i])
value = get(D, hash, nothing)
if value !== nothing && hash == value.hash
return true
end
end
return false
end
function hashList(L::Vector{Tuple{Int64, Int64, Int64}})
diffList = Vector{Tuple{Int64, Int64, Int64}}(undef, length(L)-1)
for i eachindex(diffList)
diffList[i] = L[i+1] - L[i]
end
return xxh3_64(diffList)
end
function sanitize(D::Dict{UInt, ImmutableOrientedShape}, size::Int64)
data = Vector{Vector{Vector{Tuple{Int64, Int64, Int64}}}}(undef, size)
for i eachindex(data)
data[i] = Vector{Vector{Tuple{Int64, Int64, Int64}}}(undef, 0)
end
for (K, V) D
push!(data[length(V.cubes)], V.cubes)
end
return (size, data)
end
main()

View File

@@ -1,11 +1,10 @@
include("Shape.jl")
using XXhash
struct ImmutableOrientedShape
cubes::Vector{Tuple{Int8, Int8, Int8}}
cubes::Vector{Tuple{Int64, Int64, Int64}}
hash::UInt
end
function getImmutableOrientedShape(S::Shape)
shape = ImmutableOrientedShape(S.orderedLists[1], xxh3_64(S.orderedLists[1]))
shape = ImmutableOrientedShape(S.orderedLists[1], hashList(S.orderedLists[1]))
end

134
julia/Plot.jl Normal file
View File

@@ -0,0 +1,134 @@
using PyCall
using Serialization
py"""
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def plotShapePY(v):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plotSingleShape(ax, v)
plt.show()
def plotShapesPY(vs):
n = len(vs)
if n == 1:
plotShapePY(vs[0])
else:
fig = plt.figure()
print(n)
n_rows = int(np.ceil(0.6*n))
n_cols = int(np.ceil(n/n_rows))
print(n_rows)
print(n_cols)
for i in range(len(vs)):
v = vs[i]
ax = fig.add_subplot(n_cols, n_rows, i+1, projection='3d')
plotSingleShape(ax, v)
plt.show()
def plotSingleShape(ax, v):
l = len(v)
for i in range(l):
X1, Y1, Z1 = horizontalPlane(v[i][0] , v[i][1] , v[i][2] )
X2, Y2, Z2 = horizontalPlane(v[i][0] , v[i][1] , v[i][2]+1)
X3, Y3, Z3 = verticalPlaneX( v[i][0] , v[i][1] , v[i][2] )
X4, Y4, Z4 = verticalPlaneX( v[i][0] , v[i][1]+1, v[i][2] )
X5, Y5, Z5 = verticalPlaneY( v[i][0] , v[i][1] , v[i][2] )
X6, Y6, Z6 = verticalPlaneY( v[i][0]+1, v[i][1] , v[i][2] )
ax.plot_surface(X1, Y1, Z1, alpha=0.8, color='orange')
ax.plot_surface(X2, Y2, Z2, alpha=0.8, color='orange')
ax.plot_surface(X3, Y3, Z3, alpha=0.8, color='green' )
ax.plot_surface(X4, Y4, Z4, alpha=0.8, color='green' )
ax.plot_surface(X5, Y5, Z5, alpha=0.8, color='cyan' )
ax.plot_surface(X6, Y6, Z6, alpha=0.8, color='cyan' )
x_min = np.inf
x_max = -np.inf
y_min = np.inf
y_max = -np.inf
z_min = np.inf
z_max = -np.inf
for i in range(l):
x_min = np.min([x_min, v[i][0]])
x_max = np.max([x_max, v[i][0]])
y_min = np.min([y_min, v[i][1]])
y_max = np.max([y_max, v[i][1]])
z_min = np.min([z_min, v[i][2]])
z_max = np.max([z_max, v[i][2]])
biggest_length = max([x_max-x_min, y_max-y_min, z_max-z_min])
x_diff = (biggest_length - (x_max - x_min)) / 2
x_lim_min = x_min - x_diff
x_lim_max = x_max + x_diff
y_diff = (biggest_length - (y_max - y_min)) / 2
y_lim_min = y_min - y_diff
y_lim_max = y_max + y_diff
z_diff = (biggest_length - (z_max - z_min)) / 2
z_lim_min = z_min - z_diff
z_lim_max = z_max + z_diff
ax.scatter([x_lim_min, x_lim_max+1], [y_lim_min, y_lim_max+1], [z_lim_min, z_lim_max+1], alpha=0)
def getPoints(a):
x = a[0]
y = a[1]
z = a[2]
p = [
[x, y, z ],
[x+1, y, z ],
[x+1, y+1, z ],
[x, y+1, z ],
[x, y, z+1],
[x+1, y, z+1],
[x+1, y+1, z+1],
[x, y+1, z+1]
]
return p
def horizontalPlane(x, y, z):
one = np.ones(4).reshape(2, 2)
r1 = [x, x + 1]
r2 = [y, y + 1]
X, Y = np.meshgrid(r1, r2)
Z = one*z
return X, Y, Z
def verticalPlaneX(x, y, z):
one = np.ones(4).reshape(2, 2)
r1 = [x, x + 1]
r2 = [z, z + 1]
X, Z = np.meshgrid(r1, r2)
Y = one*y
return X, Y, Z
def verticalPlaneY(x, y, z):
one = np.ones(4).reshape(2, 2)
r1 = [y, y + 1]
r2 = [z, z + 1]
Y, Z = np.meshgrid(r1, r2)
X = one*x
return X, Y, Z
"""
function plotShape(t::Vector{Int64})
T = deserialize("results.bin")
v = T[2][t[1]][t[2]]
py"plotShapePY"(v)
end
function plotShapes(t::Vector{Int64})
T = deserialize("results.bin")
v = T[2][t[1]]
py"plotShapesPY"(v)
end

View File

@@ -4,6 +4,8 @@ global _calculatedPowerSets = Matrix{Int64}(undef, 1, 0)
global _grownUntil = 0
function getPowerSet(setSize::Integer)
global _calculatedPowerSets
global _grownUntil
wantedPowerSetSize = 2^setSize
if setSize <= _grownUntil
return _calculatedPowerSets[1:wantedPowerSetSize, 1:setSize]
@@ -29,13 +31,19 @@ end
function getPowerSubSet(setSize::Integer, subSetSize::Integer)
PowerSet = getPowerSet(setSize)
setSizes = dropdim(sum(Powerset, dims = 2), dims = 2)
setSizes = dropdims(sum(PowerSet, dims = 2), dims = 2)
powerSubSetSize = binomial(setSize, subSetSize)
powerSubSets = Matrix{Int64}(undef, powerSubSetSize, setSize)
powerSubSets = Matrix{Int64}(undef, powerSubSetSize, subSetSize)
j = 1
for i 1:setSize
for i axes(PowerSet, 1)
if setSizes[i] == subSetSize
powerSubSets[j, :] = PowerSet[i, :]
l = 1
for k axes(PowerSet, 2)
if PowerSet[i, k] == 1
powerSubSets[j, l] = k
l += 1
end
end
j += 1
end
end

59
julia/Rotations.jl Normal file
View File

@@ -0,0 +1,59 @@
const global _rot01(x) = (x[1], x[2], x[3])
const global _rot02(x) = (x[2], x[3], x[1])
const global _rot03(x) = (x[3], x[1], x[2])
const global _rot04(x) = (x[1], x[2], -x[3])
const global _rot05(x) = (x[2], x[3], -x[1])
const global _rot06(x) = (x[3], x[1], -x[2])
const global _rot07(x) = (x[1], -x[2], x[3])
const global _rot08(x) = (x[2], -x[3], x[1])
const global _rot09(x) = (x[3], -x[1], x[2])
const global _rot10(x) = (x[1], -x[2], -x[3])
const global _rot11(x) = (x[2], -x[3], -x[1])
const global _rot12(x) = (x[3], -x[1], -x[2])
const global _rot13(x) = (-x[1], x[2], x[3])
const global _rot14(x) = (-x[2], x[3], x[1])
const global _rot15(x) = (-x[3], x[1], x[2])
const global _rot16(x) = (-x[1], x[2], -x[3])
const global _rot17(x) = (-x[2], x[3], -x[1])
const global _rot18(x) = (-x[3], x[1], -x[2])
const global _rot19(x) = (-x[1], -x[2], x[3])
const global _rot20(x) = (-x[2], -x[3], x[1])
const global _rot21(x) = (-x[3], -x[1], x[2])
const global _rot22(x) = (-x[1], -x[2], -x[3])
const global _rot23(x) = (-x[2], -x[3], -x[1])
const global _rot24(x) = (-x[3], -x[1], -x[2])
const global Rotations = [
_rot01,
_rot02,
_rot03,
_rot04,
_rot05,
_rot06,
_rot07,
_rot08,
_rot09,
_rot10,
_rot11,
_rot12,
_rot13,
_rot14,
_rot15,
_rot16,
_rot17,
_rot18,
_rot19,
_rot20,
_rot21,
_rot22,
_rot23,
_rot24
]

View File

@@ -1,28 +1,40 @@
include("SortingModifiers.jl")
include("Rotations.jl")
struct Shape
cubes::Set{Tuple{Int8, Int8, Int8}}
recentCubes::Set{Tuple{Int8, Int8, Int8}}
orderedLists::Vector{Vector{Tuple{Int8, Int8, Int8}}}
cubes::Set{Tuple{Int64, Int64, Int64}}
recentCubes::Set{Tuple{Int64, Int64, Int64}}
orderedLists::Vector{Vector{Tuple{Int64, Int64, Int64}}}
end
function trypush!(S::Shape, t::Tuple{Int8, Int8, Int8})
if t S.cubes
return false
else
function Base.:push!(S::Shape, t::Tuple{Int64, Int64, Int64})
push!(S.cubes, t)
for i 1:24
index = searchsortedfirst(S.orderedLists[i], t, by=SortingModifiers[i])
insert!(S.orderedLists, index, t)
t_rot = Rotations[i](t)
index = searchsortedfirst(S.orderedLists[i], t_rot)
insert!(S.orderedLists[i], index, t_rot)
end
return true
end
function getPossibleNeighbors(S::Shape)
possibleSpots = Set{Tuple{Int64, Int64, Int64}}()
for p S.cubes
push!(possibleSpots,
p + (1, 0, 0),
p + (0, 1, 0),
p + (0, 0, 1),
p - (1, 0, 0),
p - (0, 1, 0),
p - (0, 0, 1)
)
end
spots = setdiff(possibleSpots, S.cubes)
return spots
end
function getCube()
return Shape(
{(0, 0, 0)},
{(0, 0, 0)},
Set([(0, 0, 0)]),
Set([(0, 0, 0)]),
[
[(0, 0, 0)],
[(0, 0, 0)],

View File

@@ -1,59 +0,0 @@
const global _comp01(x) = (x[1], x[2], x[3])
const global _comp02(x) = (x[2], x[3], x[1])
const global _comp03(x) = (x[3], x[1], x[2])
const global _comp04(x) = (x[1], x[2], -x[3])
const global _comp05(x) = (x[2], x[3], -x[1])
const global _comp06(x) = (x[3], x[1], -x[2])
const global _comp07(x) = (x[1], -x[2], x[3])
const global _comp08(x) = (x[2], -x[3], x[1])
const global _comp09(x) = (x[3], -x[1], x[2])
const global _comp10(x) = (x[1], -x[2], -x[3])
const global _comp11(x) = (x[2], -x[3], -x[1])
const global _comp12(x) = (x[3], -x[1], -x[2])
const global _comp13(x) = (-x[1], x[2], x[3])
const global _comp14(x) = (-x[2], x[3], x[1])
const global _comp15(x) = (-x[3], x[1], x[2])
const global _comp16(x) = (-x[1], x[2], -x[3])
const global _comp17(x) = (-x[2], x[3], -x[1])
const global _comp18(x) = (-x[3], x[1], -x[2])
const global _comp19(x) = (-x[1], -x[2], x[3])
const global _comp20(x) = (-x[2], -x[3], x[1])
const global _comp21(x) = (-x[3], -x[1], x[2])
const global _comp22(x) = (-x[1], -x[2], -x[3])
const global _comp23(x) = (-x[2], -x[3], -x[1])
const global _comp24(x) = (-x[3], -x[1], -x[2])
const global SortingModifiers = [
_comp01,
_comp02,
_comp03,
_comp04,
_comp05,
_comp06,
_comp07,
_comp08,
_comp09,
_comp10,
_comp11,
_comp12,
_comp13,
_comp14,
_comp15,
_comp16,
_comp17,
_comp18,
_comp19,
_comp20,
_comp21,
_comp22,
_comp23,
_comp24
]

3
julia/TupleMisc.jl Normal file
View File

@@ -0,0 +1,3 @@
Base.:+(X::Tuple{Integer, Integer, Integer}, Y::Tuple{Integer, Integer, Integer}) = (X[1]+Y[1], X[2]+Y[2], X[3]+Y[3])
Base.:-(X::Tuple{Integer, Integer, Integer}, Y::Tuple{Integer, Integer, Integer}) = (X[1]-Y[1], X[2]-Y[2], X[3]-Y[3])

BIN
julia/results.bin Normal file

Binary file not shown.