This commit is contained in:
Maxime Vorwerk
2023-07-19 19:37:50 +02:00
parent c5bf09836f
commit 6657154f41
4 changed files with 107 additions and 168 deletions

56
.cs
View File

@@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
public class Shape {
private int _x;
private int _y;
private int _z;
private SortedDictionary<(int, int, int), int>[] _data;
public bool this[int x, int y, int z] {;
get {
if (x < _x && y < _y && z < _z && x >= 0 && y >= 0 && z >= 0) {
return _data[(x, y, z)];
}
else
throw new IndexOutOfRangeException();
}
}
private Shape(int x, int y, int z) {
_x = x;
_y = y;
_z = z;
_data = new SortedDictionary<(int, int, int), int>[24];
for (int i = 0; i < 24; i++) {
int rot = i%3;
int corner = (i/3)%8;
bool apos = corner%2;
bool bpos = (corner/2)%2;
bool cpos = (corner/4)%2;
Func<Tuple<int, int, int>, Tuple<int, int, int>, int> comparer = (Tuple<int, int, int> A, Tuple<int, int, int> B) => {
int[] d = new int[3];
d[0] = (apos ? 1 : -1)*(B.Item1 - A.Item1);
d[1] = (bpos ? 1 : -1)*(B.Item2 - A.Item2);
d[2] = (cpos ? 1 : -1)*(B.Item3 - A.Item3);
return d[(2+rot)%3] != 0 ? d[(2+rot)%3] : (d[(1+rot)%3] != 0 ? d[(1+rot)%3] : d[rot]);
};
_data[i] = new SortedDictionary<Tuple<int, int, int>, int>(comparer);
}
}
public Shape Grow(int x, int y, int z) {
Tuple<int, int, int> newP = new Tuple<int, int, int>(x, y, z);
if (this._data[0].ContainsKey(newP) throw new InvalidOperationException();
else if (this._data[0].ContainsKey(new Tuple<int, int, int>(x+1, y, z)))
else throw new InvalidOperationException();
}
public static Shape GetCube() {
Shape S = new Shape(1, 1, 1);
S._data[0] = 1;
return S;
}
}

View File

@@ -1,12 +0,0 @@
using System.Collections;
using System.IO.Hashing;
public class AssembledObject {
private static XxHash32 _hash = new XxHash32();
private BitArray _shape;
public override int GetHashCode() {
return 1;
}
}

View File

@@ -1,14 +1,23 @@
namespace CubeShapeCounting { namespace CubeShapeCounting {
internal class Program { internal class Program {
private int _numBlocks = 0; private int _numBlocks = 0;
//private Dictionary<>(); private Dictionary<Shape.ImmutableOrientedShape, int>[] _knownShapes;
public Program(int numBlocks) { public Program(int numBlocks) {
this._numBlocks = numBlocks; _numBlocks = numBlocks;
_knownShapes = new Dictionary<Shape.ImmutableOrientedShape, int>[numBlocks - 1];
for (int i = 0; i < _numBlocks - 1; i++)
_knownShapes[i] = new Dictionary<Shape.ImmutableOrientedShape, int>();
} }
public void Start() { public void Start() {
Stack<Shape> shapes = new Stack<Shape>();
shapes.Push(Shape.GetCube());
while (shapes.Count > 0) {
Shape shape = shapes.Pop();
List<(int, int, int)> next_spaces = shape.GetGrowableSpaces();
}
} }
static void Main(string[] args) { static void Main(string[] args) {
@@ -19,8 +28,7 @@
int numBlocks; int numBlocks;
try { try {
numBlocks = Int32.Parse(args[0]); numBlocks = Int32.Parse(args[0]);
} } catch {
catch {
Console.WriteLine("Cannot parse" + args[0] + "as an Int32."); Console.WriteLine("Cannot parse" + args[0] + "as an Int32.");
return; return;
} }

View File

@@ -1,142 +1,141 @@
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.IO.Hashing; using System.IO.Hashing;
using System.Security.Cryptography;
public class Shape { public class Shape {
private (int, int, int) _minp; private int _size;
private (int, int, int) _maxp; private (int, int, int) _minp;
private (int, int, int)[] _newest; private (int, int, int) _maxp;
private SortedDictionary<(int, int, int), int>[] _data; private (int, int, int)[] _newest;
public bool this[int x, int y, int z] { private SortedDictionary<(int, int, int), int>[] _data;
get { public bool this[int x, int y, int z] {
if (x <= _maxp.Item1 && y <= _maxp.Item2 && z <= _maxp.Item3 && x >= _minp.Item1 && y >= _minp.Item2 && z >= _minp.Item3) { get {
return _data[0].ContainsKey((x, y, z)); if (x <= _maxp.Item1 && y <= _maxp.Item2 && z <= _maxp.Item3 && x >= _minp.Item1 && y >= _minp.Item2 && z >= _minp.Item3) {
} return _data[0].ContainsKey((x, y, z));
else } else
throw new IndexOutOfRangeException(); throw new IndexOutOfRangeException();
} }
} }
private Shape((int, int, int) minp, (int, int, int) maxp, (int, int, int)[] newest, SortedDictionary<(int, int, int), int>[] D) { private Shape((int, int, int) minp, (int, int, int) maxp, (int, int, int)[] newest, SortedDictionary<(int, int, int), int>[] D) {
_minp = minp; _minp = minp;
_maxp = maxp; _maxp = maxp;
_newest = newest; _newest = newest;
_data = D; _data = D;
} _size = D[0].Count;
}
public List<(int, int, int)> GetGrowableSpaces() { public List<(int, int, int)> GetGrowableSpaces() {
List<(int, int, int)> L = new List<(int, int, int)>(); List<(int, int, int)> L = new List<(int, int, int)>();
foreach ((int x, int y, int z) in _data[0].Keys) { foreach ((int x, int y, int z) in _newest) {
if (!_data[0].ContainsKey((x + 1, y, z)) && !L.Contains((x + 1, y, z))) if (!_data[0].ContainsKey((x + 1, y, z)) && !L.Contains((x + 1, y, z)))
L.Add((x + 1, y, z)); L.Add((x + 1, y, z));
if (!_data[0].ContainsKey((x - 1, y, z)) && !L.Contains((x - 1, y, z))) if (!_data[0].ContainsKey((x - 1, y, z)) && !L.Contains((x - 1, y, z)))
L.Add((x - 1, y, z)); L.Add((x - 1, y, z));
if (!_data[0].ContainsKey((x, y + 1, z)) && !L.Contains((x, y + 1, z))) if (!_data[0].ContainsKey((x, y + 1, z)) && !L.Contains((x, y + 1, z)))
L.Add((x, y + 1, z)); L.Add((x, y + 1, z));
if (!_data[0].ContainsKey((x, y - 1, z)) && !L.Contains((x, y - 1, z))) if (!_data[0].ContainsKey((x, y - 1, z)) && !L.Contains((x, y - 1, z)))
L.Add((x, y - 1, z)); L.Add((x, y - 1, z));
if (!_data[0].ContainsKey((x, y, z + 1)) && !L.Contains((x, y, z + 1))) if (!_data[0].ContainsKey((x, y, z + 1)) && !L.Contains((x, y, z + 1)))
L.Add((x, y, z + 1)); L.Add((x, y, z + 1));
if (!_data[0].ContainsKey((x, y, z - 1)) && !L.Contains((x, y, z - 1))) if (!_data[0].ContainsKey((x, y, z - 1)) && !L.Contains((x, y, z - 1)))
L.Add((x, y, z - 1)); L.Add((x, y, z - 1));
} }
return L; return L;
} }
public Shape Grow((int, int, int)[] newPs) { public Shape Grow((int, int, int)[] newPs) {
SortedDictionary<(int, int, int), int> D = this._data[0]; SortedDictionary<(int, int, int), int> D = this._data[0];
for (int i = 0; i < newPs.Length; i++) { for (int i = 0; i < newPs.Length; i++) {
(int x, int y, int z) = newPs[i]; (int x, int y, int z) = newPs[i];
if (D.ContainsKey(newPs[i]) || if (D.ContainsKey(newPs[i]) ||
(!D.ContainsKey((x + 1, y, z)) (!D.ContainsKey((x + 1, y, z))
&& !D.ContainsKey((x - 1, y, z)) && !D.ContainsKey((x - 1, y, z))
&& !D.ContainsKey((x, y + 1, z)) && !D.ContainsKey((x, y + 1, z))
&& !D.ContainsKey((x, y - 1, z)) && !D.ContainsKey((x, y - 1, z))
&& !D.ContainsKey((x, y, z + 1)) && !D.ContainsKey((x, y, z + 1))
&& !D.ContainsKey((x, y, z - 1)))) && !D.ContainsKey((x, y, z - 1))))
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
SortedDictionary<(int, int, int), int>[] newD = new SortedDictionary<(int, int, int), int>[24]; SortedDictionary<(int, int, int), int>[] newD = new SortedDictionary<(int, int, int), int>[24];
for (int i = 0; i < 24; i++) { for (int i = 0; i < 24; i++) {
int rot = i%3; int rot = i % 3;
int corner = (i/3)%8; int corner = (i / 3) % 8;
bool apos = corner%2 != 0; bool apos = corner % 2 != 0;
bool bpos = (corner/2)%2 != 0; bool bpos = (corner / 2) % 2 != 0;
bool cpos = (corner/4)%2 != 0; bool cpos = (corner / 4) % 2 != 0;
Comparison<(int, int, int)> comparer = ((int, int, int) A, (int, int, int) B) => { Comparison<(int, int, int)> comparer = ((int, int, int) A, (int, int, int) B) => {
int[] d = new int[3]; int[] d = new int[3];
d[0] = (apos ? 1 : -1)*(B.Item1 - A.Item1); d[0] = (apos ? 1 : -1) * (B.Item1 - A.Item1);
d[1] = (bpos ? 1 : -1)*(B.Item2 - A.Item2); d[1] = (bpos ? 1 : -1) * (B.Item2 - A.Item2);
d[2] = (cpos ? 1 : -1)*(B.Item3 - A.Item3); d[2] = (cpos ? 1 : -1) * (B.Item3 - A.Item3);
return d[(2+rot)%3] != 0 ? d[(2+rot)%3] : (d[(1+rot)%3] != 0 ? d[(1+rot)%3] : d[rot]); return d[(2 + rot) % 3] != 0 ? d[(2 + rot) % 3] : (d[(1 + rot) % 3] != 0 ? d[(1 + rot) % 3] : d[rot]);
}; };
newD[i] = new SortedDictionary<(int, int, int), int>(D, Comparer<(int, int, int)>.Create(comparer)); newD[i] = new SortedDictionary<(int, int, int), int>(D, Comparer<(int, int, int)>.Create(comparer));
} }
(int, int, int) newminp = this._minp; (int, int, int) newminp = this._minp;
(int, int, int) newmaxp = this._maxp; (int, int, int) newmaxp = this._maxp;
for (int i = 0; i < newPs.Length; i++) { for (int i = 0; i < newPs.Length; i++) {
for (int j = 0; j < newPs.Length; j++) for (int j = 0; j < newPs.Length; j++)
newD[i].Add(newPs[i], 0); newD[i].Add(newPs[i], 0);
newminp = (Math.Min(newminp.Item1, newPs[i].Item1), Math.Min(newminp.Item2, newPs[i].Item2), Math.Min(newminp.Item3, newPs[i].Item3)); newminp = (Math.Min(newminp.Item1, newPs[i].Item1), Math.Min(newminp.Item2, newPs[i].Item2), Math.Min(newminp.Item3, newPs[i].Item3));
newmaxp = (Math.Max(newmaxp.Item1, newPs[i].Item1), Math.Max(newmaxp.Item2, newPs[i].Item2), Math.Max(newmaxp.Item3, newPs[i].Item3)); newmaxp = (Math.Max(newmaxp.Item1, newPs[i].Item1), Math.Max(newmaxp.Item2, newPs[i].Item2), Math.Max(newmaxp.Item3, newPs[i].Item3));
} }
return new Shape(newminp, newmaxp, newPs, newD); return new Shape(newminp, newmaxp, newPs, newD);
} }
public ImmutableOrientedShape[] GetOrientations() { public ImmutableOrientedShape[] GetOrientations() {
ImmutableOrientedShape[] S = new ImmutableOrientedShape[24]; ImmutableOrientedShape[] S = new ImmutableOrientedShape[24];
for (int i = 0; i < 24; i++) { for (int i = 0; i < 24; i++) {
S[i] = new ImmutableOrientedShape(_data[i]); S[i] = new ImmutableOrientedShape(_data[i]);
} }
return S; return S;
} }
public class ImmutableOrientedShape { public class ImmutableOrientedShape {
public readonly ImmutableSortedDictionary<(int, int, int), int> Dict; public readonly ImmutableSortedDictionary<(int, int, int), int> Dict;
public readonly int Hash; public readonly int Hash;
internal ImmutableOrientedShape(SortedDictionary<(int, int, int), int> D) { internal ImmutableOrientedShape(SortedDictionary<(int, int, int), int> D) {
Dict = D.ToImmutableSortedDictionary(); Dict = D.ToImmutableSortedDictionary();
XxHash64 H = new XxHash64(0); XxHash64 H = new XxHash64(0);
IEnumerable<(int, int, int)> keys = Dict.Keys; IEnumerable<(int, int, int)> keys = Dict.Keys;
(int a, int b, int c) = keys.First(); (int a, int b, int c) = keys.First();
Span<byte> s = new byte[12]; Span<byte> s = new byte[12];
foreach ((int x, int y, int z) in keys) { foreach ((int x, int y, int z) in keys) {
BinaryPrimitives.WriteInt32BigEndian(s.Slice(0), x - a); BinaryPrimitives.WriteInt32BigEndian(s.Slice(0), x - a);
BinaryPrimitives.WriteInt32BigEndian(s.Slice(4), y - b); BinaryPrimitives.WriteInt32BigEndian(s.Slice(4), y - b);
BinaryPrimitives.WriteInt32BigEndian(s.Slice(8), z - c); BinaryPrimitives.WriteInt32BigEndian(s.Slice(8), z - c);
H.Append(s.ToArray()); H.Append(s.ToArray());
} }
Hash = BinaryPrimitives.ReadInt32BigEndian(H.GetCurrentHash()); Hash = BinaryPrimitives.ReadInt32BigEndian(H.GetCurrentHash());
} }
public override int GetHashCode() { public override int GetHashCode() {
return Hash; return Hash;
} }
public override bool Equals(object? obj) { public override bool Equals(object? obj) {
if (!(obj is ImmutableOrientedShape)) if (!(obj is ImmutableOrientedShape))
return false; return false;
ImmutableOrientedShape o = (ImmutableOrientedShape)obj; ImmutableOrientedShape o = (ImmutableOrientedShape)obj;
IEnumerable<(int, int, int)> K1 = Dict.Keys; IEnumerable<(int, int, int)> K1 = Dict.Keys;
IEnumerable<(int, int, int)> K2 = o.Dict.Keys; IEnumerable<(int, int, int)> K2 = o.Dict.Keys;
if (K1.Count() != K2.Count()) if (K1.Count() != K2.Count())
return false; return false;
foreach (((int a1, int a2, int a3), (int b1, int b2, int b3)) in K1.Zip(K2)) foreach (((int a1, int a2, int a3), (int b1, int b2, int b3)) in K1.Zip(K2))
if (a1 != b1 || a2 != b2 || a3 != b3) if (a1 != b1 || a2 != b2 || a3 != b3)
return false; return false;
return true; return true;
} }
} }
public static Shape GetCube() { public static Shape GetCube() {
SortedDictionary<(int, int, int), int>[] newD = new SortedDictionary<(int, int, int), int>[24]; SortedDictionary<(int, int, int), int>[] newD = new SortedDictionary<(int, int, int), int>[24];
for (int i = 0; i < 24; i++) { for (int i = 0; i < 24; i++) {
newD[i] = new SortedDictionary<(int, int, int), int>(); newD[i] = new SortedDictionary<(int, int, int), int>();
newD[i].Add((0, 0, 0), 0); newD[i].Add((0, 0, 0), 0);
} }
return new Shape((1, 1, 1), (1, 1, 1), new (int, int, int)[] {(0, 0, 0)}, newD); return new Shape((0, 0, 0), (0, 0, 0), new (int, int, int)[] { (0, 0, 0) }, newD);
} }
} }