Python: 2D to 1D clockwise?
I'm a bit new to Python and I'm looking for a function that converts any n x n 2D list to a 1D list in clockwise direction .
For example:
When n = 3
list = [[2, 3, 5],[ 8, 7, 1],[ 0, 4, 6]]
or
list = [[2, 3, 5] ,[8, 7, 1] ,[0, 4, 6]]
will become
result = [2, 3, 5, 1, 6, 4, 0, 8, 7]
and for n = 5
list = [[2, 3, 5, 9, 10],[ 8, 7, 1, 11, 13],[ 0, 4, 6, 21, 22], [12, 19, 17, 18, 25], [14, 15, 16, 23, 24]]
or
list = [[ 2, 3, 5, 9, 10] ,[ 8, 7, 1, 11, 13] ,[ 0, 4, 6, 21, 22] ,[ 12, 19, 17, 18, 25] , [ 14, 15, 16, 23, 24]]
will become
result = [2, 3, 5, 9, 10, 13, 22, 25, 24, 23, 16, 15, 14, 12, 0, 8, 7, 1, 11, 21, 18, 17, 19, 4, 6]
How can I efficiently do this for any n x n value ?
source to share
Adapted from Printing a two-dimensional array in a spiral order
import itertools
arr = [[2, 3, 5, 9, 10],
[8, 7, 1, 11, 13],
[0, 4, 6, 21, 22],
[12, 19, 17, 18, 25],
[14, 15, 16, 23, 24]]
def transpose_and_yield_top(arr):
while arr:
yield arr[0]
arr = list(zip(*arr[1:]))[::-1]
rotated = list(itertools.chain(*transpose_and_yield_top(arr)))
source to share
This sounds like an exam question - is that ?!
This would be my solution using Python recursion and list manipulation operators:
def clockwise(input_list, output_list):
list_size = len(input_list[0])
if list_size == 1:
output_list.append(input_list[0][0])
else:
for i in range(list_size):
output_list.append(input_list[0][i])
for i in range(list_size)[1:]:
output_list.append(input_list[i][list_size - 1])
for i in reversed(range(list_size)[:-1]):
output_list.append(input_list[list_size - 1][i])
for i in reversed(range(list_size)[1:-1]):
output_list.append(input_list[i][0])
new_list = list()
for i in range(list_size - 2):
new_list.append(input_list[i + 1][1:-1])
return clockwise(new_list, output_list)
l = [[2, 3, 5, 9, 10],[ 8, 7, 1, 11, 13],[ 0, 4, 6, 21, 22], [12, 19, 17, 18, 25], [14, 15, 16, 23, 24]]
output_list = []
clockwise(l, output_list)
print output_list
source to share
This also works:
from math import floor
lists = [[ 2, 3, 5, 9, 10]
,[ 8, 7, 1, 11, 13]
,[ 0, 4, 6, 21, 22]
,[ 12, 19, 17, 18, 25]
, [ 14, 15, 16, 23, 24]]
n = len(lists) # assume each list also has n-length
output_list = []
idx = 0
while idx <= floor(n/2):
if len(output_list) == n*n:
break
# across ->
print("Across ->")
for item in lists[idx][idx:n-idx]:
output_list.append(item)
print(output_list)
if len(output_list) == n*n:
break
# down
print("Down")
for _idx in range(idx+1, n-idx-1):
output_list.append(lists[_idx][n-idx-1])
print(output_list)
if len(output_list) == n*n:
break
# across <-
print("Across <-")
for _idx in range(n-idx-1, idx-1, -1):
output_list.append(lists[n-idx-1][_idx])
print(output_list)
if len(output_list) == n*n:
break
# up
print("Up")
for _idx in range(n-idx-2, idx, -1):
output_list.append(lists[_idx][idx])
print(output_list)
idx += 1
print("\nOutput: ")
print(output_list)
source to share
import math
import numpy as np
def print_wall(input, result):
n = input.shape[0]
for i in range(n): # print top outer
result.append(input[0][i])
for i in range(n - 1): # print right outer
result.append(input[i + 1][n - 1])
for i in range(n - 1): # print bottom outer
result.append(input[n - 1][n - 2 - i])
for i in range(n - 2): # print left outer
result.append(input[n - 2 - i][0])
def clock_wise(input):
n = input.shape[0]
result = list()
for i in range(math.ceil(n / 2)): # from the outer to the inner
print_wall(input[i: n - i, i: n - i], result)
print(result)
This method prints from the outside array to the inside of the array. For example an array:
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
First print the outer 5x5 array in clockwise direction, getting 1 2 3 4 5 10 15 20 25 24 23 22 21 16 11 6;
Then process the internal array (3x3):
7 8 9
12 13 14
17 18 19
print the appearance of the 3x3 array in clockwise direction, getting 7 8 9 14 19 18 17 12;
Finally, consider 13.
source to share