% 4-story tetrahedral ball tower from 6 2D shapes:
%
%  o     o       o    o o              o
% o o   o o   o o    o o    o o o   o o o
%
%  h     h     l      4       3       p
%
% Order of positions:
%
%       10                16           19        20
%      8   9            14  15       17  18
%    5   6   7        11  12  13
%  1   2   3   4
%
% Example solution:
% [3,4,4,p,3,4,4,3,h,h,h,p,p,h,l,h,h,p,l,l]
%
%    h        h      l     l
%   3 h      h l    h p
%  3 4 4    h p p
% 3 4 4 p

pos(p(X,Y,1)) :- between(1, 4, X), between(1, 4, Y), X + Y =< 5.
pos(p(X,Y,2)) :- between(1, 3, X), between(1, 3, Y), X + Y =< 4.
pos(p(X,Y,3)) :- between(1, 2, X), between(1, 2, Y), X + Y =< 3.
pos(p(1,1,4)).

dir(d( 1, 0, 0)). dir(d( 0, 1, 0)). dir(d( 0, 0, 1)).
dir(d(-1, 0, 0)). dir(d( 0,-1, 0)). dir(d( 0, 0,-1)).
dir(d( 1,-1, 0)). dir(d( 0, 1,-1)). dir(d(-1, 0, 1)).
dir(d(-1, 1, 0)). dir(d( 0,-1, 1)). dir(d( 1, 0,-1)).

vector(d(U,V,W), v(X,Y,Z)) :-
    X is U + 0.5 * V + 0.5 * W,
    Y is V * sqrt(3) / 2 + W * sqrt(3) / 6,
    Z is W * sqrt(6) / 3.

dot(v(X1,Y1,Z1), v(X2,Y2,Z2), D) :- D is X1 * X2 + Y1 * Y2 + Z1 * Z2.

:- table(valid_system/2).
valid_system(D1, D2) :-
    vector(D1, V1), vector(D2, V2),
    dot(V1, V2, D), abs(D - 0.5) < 0.05.

in_system(U-V, d(X1,Y1,Z1), d(X2,Y2,Z2), d(X,Y,Z)) :-
    X is X1 * U + X2 * V,
    Y is Y1 * U + Y2 * V,
    Z is Z1 * U + Z2 * V.

add(p(X,Y,Z), d(DX,DY,DZ), p(X1,Y1,Z1)) :-
    X1 is X + DX,
    Y1 is Y + DY,
    Z1 is Z + DZ.

shape(3, [1-0,2-0]).
shape(4, [1-0,0-1,1-1]).
shape(h, [1-0,0-1]).
shape(l, [1-0,1-1]).
shape(p, [1-0,2-0,1-1]).

solve(X) :- solve([3,4,h,h,l,p], [], X).

solve([], X, X).
solve([S|Ss], A, X) :-
    pos(P), \+ member(P-_, A),
    dir(D1), dir(D2), valid_system(D1, D2),
    shape(S, L),
    place(L, S, P, D1, D2, [P-S|A], A1),
    solve(Ss, A1, X).

place([], _, _, _, _, A, A).
place([UV|UVs], S, P, D1, D2, A, X) :-
    in_system(UV, D1, D2, D),
    add(P, D, P1),
    pos(P1), \+ member(P1-_, A),
    place(UVs, S, P, D1, D2, [P1-S|A], X).

serialize(X, S) :-
    findall(P, pos(P), L),
    maplist(type(X), L, S).

type(X, P, T) :- member(P-T, X).

% To get rid of symmetries, let us fix the `3`-shape.
% There are only 2 variations:
% ?- solve([4,h,h,l,p], [p(1,1,1)-3,p(2,1,1)-3,p(3,1,1)-3], X),
%    serialize(X, S), write(S), nl, false.
% ?- solve([4,h,h,l,p], [p(1,2,1)-3,p(2,2,1)-3,p(3,2,1)-3], X),
%    serialize(X, S), write(S), nl, false.

% Both variations allow mirroring - should be eliminated by hand.

% Type I (duplicates removed, mirror associations shown):

% 001. [3,4,4,h,3,p,h,3,p,l,4,4,h,l,p,l,h,p,h,h]
% 002. [3,4,4,l,3,4,4,3,h,h,p,l,l,h,h,h,p,p,h,p]
% 003. [3,4,4,l,3,4,4,3,h,h,p,l,l,p,h,h,p,h,h,p]
% 004. [3,4,4,l,3,4,4,3,p,p,h,h,l,h,l,p,h,h,p,h]
% 005. [3,4,4,l,3,h,h,3,h,p,4,4,l,p,l,p,h,h,p,h]
% 006. [3,4,4,l,3,l,l,3,h,h,4,4,p,h,h,h,p,p,h,p]
% 007. [3,4,4,l,3,l,l,3,h,h,4,4,p,h,p,h,h,p,h,p]
% 008. [3,4,4,l,3,l,l,3,h,h,p,4,4,h,h,h,p,p,h,p]
% 009. [3,4,4,l,3,l,l,3,h,h,p,4,4,p,h,h,p,h,h,p]
% 010. [3,4,4,l,3,p,p,3,p,p,4,4,l,h,l,h,h,h,h,h]
% 011. [3,4,4,p,3,4,4,3,h,h,h,h,p,l,p,h,h,p,l,l]
% 012. [3,4,4,p,3,4,4,3,h,h,h,p,p,h,l,h,h,p,l,l]
% 013. [3,4,4,p,3,4,4,3,h,h,l,p,p,l,l,h,h,p,h,h]
% 014. [3,4,4,p,3,h,h,3,h,l,4,4,p,l,p,l,h,p,h,h]
% 015. [3,4,4,p,3,h,p,3,h,l,4,4,p,l,h,l,h,p,h,h]
% 016. [3,4,4,p,3,l,l,3,h,h,4,4,p,l,p,h,h,p,h,h]
% 017. [3,4,4,p,3,l,p,3,l,l,4,4,p,h,h,h,h,p,h,h]
% 018. [3,4,4,p,3,p,p,3,p,l,4,4,h,l,h,l,h,h,h,h]
% 019. [3,4,4,p,3,p,p,3,p,l,h,4,4,h,l,l,h,h,h,h]
% 020. [3,4,h,h,3,4,h,3,h,h,l,4,p,l,4,h,p,p,l,p]
% 021. [3,4,h,h,3,4,h,3,h,h,p,4,l,p,4,h,p,l,l,p]
% 022. [3,4,h,h,3,4,p,3,p,p,l,4,h,l,4,p,h,h,l,h]
% 023. [3,4,h,h,3,h,h,3,h,l,4,4,p,l,h,l,4,p,p,p] = 017
% 024. [3,4,h,h,3,h,h,3,h,p,4,4,h,p,l,p,4,l,p,l] = 010
% 025. [3,4,h,h,3,l,h,3,h,h,4,4,p,l,p,h,4,p,l,p] = 016
% 026. [3,4,h,h,3,l,h,3,l,l,4,4,h,p,h,p,4,h,p,p] = 018
% 027. [3,4,h,h,3,l,h,3,l,l,4,4,p,h,h,h,4,p,p,p] = 015
% 028. [3,4,h,h,3,l,h,3,l,l,4,4,p,h,p,h,4,p,h,p] = 014
% 029. [3,4,h,h,3,l,h,3,l,l,4,4,p,p,p,p,4,h,h,h] = 001
% 030. [3,4,h,h,3,p,p,3,p,p,4,4,h,h,l,h,4,l,h,l] = 005
% 031. [3,4,h,p,3,h,h,3,h,h,4,4,p,l,p,h,4,p,l,l] = 007
% 032. [3,4,p,p,3,h,h,3,h,h,4,4,p,l,h,h,4,p,l,l] = 006
% 033. [3,h,4,4,3,4,4,3,l,l,h,h,p,h,l,h,p,p,h,p]
% 034. [3,h,4,4,3,4,4,3,l,p,h,h,l,p,l,p,h,h,p,h]
% 035. [3,h,4,4,3,4,4,3,p,l,h,h,p,l,p,l,h,p,h,h]
% 036. [3,h,4,4,3,4,4,3,p,p,h,h,h,l,h,p,l,h,p,l]
% 037. [3,h,4,4,3,4,4,3,p,p,h,h,l,l,l,p,h,h,p,h]
% 038. [3,h,4,l,3,4,4,3,4,p,h,h,l,p,l,p,h,h,p,h]
% 039. [3,h,4,p,3,4,4,3,4,l,h,h,p,l,p,l,h,p,h,h]
% 040. [3,h,h,4,3,h,4,3,p,p,h,l,4,h,4,p,h,l,p,l]
% 041. [3,h,h,4,3,l,4,3,h,h,p,h,4,l,4,h,p,p,l,p]
% 042. [3,h,h,4,3,l,4,3,l,l,h,h,4,h,4,p,h,p,p,p]
% 043. [3,h,h,4,3,l,4,3,l,l,p,h,4,h,4,h,p,p,h,p]
% 044. [3,h,h,4,3,l,4,3,l,l,p,h,4,p,4,p,h,h,p,h]
% 045. [3,h,h,4,3,l,4,3,l,l,p,h,4,p,4,p,p,h,h,h]
% 046. [3,h,h,h,3,h,h,3,4,4,l,h,p,l,4,4,p,p,l,p]
% 047. [3,h,h,h,3,h,h,3,4,4,p,h,l,p,4,4,p,l,l,p]
% 048. [3,h,h,h,3,h,h,3,l,l,4,4,h,p,l,p,4,4,p,p] = 019
% 049. [3,h,h,h,3,h,h,3,l,l,p,4,h,p,l,p,4,4,p,4]
% 050. [3,h,h,h,3,h,h,3,p,p,l,4,h,l,l,p,4,4,p,4]
% 051. [3,h,h,h,3,h,p,3,p,p,4,h,h,4,l,p,4,l,4,l] = 004
% 052. [3,h,h,h,3,l,h,3,4,4,h,h,p,l,4,4,l,p,p,p]
% 053. [3,h,h,h,3,l,h,3,4,4,h,h,p,l,4,4,p,p,l,p]
% 054. [3,h,h,h,3,l,h,3,4,4,p,h,h,l,4,4,p,p,l,p]
% 055. [3,h,h,h,3,l,h,3,l,l,h,h,p,4,p,4,4,p,4,p] = 039
% 056. [3,h,h,h,3,l,h,3,l,l,h,h,p,4,p,p,4,p,4,4] = 035
% 057. [3,h,h,h,3,l,h,3,l,l,p,h,h,p,4,4,p,4,4,p]
% 058. [3,h,h,h,3,l,h,3,l,l,p,h,h,p,4,p,p,4,4,4]
% 059. [3,h,h,h,3,l,p,3,p,p,h,h,h,4,l,p,4,l,4,4] = 037
% 060. [3,h,h,h,3,l,p,3,p,p,h,h,h,l,4,p,l,4,4,4]
% 061. [3,h,h,h,3,p,p,3,p,p,h,h,h,4,l,4,4,l,4,l] = 038
% 062. [3,h,h,h,3,p,p,3,p,p,h,h,h,4,l,l,4,l,4,4] = 034
% 063. [3,h,h,h,3,p,p,3,p,p,h,h,h,l,4,4,l,4,4,l]
% 064. [3,h,h,h,3,p,p,3,p,p,h,h,h,l,4,l,l,4,4,4]
% 065. [3,h,h,l,3,h,l,3,h,h,4,p,p,4,l,h,4,p,4,p] = 012
% 066. [3,h,h,l,3,h,l,3,h,h,p,p,p,4,l,h,4,p,4,4]
% 067. [3,h,h,l,3,h,p,3,p,p,h,l,l,h,4,p,h,4,4,4] = 040
% 068. [3,h,h,l,3,l,l,3,4,4,h,h,p,h,4,4,h,p,p,p]
% 069. [3,h,h,l,3,l,l,3,h,h,4,h,p,4,p,h,4,p,4,p] = 011
% 070. [3,h,h,l,3,l,l,3,h,h,p,h,4,p,4,h,p,4,4,p]
% 071. [3,h,h,p,3,h,p,3,4,4,h,h,p,l,4,4,h,p,l,l] = 068
% 072. [3,h,h,p,3,h,p,3,h,h,l,l,p,4,l,h,4,p,4,4]
% 073. [3,h,h,p,3,h,p,3,p,l,h,h,p,l,4,l,h,4,4,4] = 042
% 074. [3,h,l,4,3,l,4,3,l,p,h,h,4,p,4,p,h,h,p,h] = 064
% 075. [3,h,l,4,3,l,4,3,p,p,h,h,4,l,4,p,h,h,p,h] = 060
% 076. [3,h,l,l,3,l,4,3,4,p,h,h,4,p,4,p,h,h,p,h] = 063
% 077. [3,h,l,l,3,l,p,3,p,p,h,h,h,4,h,p,4,h,4,4] = 036
% 078. [3,h,l,p,3,l,p,3,4,4,h,h,p,l,4,4,h,p,h,h] = 052
% 079. [3,h,p,p,3,h,h,3,h,l,h,h,p,4,l,l,4,p,4,4] = 033
% 080. [3,h,p,p,3,l,l,3,4,4,h,h,p,l,4,4,h,p,h,h] = 053
% 081. [3,l,4,4,3,4,4,3,h,h,h,l,p,h,l,h,h,p,p,p] = 072
% 082. [3,l,4,4,3,4,4,3,h,h,l,h,p,h,h,h,l,p,p,p]
% 083. [3,l,4,4,3,4,4,3,h,h,l,p,p,h,h,h,l,p,h,p]
% 084. [3,l,4,4,3,4,4,3,h,h,p,l,l,h,h,h,p,p,h,p]
% 085. [3,l,4,4,3,4,4,3,h,h,p,l,l,p,h,h,p,h,h,p]
% 086. [3,l,4,4,3,h,p,3,p,p,l,4,4,h,h,p,l,h,h,h]
% 087. [3,l,4,4,3,l,l,3,h,h,p,4,4,h,h,h,p,p,h,p]
% 088. [3,l,4,4,3,l,l,3,h,h,p,4,4,p,h,h,p,h,h,p]
% 089. [3,l,4,4,3,l,p,3,p,p,h,4,4,h,l,p,h,h,h,h] = 050
% 090. [3,l,4,4,3,p,p,3,p,p,l,4,4,h,h,h,l,h,h,h]
% 091. [3,l,h,h,3,4,h,3,h,h,l,p,p,4,4,h,l,p,4,p]
% 092. [3,l,h,h,3,4,h,3,h,h,p,l,l,4,4,h,p,p,4,p]
% 093. [3,l,h,h,3,h,h,3,4,4,l,h,p,h,4,4,l,p,p,p]
% 094. [3,l,h,h,3,h,p,3,p,p,l,h,h,h,4,p,l,4,4,4]
% 095. [3,l,h,h,3,l,h,3,h,h,4,p,p,4,l,h,4,p,4,p] = 013
% 096. [3,l,h,h,3,l,h,3,h,h,p,p,p,4,l,h,4,p,4,4]
% 097. [3,l,h,h,3,l,l,3,p,p,4,4,h,4,4,p,h,h,p,h] = 022
% 098. [3,l,h,h,3,p,p,3,p,p,l,4,h,4,4,4,l,h,h,h]
% 099. [3,l,l,4,3,h,4,3,p,p,l,h,4,h,4,p,h,h,p,h] = 094
% 100. [3,l,l,h,3,4,h,3,4,p,l,4,h,p,4,p,h,h,p,h] = 098
% 101. [3,l,l,h,3,h,h,3,h,p,l,4,h,p,h,p,4,4,p,4] = 090
% 102. [3,l,l,h,3,h,h,3,p,p,l,4,h,h,h,p,4,4,p,4] = 086
% 103. [3,l,l,p,3,4,4,3,h,h,l,p,p,4,4,h,h,p,h,h] = 091
% 104. [3,l,l,p,3,h,h,3,h,h,l,p,p,4,h,h,4,p,4,4] = 083
% 105. [3,l,l,p,3,h,p,3,4,4,l,h,p,h,4,4,h,p,h,h] = 093
% 106. [3,l,l,p,3,h,p,3,h,h,l,h,p,4,h,h,4,p,4,4] = 082
% 107. [3,l,p,p,3,l,l,3,4,4,h,h,p,h,4,4,h,p,h,h] = 046
% 108. [3,l,p,p,3,l,l,3,h,h,4,4,p,4,4,h,h,p,h,h] = 020
% 109. [3,p,4,4,3,4,4,3,h,h,h,p,p,h,l,h,h,p,l,l] = 066
% 110. [3,p,4,4,3,4,4,3,h,h,l,p,p,l,l,h,h,p,h,h] = 096
% 111. [3,p,4,4,3,4,4,3,h,h,p,p,l,l,l,h,h,p,h,h]
% 112. [3,p,4,4,3,4,4,3,h,h,p,p,p,h,l,h,h,l,h,l]
% 113. [3,p,4,4,3,4,4,3,h,h,p,p,p,l,h,h,l,h,h,l]
% 114. [3,p,4,4,3,4,4,3,l,l,p,p,p,h,l,h,h,h,h,h]
% 115. [3,p,4,4,3,p,p,3,p,l,h,4,4,h,l,l,h,h,h,h] = 049
% 116. [3,p,h,h,3,h,h,3,h,l,p,p,h,4,l,l,4,p,4,4] = 114
% 117. [3,p,h,h,3,l,h,3,4,4,p,p,p,l,4,4,h,h,l,h]
% 118. [3,p,h,h,3,l,h,3,4,4,p,p,p,l,4,4,l,h,h,h]
% 119. [3,p,h,h,3,l,h,3,h,h,p,p,p,4,l,h,4,l,4,4] = 111
% 120. [3,p,h,h,3,l,h,3,h,h,p,p,p,l,4,h,l,4,4,4]
% 121. [3,p,h,h,3,l,l,3,4,4,p,p,h,l,4,4,h,p,h,h] = 117
% 122. [3,p,h,h,3,p,p,3,p,l,h,h,h,l,4,l,h,4,4,4] = 044
% 123. [3,p,h,l,3,h,h,3,h,h,p,p,l,4,l,h,4,p,4,4] = 112
% 124. [3,p,l,4,3,l,4,3,h,h,p,p,4,l,4,h,h,p,h,h] = 120
% 125. [3,p,l,h,3,l,h,3,4,4,p,p,h,l,4,4,h,p,h,h] = 118
% 126. [3,p,l,l,3,l,h,3,h,h,p,p,h,4,h,h,4,p,4,4] = 113
% 127. [3,p,p,4,3,p,4,3,p,l,h,h,4,l,4,l,h,h,h,h] = 058
% 128. [3,p,p,h,3,p,h,3,p,l,h,h,h,l,4,l,h,4,4,4] = 045
% 129. [3,p,p,p,3,4,4,3,h,h,l,l,p,4,4,h,h,l,h,h] = 092
% 130. [3,p,p,p,3,h,h,3,h,h,4,4,p,l,h,h,4,4,l,l] = 008
% 131. [3,p,p,p,3,h,h,3,h,h,4,l,p,4,h,h,4,l,4,l] = 002
% 132. [3,p,p,p,3,h,h,3,h,h,l,4,p,l,h,h,4,4,l,4] = 087
% 133. [3,p,p,p,3,h,h,3,h,h,l,l,p,4,h,h,4,l,4,4] = 084
% 134. [3,p,p,p,3,h,h,3,h,l,h,h,p,l,4,l,h,4,4,4] = 043
% 135. [3,p,p,p,3,l,l,3,4,4,h,h,p,l,4,4,h,h,h,h] = 054
% 136. [3,p,p,p,3,l,l,3,h,h,h,h,p,l,4,h,h,4,4,4] = 041
% 137. [3,p,p,p,3,p,4,3,4,l,h,h,4,l,4,l,h,h,h,h] = 057
% 138. [3,p,p,p,3,p,4,3,h,h,h,h,4,l,4,h,h,4,l,l] = 070
% 139. [3,p,p,p,3,p,h,3,h,h,4,4,h,l,h,h,4,4,l,l] = 009
% 140. [3,p,p,p,3,p,h,3,h,h,4,l,h,4,h,h,4,l,4,l] = 003
% 141. [3,p,p,p,3,p,h,3,h,h,l,4,h,l,h,h,4,4,l,4] = 088
% 142. [3,p,p,p,3,p,h,3,h,h,l,l,h,4,h,h,4,l,4,4] = 085
% 143. [3,p,p,p,3,p,l,3,4,4,h,h,l,h,4,4,h,l,h,h] = 047
% 144. [3,p,p,p,3,p,l,3,h,h,4,4,l,4,4,h,h,l,h,h] = 021

% Type II (duplicates removed, mirror associations shown):

% 01. [4,3,h,h,4,3,h,p,3,p,4,l,h,4,h,p,l,h,p,l]
% 02. [4,3,h,h,4,3,p,h,3,h,4,l,h,4,p,h,l,p,p,l]
% 03. [4,3,h,l,4,3,l,p,3,p,4,h,h,4,l,p,h,h,p,h]
% 04. [4,3,l,l,4,3,h,p,3,p,4,l,h,4,h,p,h,h,p,h]
% 05. [4,3,l,l,4,3,p,h,3,h,4,l,p,4,p,h,h,h,p,h]
% 06. [4,3,p,h,4,3,h,h,3,h,4,p,h,4,l,h,p,p,l,l]
% 07. [4,3,p,l,4,3,l,h,3,h,4,p,p,4,l,h,p,h,h,h]
% 08. [h,3,4,4,h,3,l,p,3,p,h,4,4,l,l,p,h,h,p,h]
% 09. [h,3,4,4,h,3,p,h,3,h,h,4,4,l,p,h,l,p,p,l]
% 10. [h,3,4,4,h,3,p,l,3,l,h,4,4,l,p,p,h,h,p,h]
% 11. [h,3,h,h,h,3,h,l,3,l,h,4,4,l,p,p,4,4,p,p]
% 12. [h,3,h,h,h,3,h,l,3,l,h,4,p,l,p,p,4,4,p,4]
% 13. [h,3,h,h,h,3,h,p,3,p,h,4,l,l,l,p,4,4,p,4]
% 14. [h,3,h,h,h,3,l,p,3,p,h,4,h,l,l,p,4,4,p,4]
% 15. [h,3,h,h,h,3,p,4,3,4,h,l,h,4,p,4,l,p,p,l] = 06
% 16. [h,3,h,h,h,3,p,l,3,l,h,4,h,l,p,p,4,4,p,4]
% 17. [h,3,l,4,h,3,4,p,3,p,h,l,4,l,4,p,h,h,p,h]
% 18. [h,3,l,l,h,3,p,4,3,4,h,l,p,4,p,4,h,h,p,h] = 07
% 19. [h,3,p,4,h,3,4,h,3,h,h,p,4,l,4,h,p,p,l,l] = 09
% 20. [h,3,p,h,h,3,h,4,3,4,h,p,h,4,l,4,p,p,l,l] = 02
% 21. [h,3,p,l,h,3,l,4,3,4,h,p,p,4,l,4,p,h,h,h] = 05
% 22. [l,3,h,h,l,3,h,h,3,h,p,p,4,l,4,h,p,4,4,p] = 11
% 23. [l,3,h,h,l,3,h,h,3,h,p,p,p,l,4,h,p,4,4,4] = 12
% 24. [l,3,h,h,p,3,h,p,3,p,l,l,h,4,h,p,4,h,4,4]
% 25. [l,3,p,4,l,3,4,h,3,h,p,p,4,l,4,h,p,h,h,h] = 10
% 26. [l,3,p,h,l,3,h,h,3,h,p,p,h,l,4,h,p,4,4,4] = 16
% 27. [p,3,4,4,p,3,l,h,3,h,p,4,4,l,l,h,p,h,h,h] = 17
% 28. [p,3,h,h,p,3,h,4,3,4,p,h,h,4,l,4,p,h,l,l] = 01
% 29. [p,3,h,h,p,3,h,h,3,h,p,l,l,l,4,h,p,4,4,4] = 13
% 30. [p,3,h,h,p,3,h,p,3,l,p,h,h,4,l,l,4,h,4,4] = 24
% 31. [p,3,h,l,p,3,l,4,3,4,p,h,h,4,l,4,p,h,h,h] = 04
% 32. [p,3,l,4,p,3,4,h,3,h,p,l,4,l,4,h,p,h,h,h] = 08
% 33. [p,3,l,h,p,3,h,h,3,h,p,l,h,l,4,h,p,4,4,4] = 14
% 34. [p,3,l,l,p,3,h,4,3,4,p,l,h,4,h,4,p,h,h,h] = 03

% So there are 144/2 + 34/2 = 89 essentially different solutions.