101 Logo
onenoughtone

Code Implementation

Domino and Tromino Tiling Implementation

Below is the implementation of the domino and tromino tiling:

solution.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**
* Calculate the number of ways to tile a 2×n board with dominos and trominos.
* Dynamic Programming with Multiple States approach.
*
* @param {number} n - Width of the board
* @return {number} - Number of ways to tile the board
*/
function numTilings(n) {
const MOD = 1000000007;
// Base cases
if (n === 1) {
return 1;
}
// Initialize DP arrays
const dp = new Array(n + 1).fill(0); // dp[i] = ways to fully tile a 2×i board
const dp2 = new Array(n + 1).fill(0); // dp2[i] = ways to tile a 2×i board with one protruding square
// Base cases
dp[0] = 1; // Empty board has one way to tile (do nothing)
dp[1] = 1; // 2×1 board has one way to tile (vertical domino)
dp2[0] = 0; // Empty board has no way to tile with a protruding square
dp2[1] = 1; // 2×1 board has one way to tile with a protruding square
// Fill DP arrays
for (let i = 2; i <= n; i++) {
// dp2[i] = ways to tile with a protruding square
// = ways to place a horizontal domino on a board with a protruding square
// + ways to place a tromino on a fully tiled board
dp2[i] = (dp2[i - 1] + dp[i - 2]) % MOD;
// dp[i] = ways to fully tile a 2×i board
// = ways to place a vertical domino on a fully tiled board
// + ways to place two horizontal dominos on a fully tiled board
// + ways to place a tromino on a board with a protruding square (2 orientations)
dp[i] = (dp[i - 1] + dp[i - 2] + 2 * dp2[i - 1]) % MOD;
}
return dp[n];
}
/**
* Calculate the number of ways to tile a 2×n board with dominos and trominos.
* Dynamic Programming with Recurrence Relation approach.
*
* @param {number} n - Width of the board
* @return {number} - Number of ways to tile the board
*/
function numTilingsRecurrence(n) {
const MOD = 1000000007;
// Base cases
if (n === 1) {
return 1;
}
if (n === 2) {
return 2;
}
if (n === 3) {
return 5;
}
// Initialize DP array
const dp = new Array(n + 1).fill(0);
// Base cases
dp[1] = 1;
dp[2] = 2;
dp[3] = 5;
// Fill DP array using the recurrence relation
for (let i = 4; i <= n; i++) {
dp[i] = (2 * dp[i - 1] % MOD + dp[i - 3]) % MOD;
}
return dp[n];
}
/**
* Calculate the number of ways to tile a 2×n board with dominos and trominos.
* Matrix Exponentiation approach.
*
* @param {number} n - Width of the board
* @return {number} - Number of ways to tile the board
*/
function numTilingsMatrix(n) {
const MOD = 1000000007;
// Base cases
if (n === 1) {
return 1;
}
if (n === 2) {
return 2;
}
if (n === 3) {
return 5;
}
// Define the base matrix
const base = [
[2, 0, 1],
[1, 0, 0],
[0, 1, 0]
];
// Compute base^(n-3)
const result = matrixPower(base, n - 3, MOD);
// Multiply with the initial values [5, 2, 1]
return (result[0][0] * 5 + result[0][1] * 2 + result[0][2] * 1) % MOD;
}
/**
* Compute the power of a matrix using binary exponentiation.
*
* @param {number[][]} matrix - The base matrix
* @param {number} n - The exponent
* @param {number} mod - The modulo value
* @return {number[][]} - The resulting matrix
*/
function matrixPower(matrix, n, mod) {
// Base case: matrix^0 = identity matrix
if (n === 0) {
const size = matrix.length;
const result = Array(size).fill().map(() => Array(size).fill(0));
for (let i = 0; i < size; i++) {
result[i][i] = 1;
}
return result;
}
// If n is odd, compute matrix^(n-1) * matrix
if (n % 2 === 1) {
const result = matrixPower(matrix, n - 1, mod);
return multiplyMatrices(result, matrix, mod);
}
// If n is even, compute (matrix^(n/2))^2
const half = matrixPower(matrix, Math.floor(n / 2), mod);
return multiplyMatrices(half, half, mod);
}
/**
* Multiply two matrices.
*
* @param {number[][]} a - First matrix
* @param {number[][]} b - Second matrix
* @param {number} mod - The modulo value
* @return {number[][]} - The product of the two matrices
*/
function multiplyMatrices(a, b, mod) {
const rowsA = a.length;
const colsA = a[0].length;
const colsB = b[0].length;
const result = Array(rowsA).fill().map(() => Array(colsB).fill(0));
for (let i = 0; i < rowsA; i++) {
for (let j = 0; j < colsB; j++) {
for (let k = 0; k < colsA; k++) {
result[i][j] = (result[i][j] + a[i][k] * b[k][j]) % mod;
}
}
}
return result;
}
// Test cases
console.log(numTilings(1)); // 1
console.log(numTilings(2)); // 2
console.log(numTilings(3)); // 5
console.log(numTilings(4)); // 11
console.log(numTilings(5)); // 24
console.log(numTilingsRecurrence(1)); // 1
console.log(numTilingsRecurrence(2)); // 2
console.log(numTilingsRecurrence(3)); // 5
console.log(numTilingsRecurrence(4)); // 11
console.log(numTilingsRecurrence(5)); // 24
console.log(numTilingsMatrix(1)); // 1
console.log(numTilingsMatrix(2)); // 2
console.log(numTilingsMatrix(3)); // 5
console.log(numTilingsMatrix(4)); // 11
console.log(numTilingsMatrix(5)); // 24

Step-by-Step Explanation

Let's break down the implementation:

  1. Define the States: Define multiple states to represent different configurations of the board, such as fully tiled or with a protruding square.
  2. Establish Base Cases: Set up the base cases for small board sizes and for the initial states of the DP arrays.
  3. Derive Recurrence Relations: Derive the recurrence relations by considering all possible ways to place dominos and trominos on the board.
  4. Fill DP Arrays: Use dynamic programming to fill the arrays from the base cases up to the target board size.
  5. Apply Modulo Operation: Apply the modulo operation at each step to avoid integer overflow, as the answer can be very large.
ProblemSolutionCode
101 Logo
onenoughtone