perl logo Perl logo (Thanks to Olaf Alders)

The weekly challenge 354 - Task 2: Shift Grid

  1 #!/usr/bin/env perl
  2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-354/#TASK2
  3 #
  4 # Task 2: Shift Grid
  5 # ==================
  6 #
  7 # You are given m x n matrix and an integer, $k > 0.
  8 #
  9 # Write a script to shift the given matrix $k times.
 10 #
 11 # Each shift follow the rules:
 12 #
 13 # Rule 1:
 14 # Element at grid[i][j] moves to grid[i][j + 1]
 15 # This means every element moves one step to the right within its row.
 16 #
 17 # Rule 2:
 18 # Element at grid[i][n - 1] moves to grid[i + 1][0]
 19 # This handles the last column: elements in the last column of row i wrap to the first column of the next row (i+1).
 20 #
 21 # Rule 3:
 22 # Element at grid[m - 1][n - 1] moves to grid[0][0]
 23 # This is the bottom-right corner: it wraps to the top-left corner.
 24 #
 25 ## Example 1
 26 ##
 27 ## Input: @matrix = ([1, 2, 3],
 28 ##                   [4, 5, 6],
 29 ##                   [7, 8, 9],)
 30 ##        $k = 1
 31 ## Output: ([9, 1, 2],
 32 ##          [3, 4, 5],
 33 ##          [6, 7, 8],)
 34 ##
 35 ## Rule 1: grid[i][j] -> grid[i][j+1] for j < n-1.
 36 ##
 37 ## We take elements from the original grid at (i, j) and put them into new_grid[i][j+1].
 38 ##
 39 ## From original:
 40 ##
 41 ## (0,0): 1 -> new_grid[0][1] = 1
 42 ## (0,1): 2 -> new_grid[0][2] = 2
 43 ## (1,0): 4 -> new_grid[1][1] = 4
 44 ## (1,1): 5 -> new_grid[1][2] = 5
 45 ## (2,0): 7 -> new_grid[2][1] = 7
 46 ## (2,1): 8 -> new_grid[2][2] = 8
 47 ##
 48 ## New grid looks after Rule 1:
 49 ##
 50 ## ([?, 1, 2],
 51 ##  [?, 4, 5],
 52 ##  [?, 7, 8],)
 53 ##
 54 ## Rule 2: grid[i][n-1] -> grid[i+1][0] for i < m-1.
 55 ##
 56 ## Elements from original last column (except last row) go to next row's first column.
 57 ##
 58 ## From original:
 59 ##
 60 ## (0,2): 3 -> new_grid[1][0] = 3
 61 ## (1,2): 6 -> new_grid[2][0] = 6
 62 ##
 63 ## Now new grid after Rules 1 + 2:
 64 ##
 65 ## ([?, 1, 2],
 66 ##  [3, 4, 5],
 67 ##  [6, 7, 8],)
 68 ##
 69 ## Rule 3: grid[m-1][n-1] -> grid[0][0].
 70 ##
 71 ## Original (2,2): 9 -> new_grid[0][0] = 9.
 72 ##
 73 ## Now new_grid is complete:
 74 ##
 75 ## ([9, 1, 2],
 76 ##  [3, 4, 5],
 77 ##  [6, 7, 8],)
 78 #
 79 ## Example 2
 80 ##
 81 ## Input: @matrix = ([10, 20],
 82 ##                   [30, 40],)
 83 ##                 $k = 1
 84 ## Output: ([40, 10],
 85 ##          [20, 30],)
 86 ##
 87 ## Rule 1 (move right in same row if not last column):
 88 ##
 89 ## (0,0): 10 -> new[0][1] = 10
 90 ## (1,0): 30 -> new[1][1] = 30
 91 ##
 92 ## After Rule 1:
 93 ##
 94 ## ([?, 10],
 95 ##  [?, 30],)
 96 ##
 97 ## Rule 2 (last col -> next row’s first col, except last row):
 98 ##
 99 ## (0,1): 20 -> new[1][0] = 20
100 ##
101 ## After Rule 2:
102 ##
103 ## ([?,  10],
104 ##  [20, 30],)
105 ##
106 ## Rule 3 (bottom-right to top-left):
107 ##
108 ## (1,1): 40 -> new[0][0] = 40
109 ##
110 ## After Rule 3:
111 ##
112 ## ([40, 10],
113 ##  [20, 30],)
114 #
115 #
116 ## Example 3
117 ##
118 ## Input: @matrix = ([1, 2],
119 ##                   [3, 4],
120 ##                   [5, 6],)
121 ##        $k = 1
122 ## Output: ([6, 1],
123 ##          [2, 3],
124 ##          [4, 5],)
125 ##
126 ## Rule 1:
127 ## (0,0): 1 -> new[0][1] = 1
128 ## (1,0): 3 -> new[1][1] = 3
129 ## (2,0): 5 -> new[2][1] = 5
130 ##
131 ## After Rule 1:
132 ## ( [?, 1],
133 ##   [?, 3],
134 ##   [?, 5],)
135 ##
136 ## Rule 2:
137 ## (0,1): 2 -> new[1][0] = 2
138 ## (1,1): 4 -> new[2][0] = 4
139 ##
140 ## After Rule 2:
141 ## ([?, 1],
142 ##  [2, 3],
143 ##  [4, 5],)
144 ##
145 ##  Rule 3:
146 ##  (2,1): 6 -> new[0][0] = 6
147 ##
148 ##  After Rule 3:
149 ##  ([6, 1],
150 ##   [2, 3],
151 ##   [4, 5],)
152 #
153 #
154 ## Example 4
155 ##
156 ## Input: @matrix = ([1, 2, 3],
157 ##                   [4, 5, 6],)
158 ##        $k = 5
159 ## Output: ([2, 3, 4],
160 ##          [5, 6, 1],)
161 ##
162 ## Shift 1
163 ##
164 ## Rule 1
165 ## 1 -> (0,1)
166 ## 2 -> (0,2)
167 ## 4 -> (1,1)
168 ## 5 -> (1,2)
169 ##
170 ## Rule 2
171 ## 3 -> (1,0) (last column of row 0)
172 ##
173 ## Rule 3
174 ## 6 -> (0,0) (bottom-right corner)
175 ##
176 ## Result
177 ## [6, 1, 2]
178 ## [3, 4, 5]
179 ##
180 ## ----------------------------
181 ##
182 ## Shift 2
183 ##
184 ## Starting from the previous matrix:
185 ##
186 ## [6, 1, 2]
187 ## [3, 4, 5]
188 ##
189 ## Rule 1
190 ## 6 -> (0,1)
191 ## 1 -> (0,2)
192 ## 3 -> (1,1)
193 ## 4 -> (1,2)
194 ##
195 ## Rule 2
196 ## 2 -> (1,0)
197 ##
198 ## Rule 3
199 ## 5 -> (0,0)
200 ##
201 ## Result
202 ## [5, 6, 1]
203 ## [2, 3, 4]
204 ##
205 ## ----------------------------
206 ##
207 ## Shift 3
208 ##
209 ## [5, 6, 1]
210 ## [2, 3, 4]
211 ##
212 ## Rule 2: 1 -> (1,0)
213 ## Rule 3: 4 -> (0,0)
214 ##
215 ## Others follow Rule 1
216 ##
217 ## Result
218 ## [4, 5, 6]
219 ## [1, 2, 3]
220 ##
221 ## ----------------------------
222 ##
223 ## Shift 4
224 ##
225 ## [4, 5, 6]
226 ## [1, 2, 3]
227 ##
228 ## Result
229 ## [3, 4, 5]
230 ## [6, 1, 2]
231 ##
232 ## ----------------------------
233 ##
234 ## Shift 5
235 ## [3, 4, 5]
236 ## [6, 1, 2]
237 ##
238 ## Result
239 ## [2, 3, 4]
240 ## [5, 6, 1]
241 ##
242 ## Final Output (after k = 5 shifts)
243 ## ([2, 3, 4],
244 ##  [5, 6, 1])
245 #
246 #
247 ## Example 5
248 ##
249 ## Input: @matrix = ([1, 2, 3, 4])
250 ##        $k = 1
251 ## Output: ([4, 1, 2, 3])
252 ##
253 ## Rule 1:
254 ## (0,0): 1 -> new[0][1] = 1
255 ## (0,1): 2 -> new[0][2] = 2
256 ## (0,2): 3 -> new[0][3] = 3
257 ##
258 ## After Rule 1:
259 ## ([?, 1, 2, 3])
260 ##
261 ## Rule 2:
262 ## (0,3): 4 -> new[1][0] ??
263 ##
264 ## Wait — but i=0, n-1=3, next row i+1=1 doesn’t exist (m=1).
265 ## So this is actually a special case where Rule 2 should not apply.
266 ## because m=1, so (0,3) goes by Rule 3 actually.
267 ##
268 ## The rules say:
269 ## grid[i][j]     -> grid[i][j+1] for j < n-1.
270 ## grid[i][n-1]   -> grid[i+1][0] for i < m-1.
271 ## grid[m-1][n-1] -> grid[0][0].
272 ##
273 ## For m = 1:
274 ## Elements (0,0),(0,1),(0,2) follow Rule 1 -> (0,1),(0,2),(0,3).
275 ## Element (0,3) is (m-1, n-1), so follows Rule 3 -> (0,0).
276 ##
277 ## Actually, that means after Rule 1:
278 ## We put 1,2,3 in positions 1,2,3, leaving position 0 empty.
279 ## Then Rule 3 puts 4 in position 0.
280 ##
281 ## So final directly:
282 ## [4, 1, 2, 3]
283 #
284 ############################################################
285 ##
286 ## discussion
287 ##
288 ############################################################
289 #
290 # The rules are a complicated way to bascially say "move every
291 # element in the matrix to the right, just handing over the overflow
292 # into the next line unless it's the last line in which case the
293 # overflow goes into the first line". So this whole operation
294 # turns into something pretty straight forward: k times, we just
295 # do this simple operation of moving the last element of the last
296 # array in the matrix to the beginning of the first one, and then
297 # for all array starting in the first and ending in the
298 # second to last one, we just move the last element to the beginning
299 # of the next array.
300 
301 use v5.36;
302 
303 shift_grid([[1, 2, 3], [4, 5, 6], [7, 8, 9]], 1);
304 shift_grid([[10, 20], [30, 40]], 1);
305 shift_grid([[1, 2], [3, 4], [5, 6]], 1);
306 shift_grid([[1, 2, 3], [4, 5, 6]], 5);
307 shift_grid([[1, 2, 3, 4]], 1);
308 
309 sub shift_grid($matrix, $k) {
310     say "Input: \@matrix = [";
311     foreach my $array (@$matrix) {
312         say "            [" . join(", ", @$array) . "],";
313     }
314     say "       ], \$k = $k";
315     foreach my $count (1..$k) {
316         my $last = scalar(@$matrix) - 1;
317         my $elem = pop(@{$matrix->[$last]});
318         unshift @{$matrix->[0]}, $elem;
319         foreach my $line (0..$last-1) {
320             $elem = pop(@{$matrix->[$line]});
321             unshift @{$matrix->[$line+1]}, $elem;
322         }
323     }
324     say "Output: [";
325     foreach my $array (@$matrix) {
326         say "         [" . join(", ", @$array) . "],";
327     }
328     say "        ]";
329 }