Append every three elements in sublist to dictionary - python

Say I have a list containing lists.
board = [[5, 3, 0, 0, 7, 0, 1, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]]
I want to append every three numbers in each sublist to a key in a dictionary.
For example
dd = {1:[5, 3, 0,6, 0, 0,0, 9, 8]}
Then I'll look for the next 3x3 section.
dd = {2:[0,7,0,1,9,5,0,0,0]}
In total I should have 9 keys each with a list of 9 elements.
This clearly doesn't work XD:
board = [[5, 3, 0, 0, 7, 0, 1, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]]
xBx = {}
count1 = 1
count2 = 3
count3 = 0
for row in board:
if count1 == 4:
count = 1
xBx[count1] = row[count3:count2]
count1 += 1
count2 += 3
count3 += 3
print(xBx)

Using numpy, it's easier to slice a multi-dimensional array
import numpy as np
board = np.array(board)
result = {}
for i in range(len(board) // size):
for j in range(len(board) // size):
values = board[j * size:(j + 1) * size, i * size:(i + 1) * size]
result[i * size + j + 1] = values.flatten()
And result gives
{
1: array([5, 3, 0, 6, 0, 0, 0, 9, 8]),
2: array([8, 0, 0, 4, 0, 0, 7, 0, 0]),
3: array([0, 6, 0, 0, 0, 0, 0, 0, 0]),
4: array([0, 7, 0, 1, 9, 5, 0, 0, 0]),
5: array([0, 6, 0, 8, 0, 3, 0, 2, 0]),
6: array([0, 0, 0, 4, 1, 9, 0, 8, 0]),
7: array([1, 0, 0, 0, 0, 0, 0, 6, 0]),
8: array([0, 0, 3, 0, 0, 1, 0, 0, 6]),
9: array([2, 8, 0, 0, 0, 5, 0, 7, 9])
}

This should work:
board = [[5, 3, 0, 0, 7, 0, 1, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]]
d = {}
for i in range(len(board[0]) // 3):
for l in board:
if i + 1 in d.keys():
d[i + 1].append(l[0 + i*3])
d[i + 1].append(l[1 + i*3])
d[i + 1].append(l[2 + i*3])
else:
d[i + 1] = []
d[i + 1].append(l[0 + i*3])
d[i + 1].append(l[1 + i*3])
d[i + 1].append(l[2 + i*3])
for key, value in d.items():
print(f"{key} {value}")

This is what you are probably looking for
size = 3
l = len(board)
dict = {}
dictIndex = 1
for x in range(0, l, size):
for y in range(0, l, size):
a = []
for i in range(x, x + size):
for j in range(y, y + size):
a.append(board[i][j])
dict[dictIndex] = a
dictIndex += 1
print(dict)
Shorter variant
size, l, dict, dictIndex = 3, len(board), {}, 1
for x in range(0, l, size):
for y in range(0, l, size):
dict[dictIndex], dictIndex = [board[i][j] for i in range(x, x + size) for j in range(y, y + size)], dictIndex + 1
print(dict)

Related

How to split a list into sublists of 6 zeros in a row and other values

This is the list that I have:
a = [0, 0, 0, 0, 0, 0, 1, 1, 4, 5, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 3, 4]
I would like to split the list into sublists of 6 zeros in a row and other values to have the desired output of
a = [[0, 0, 0, 0, 0, 0], [1, 1, 4, 5, 0, 0, 4], [0, 0, 0, 0, 0, 0], [1, 3, 4]]
I tried to convert list to string to use split function and then convert string back to list
b = ''.join(map(str,a))
c = b.split('0'*6)
d = list(map(int, c))
and ended up with invalid literal for int() with base 10: '' error message.
Is this the right way to do it? or is there a different way that doesnt involve switching between list and string to avoid such error message?
The following is a quite crude way of doing it:
a = [0, 0, 0, 0, 0, 0, 1, 1, 4, 5, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 3, 4]
output, temp = [], []
while a:
if a[:6] == [0] * 6:
if temp:
output.append(temp)
temp = []
output.append([0] * 6)
a = a[6:]
else:
temp.append(a[0])
a = a[1:]
else:
if temp:
output.append(temp)
print(output)
# [[0, 0, 0, 0, 0, 0], [1, 1, 4, 5, 0, 0, 4], [0, 0, 0, 0, 0, 0], [1, 3, 4]]
This will deplete the original list a.
One way to do this is to make a generator that keeps track of the seen zeros so far and seen numbers so far. When you get six zeros, you yield it and any previous numbers. Otherwise move the zeros to the other list.
a = [0, 0, 0, 0, 0, 0, 1, 1, 4, 5, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 3, 4]
def six_zeros(l):
z = []
nums = []
for n in l:
if n != 0:
nums.extend(z) # add zeros seen so far
nums.append(n) # append the number
z = []
else:
z.append(n) # append the zero
if len(z) == 6: # but you've seen 6 yield them
if nums:
yield nums
yield z
nums = []
z = []
if nums or z: # don't forget any left-overs
nums.extend(z)
yield nums
list(six_zeros(a))
# [[0, 0, 0, 0, 0, 0], [1, 1, 4, 5, 0, 0, 4], [0, 0, 0, 0, 0, 0], [1, 3, 4]]
I think this might be a simpler way:
a = [0, 0, 0, 0, 0, 0, 1, 1, 4, 5, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 3, 4]
six_zeros = [0]*6
b, temp = [], []
for x in a:
temp.append(x)
temp_len = len(temp)
if temp_len >= 6 and temp[-6:] == six_zeros:
if temp_len > 6:
b.append(temp[:-6])
b.append(six_zeros)
temp.clear()
if temp:
b.append(temp)
print(b)
Output:
[[0, 0, 0, 0, 0, 0], [1, 1, 4, 5, 0, 0, 4], [0, 0, 0, 0, 0, 0], [1, 3, 4]]
Here's a working version of your attempt:
import re
a = [0, 0, 0, 0, 0, 0, 1, 1, 4, 5, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 3, 4]
b = ''.join(map(str, a))
c = re.split(f"({'0'*6})", b)
d = [list(map(int, g)) for g in c if g]
print(d)
Output as desired:
[[0, 0, 0, 0, 0, 0], [1, 1, 4, 5, 0, 0, 4], [0, 0, 0, 0, 0, 0], [1, 3, 4]]
I used re.split because that includes the splitters when asked to.

Change zeros into their closest left nonzero neighbors in an array

Assuming I have an array :
[1, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 2]
How can I change the zeros into the value of its closest left non-zero neighbor?
[1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 1, 1, 1, 1, 2]
l=[1, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 2]
arr=[]
for i in l:
if i!=0:
arr.append(i)
left_element=i
else:
arr.append(left_element)
print(arr)
keep track of non zero left element and append it to the new list
Space:-O(n)
runtime:-O(n)
OR
l=[1, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 2]
for i in range(len(l)):
if l[i]!=0:
left_element=l[i]
else:
l[i]=left_element
print(l)
I would iterate through your array and evaluate each item, replacing when necessary:
arr = [1, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 2]
# replace values with the following
previous_x = None
for i,x in enumerate(arr):
if x>0:
previous_x = x
else:
arr[i] = previous_x
If your array is massive (>100,000), I would look into leveraging numpy for a solution.

how do I ask for sudoku board input in python 3.X? ,I've made a sudoku solver program but it just works for the board that I declared

myBoard = [[0, 4, 0, 7, 0, 0, 1, 3, 0],
[0, 0, 2, 0, 0, 0, 6, 0, 0],
[0, 0, 0, 4, 2, 0, 0, 0, 0],
[6, 0, 0, 0, 0, 2, 0, 0, 3],
[2, 3, 1, 0, 7, 0, 0, 8, 0],
[4, 0, 0, 3, 1, 0, 0, 0, 0],
[0, 7, 0, 0, 0, 8, 0, 0, 0],
[0, 0, 6, 0, 3, 0, 0, 0, 4],
[8, 9, 0, 0, 5, 0, 0, 0, 6]]
how to get this like an input from the user
Try this.
myBoard = []
rows = 9
for x in range(rows):
line = input().split(',')
myBoard.append(line)
Or you can use list comprehension
rows = 9
myBoard = [input().split(',') for x in range(rows)]
You can take comma separated input like this
0,4,0,7,0,0,1,3,0
0,0,2,0,0,0,6,0,0
0,0,0,4,2,0,0,0,0
6,0,0,0,0,2,0,0,3
2,3,1,0,7,0,0,8,0
4,0,0,3,1,0,0,0,0
0,7,0,0,0,8,0,0,0
0,0,6,0,3,0,0,0,4
8,9,0,0,5,0,0,0,6

how to do padding a nested list

I have a nested list that contains 1002 time steps and in each time step, I have observation of 11 features. I have read docs related to padding but I really could not find out how to add zero elements at the end of each list. I found out the highest length of lists is for example the 24th item in my main list and now I want to pad all the rest elements based on this unless the 24th element that already in shape.As an example:
a = [[1,2,3,4,5,6,76,7],[2,2,3,4,2,5,5,5,,7,8,9,33,677,8,8,9,9],[2,3,46,7,8,9,],[3,3,3,5],[2,2],[1,1],[2,2]]
a[1] = padding(a[1],len(a[2]) with zeros at the end of the list)
I have done below:
import numpy as np
def pad_or_truncate(some_list, target_len):
return some_list[:target_len] + [0]*(target_len - len(some_list))
for i in range(len(Length)):
pad_or_truncate(Length[i],len(Length[24]))
print(len(Length[i]))
or
for i in range(len(Length)):
df_train_array = np.pad(Length[i],len(Length[24]),mode='constant')
and I got this error: Unable to coerce to Series, length must be 11: given 375
Solution 1
# set the max number of 0
max_len = max([len(x) for x in a])
# add zeros to the lists
temp = [x+ [0]*max_len for x in a]
#Limit the output to the wished length
[x[0:max_len] for x in temp]
Solution 2 using pandas
import pandas as pd
df = pd.DataFrame(a)
df.fillna(0).astype(int).values.tolist()
Output
[[1, 2, 3, 4, 5, 6, 76, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[2, 2, 3, 4, 2, 5, 5, 5, 7, 8, 9, 33, 677, 8, 8, 9, 9],
[2, 3, 46, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[3, 3, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
...]
The following code snippet should pad the individual lists with the appropriate number of 0s(driven by the size of the list with the maximum elements)
def main():
data = [
[1,2,3,4,5,6,76,7],
[2,2,3,4,2,5,5,5,7,8,9,33,677,8,8,9,9],
[2,3,46,7,8,9,],
[3,3,3,5],
[2,2],
[1,1],
[2,2]
]
# find the list with the maximum elements
max_length = max(map(len, data))
for element in data:
for _ in range(len(element), max_length):
element.append(0)
if __name__ == '__main__':
main()
You can use this simple line, which uses np.pad
list(map(lambda x: np.pad(x, (max(map(len, a)) - len(x), 0)).tolist(), a))
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 76, 7],
[2, 2, 3, 4, 2, 5, 5, 5, 7, 8, 9, 33, 677, 8, 8, 9, 9],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 46, 7, 8, 9],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 5],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2]]
Use this if you want to pad at the end instead:
list(map(lambda x: np.pad(x, (0, max(map(len, a)) - len(x))).tolist(), a))

How to return numpy.array object from a function?

This program uses backtracking to solve sudoku. The input matrix is a numpy.array object.
Program:
import numpy as np
sudoku_matrix = np.array([[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]])
number_list = [x for x in range(1, 10)]
def possible_number(a, b, number):
x1, y1 = (a // 3) * 3, (b // 3) * 3
flag = False
sub_array = sudoku_matrix[x1:(x1 + 3), y1:(y1 + 3)]
if number not in sudoku_matrix[a]:
if number not in sudoku_matrix[:, [b]]:
for x in sub_array:
if number in x:
flag = True
break
if flag == False:
return True
return False
def solver():
for a in range(0, 9):
for b in range(0, 9):
if sudoku_matrix[a][b] == 0:
for number in number_list:
if possible_number(a, b, number):
sudoku_matrix[a][b] = number
solver()
sudoku_matrix[a][b] = 0
return
return sudoku_matrix
# print(sudoku_matrix)
if __name__ == '__main__':
print(solver())
If you print the result in the solver(), it successfully prints to stdout, but when you return sudoku_matrix, it returns None. What am I doing wrong.

Categories