Crack-free Walls
Consider building a wall that is 32 units wide and 10 units tall using bricks of width 2 and width 3 (all height 1). A wall is crack-free if there is no vertical line running through the entire hei...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Consider the problem of building a wall out of \(2 \times 1\) and \(3 \times 1\) bricks (\(\text {horizontal} \times \text {vertical}\) dimensions) such that, for extra strength, the gaps between horizontally-adjacent bricks never line up in consecutive layers, i.e. never form a "running crack".
For example, the following \(9 \times 3\) wall is not acceptable due to the running crack shown in red:

There are eight ways of forming a crack-free \(9 \times 3\) wall, written \(W(9,3) = 8\).
Calculate \(W(32,10)\).
Problem 215: Crack-free Walls
Mathematical Foundation
Definition. A row tiling of width is an ordered sequence of bricks of width 2 or 3 whose widths sum to . The crack set of a row tiling is the set of interior partial sums, i.e., the positions of joints between consecutive bricks (excluding and ).
Theorem 1 (Crack-free characterization). A wall of height with row tilings (from bottom to top) is crack-free if and only if for all .
Proof. () Suppose every adjacent pair is compatible. A vertical crack at position would require for all . But if , then by the compatibility condition, so cannot persist through all rows.
() Conversely, if some adjacent pair shares a crack position , then we do not directly get a full-height crack. However, the problem’s condition is pairwise: the wall is crack-free iff no position appears in all rows. But the standard formulation actually requires pairwise compatibility of adjacent rows to prevent any crack from propagating. We prove the stronger claim: the condition for all adjacent pairs is equivalent to requiring no position belongs to for all simultaneously. The forward direction is immediate (pairwise disjointness is stronger). For the reverse: any appearing in all rows would in particular appear in adjacent rows , contradicting pairwise disjointness. So pairwise compatibility is sufficient. It is also necessary for ensuring crack-freedom under the standard construction where cracks must be blocked at each layer boundary.
Lemma 1 (Row tiling count). The number of row tilings of width 32 with bricks of width 2 and 3 equals over all with . The valid pairs are .
Proof. A tiling with bricks of width 2 and bricks of width 3 is an ordered arrangement of bricks, of which are of one type and of another. The number of such arrangements is the multinomial coefficient . The constraint with yields the listed pairs.
Theorem 2 (DP correctness). Let be the set of all row tilings. Define as the number of crack-free walls of height whose top row is . Then:
- Base: for all .
- Recurrence: .
- Answer: where .
Proof. The base case is clear: every single-row tiling is trivially crack-free. For the recurrence, a crack-free wall of height with top row is obtained by choosing a crack-free wall of height whose top row is compatible with (i.e., ), and placing on top. The summation counts all such extensions.
Editorial
We enumerate all row tilings of width W. We then build compatibility matrix. Finally, we apply dynamic programming over the compatible rows. We use dynamic programming over the state space implied by the derivation, apply each admissible transition, and read the answer from the final table entry.
Pseudocode
Enumerate all row tilings of width W
Build compatibility matrix
DP over rows
Complexity Analysis
Let be the number of distinct row tilings.
- Time: Enumeration: . Compatibility matrix: . DP: . Total: . For , is in the low thousands, making this highly tractable.
- Space: for the compatibility matrix, for the DP state.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
int W = 32;
int H = 10;
vector<vector<int>> rows; // each row is a set of crack positions
void generate(int pos, vector<int>& cracks) {
if (pos == W) {
rows.push_back(cracks);
return;
}
// Try placing a 2-brick
if (pos + 2 <= W) {
if (pos + 2 < W) cracks.push_back(pos + 2);
generate(pos + 2, cracks);
if (pos + 2 < W) cracks.pop_back();
}
// Try placing a 3-brick
if (pos + 3 <= W) {
if (pos + 3 < W) cracks.push_back(pos + 3);
generate(pos + 3, cracks);
if (pos + 3 < W) cracks.pop_back();
}
}
int main() {
vector<int> cracks;
generate(0, cracks);
int m = rows.size();
// Convert crack positions to bitmask for fast compatibility check
vector<unsigned int> mask(m, 0);
for (int i = 0; i < m; i++) {
for (int c : rows[i]) {
mask[i] |= (1u << c);
}
}
// Build compatibility list
vector<vector<int>> compat(m);
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
if ((mask[i] & mask[j]) == 0) {
compat[i].push_back(j);
}
}
}
// DP
vector<long long> dp(m, 1); // height 1: each row has 1 way
for (int h = 2; h <= H; h++) {
vector<long long> ndp(m, 0);
for (int i = 0; i < m; i++) {
for (int j : compat[i]) {
ndp[i] += dp[j];
}
}
dp = ndp;
}
long long answer = 0;
for (int i = 0; i < m; i++) {
answer += dp[i];
}
cout << answer << endl;
return 0;
}
def solve():
W = 32
H = 10
# Generate all row tilings as sets of crack positions
rows = []
def generate(pos, cracks):
if pos == W:
rows.append(frozenset(cracks))
return
# Try 2-brick
if pos + 2 <= W:
new_cracks = cracks + ([pos + 2] if pos + 2 < W else [])
generate(pos + 2, new_cracks)
# Try 3-brick
if pos + 3 <= W:
new_cracks = cracks + ([pos + 3] if pos + 3 < W else [])
generate(pos + 3, new_cracks)
generate(0, [])
m = len(rows)
# Build compatibility: two rows are compatible if they share no crack position
compat = [[] for _ in range(m)]
for i in range(m):
for j in range(m):
if rows[i].isdisjoint(rows[j]):
compat[i].append(j)
# DP: dp[i] = number of walls of current height ending with row i
dp = [1] * m # height 1
for h in range(2, H + 1):
ndp = [0] * m
for i in range(m):
for j in compat[i]:
ndp[i] += dp[j]
dp = ndp
answer = sum(dp)
print(answer)
if __name__ == "__main__":
solve()