101 Logo
onenoughtone

Code Implementation

Painting a Grid Implementation

Below is the implementation of the painting a grid:

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
189
190
191
192
/**
* Count the number of ways to paint an m × n grid with three colors.
*
* @param {number} m - Number of rows
* @param {number} n - Number of columns
* @return {number} - Number of ways to paint the grid
*/
function colorTheGrid(m, n) {
const MOD = 1000000007;
// Generate all valid column states
const validStates = [];
const limit = Math.pow(3, m);
for (let state = 0; state < limit; state++) {
if (isValidState(state, m)) {
validStates.push(state);
}
}
// Precompute valid transitions
const validTransitions = {};
for (const state1 of validStates) {
validTransitions[state1] = [];
for (const state2 of validStates) {
if (canTransition(state1, state2, m)) {
validTransitions[state1].push(state2);
}
}
}
// Initialize DP array
let dp = new Array(validStates.length).fill(1);
// Fill DP array
for (let j = 1; j < n; j++) {
const newDp = new Array(validStates.length).fill(0);
for (let i = 0; i < validStates.length; i++) {
const state1 = validStates[i];
for (const state2 of validTransitions[state1]) {
const idx = validStates.indexOf(state2);
newDp[idx] = (newDp[idx] + dp[i]) % MOD;
}
}
dp = newDp;
}
// Sum up the results
let result = 0;
for (let i = 0; i < validStates.length; i++) {
result = (result + dp[i]) % MOD;
}
return result;
}
/**
* Check if a column state is valid (no adjacent cells have the same color).
*
* @param {number} state - The column state in base-3
* @param {number} m - Number of rows
* @return {boolean} - True if the state is valid, false otherwise
*/
function isValidState(state, m) {
// Convert state to base-3 representation
const colors = [];
let tempState = state;
for (let i = 0; i < m; i++) {
colors.push(tempState % 3);
tempState = Math.floor(tempState / 3);
}
// Check if adjacent cells have different colors
for (let i = 0; i < m - 1; i++) {
if (colors[i] === colors[i + 1]) {
return false;
}
}
return true;
}
/**
* Check if two column states can be adjacent (no horizontally adjacent cells have the same color).
*
* @param {number} state1 - The first column state in base-3
* @param {number} state2 - The second column state in base-3
* @param {number} m - Number of rows
* @return {boolean} - True if the states can be adjacent, false otherwise
*/
function canTransition(state1, state2, m) {
// Convert states to base-3 representation
const colors1 = [];
const colors2 = [];
let tempState1 = state1;
let tempState2 = state2;
for (let i = 0; i < m; i++) {
colors1.push(tempState1 % 3);
colors2.push(tempState2 % 3);
tempState1 = Math.floor(tempState1 / 3);
tempState2 = Math.floor(tempState2 / 3);
}
// Check if horizontally adjacent cells have different colors
for (let i = 0; i < m; i++) {
if (colors1[i] === colors2[i]) {
return false;
}
}
return true;
}
// Optimized version for larger inputs
function colorTheGridOptimized(m, n) {
const MOD = 1000000007;
// Generate all valid column states and their color configurations
const validStates = [];
const colorConfigs = new Map();
const limit = Math.pow(3, m);
for (let state = 0; state < limit; state++) {
if (isValidState(state, m)) {
validStates.push(state);
// Store the color configuration for this state
const colors = [];
let tempState = state;
for (let i = 0; i < m; i++) {
colors.push(tempState % 3);
tempState = Math.floor(tempState / 3);
}
colorConfigs.set(state, colors);
}
}
// Precompute valid transitions using color configurations
const validTransitions = {};
for (const state1 of validStates) {
validTransitions[state1] = [];
const colors1 = colorConfigs.get(state1);
for (const state2 of validStates) {
const colors2 = colorConfigs.get(state2);
let valid = true;
for (let i = 0; i < m; i++) {
if (colors1[i] === colors2[i]) {
valid = false;
break;
}
}
if (valid) {
validTransitions[state1].push(state2);
}
}
}
// Initialize DP array
let dp = new Array(validStates.length).fill(1);
// Fill DP array
for (let j = 1; j < n; j++) {
const newDp = new Array(validStates.length).fill(0);
for (let i = 0; i < validStates.length; i++) {
const state1 = validStates[i];
for (let k = 0; k < validTransitions[state1].length; k++) {
const state2 = validTransitions[state1][k];
const idx = validStates.indexOf(state2);
newDp[idx] = (newDp[idx] + dp[i]) % MOD;
}
}
dp = newDp;
}
// Sum up the results
let result = 0;
for (let i = 0; i < validStates.length; i++) {
result = (result + dp[i]) % MOD;
}
return result;
}
// Test cases
console.log(colorTheGrid(1, 1)); // 3
console.log(colorTheGrid(1, 2)); // 6
console.log(colorTheGrid(5, 3)); // 580986

Step-by-Step Explanation

Let's break down the implementation:

  1. Understand the Problem: First, understand that we need to count the number of ways to paint an m × n grid with three colors such that no adjacent cells have the same color.
  2. Generate Valid Column States: Generate all valid column states where no adjacent cells in the column have the same color.
  3. Precompute Valid Transitions: For each valid column state, precompute all valid next states that can follow it (no horizontally adjacent cells have the same color).
  4. Implement Dynamic Programming: Use dynamic programming to count the number of ways to paint the grid, considering one column at a time.
  5. Optimize for Space: Optimize the space complexity by only storing the DP results for the current column.
ProblemSolutionCode
101 Logo
onenoughtone