Forming a magic square - python

We define a magic square to be an matrix of distinct positive integers from to where the sum of any row, column, or diagonal of length is always equal to the same number: the magic constant.
You will be given a matrix of integers in the inclusive range . We can convert any digit to any other digit in the range at cost of . Given , convert it into a magic square at minimal cost. Print this cost on a new line.
Note: The resulting magic square must contain distinct integers in the inclusive range .
For example, we start with the following matrix :
5 3 4
1 5 8
6 4 2
We can convert it to the following magic square:
8 3 4
1 5 9
6 7 2
This took three replacements at a cost of .
5-8 + 8-9 + 4-7 = 7
I Have Write a programm to slove this but i get the incorrect result when i try to run it.
def formingMagicSquare(s):
arr=[]
duplicates=[]
totaldifference=0
for i in range(0,len(s)):
linesum=sum(s[i])
for j in range(0,len(s[i])):
if(s[i][j] in arr and linesum!=15):
duplicates.append(i*10+j)
else:
arr.append(s[i][j])
for i in range(0,len(duplicates)):
iarr = duplicates[i]//10
jarr = duplicates[i]%10
linesum=sum(s[i])
difference=15-linesum
totaldifference = totaldifference + difference
return totaldifference
if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
s = []
for _ in range(3):
s.append(list(map(int, input().rstrip().split())))
result = formingMagicSquare(s)
fptr.write(str(result) + '\n')
fptr.close()

class Magic(object):
pre = [
[[8, 1, 6], [3, 5, 7], [4, 9, 2]],
[[6, 1, 8], [7, 5, 3], [2, 9, 4]],
[[4, 9, 2], [3, 5, 7], [8, 1, 6]],
[[2, 9, 4], [7, 5, 3], [6, 1, 8]],
[[8, 3, 4], [1, 5, 9], [6, 7, 2]],
[[4, 3, 8], [9, 5, 1], [2, 7, 6]],
[[6, 7, 2], [1, 5, 9], [8, 3, 4]],
[[2, 7, 6], [9, 5, 1], [4, 3, 8]],
]
def evaluate(self, s):
totals = []
for p in self.pre:
total = 0
for p_row, s_row in zip(p, s):
for i, j in zip(p_row, s_row):
if not i == j:
total += max([i, j]) - min([i, j])
totals.append(total)
return min(totals)
def main():
s=[]
for _ in range(3):
s.append(list(map(int, input().rstrip().split())))
magic = Magic()
result = magic.evaluate(s)
print(result)
if __name__ == '__main__':
main()
Thank You I Have Write A new Code And I Have Change my code from the base.

I think you can easily try:
def forming_magic_square(s):
# Flaten s
s = list(itertools.chain.from_iterable(s))
magic_squares = [
[8, 1, 6, 3, 5, 7, 4, 9, 2],
[6, 1, 8, 7, 5, 3, 2, 9, 4],
[4, 9, 2, 3, 5, 7, 8, 1, 6],
[2, 9, 4, 7, 5, 3, 6, 1, 8],
[8, 3, 4, 1, 5, 9, 6, 7, 2],
[4, 3, 8, 9, 5, 1, 2, 7, 6],
[6, 7, 2, 1, 5, 9, 8, 3, 4],
[2, 7, 6, 9, 5, 1, 4, 3, 8],
]
costs = []
for magic_square in magic_squares:
costs.append(sum([abs(magic_square[i] - s[i]) for i in range(9)]))
return min(costs)

Related

Splitting list of elements without numpy array function [duplicate]

This question already has answers here:
How do I split a list into equally-sized chunks?
(66 answers)
Closed 1 year ago.
Example: I have a list:
[8, 3, 4, 1, 5, 9, 6, 7, 2]
And I need to make it look like this but without using numpy.array_split():
[[8, 3, 4], [1, 5, 9], [6, 7, 2]]
How can I do it? Not only for this one case, but when I have 4 elements, I want to have 2 and 2, (9 - 3,3,3 and 16 - 4,4,4,4) etc.
You can get the square root of the list's length then split it using a list comprehension. This will work for lists with the length of 4, 9, 16, ...:
lst = [8, 3, 4, 1, 5, 9, 6, 7, 2]
lst2 = [8, 3, 4, 1]
def split_equal(lst):
len_ = len(lst)
# returns emtpy list, if the list has no item.
if len_ == 0:
return []
n = int(len_ ** 0.5)
return [lst[i:i + n] for i in range(0, len_, n)]
output:
[[8, 3, 4], [1, 5, 9], [6, 7, 2]]
[[8, 3], [4, 1]]
You can use that:
def splitter(inlist):
n = len(inlist)
m = int(n ** 0.5)
if m*m != n:
raise Exception("")
return [[inlist[i+j] for j in range(m)] for i in range(m)]
print(splitter([8, 3, 4, 1]))
print(splitter([8, 3, 4, 1, 5, 9, 6, 7, 2]))
print(splitter([8, 3, 4, 1, 5, 9, 6, 7, 2, 8, 3, 4, 1, 5, 9, 6]))
Result:
[[8, 3], [3, 4]]
[[8, 3, 4], [3, 4, 1], [4, 1, 5]]
[[8, 3, 4, 1], [3, 4, 1, 5], [4, 1, 5, 9], [1, 5, 9, 6]]
Carefull, it will crash if the square of the len of input list is not integer.
def equal_array_split(arr, split_arr_len):
array_length = len(arr)
if array_length % split_arr_len == 0:
return [arr[i:i+split_arr_len] for i in range(0,array_length,split_arr_len)]
else:
return "Invalid split array length!!"
print(equal_array_split([1,2,3,4,5,6,7,8,9],3))
print(equal_array_split([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],4))
print(equal_array_split([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],8))
print(equal_array_split([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],2))
Output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
[[1, 2, 3, 4, 5, 6, 7, 8], [9, 10, 11, 12, 13, 14, 15, 16]]
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14], [15, 16]]
You can slice the list with a list comprehension. Assuming the input is a square number length:
import numpy as np
arr = [8, 3, 4, 1, 5, 9, 6, 7, 2]
n = int(np.sqrt(len(arr)))
result = [arr[i*n:(i+1)*n] for i in range(int(n))]
the split value being a square
list = [8, 3, 4, 1, 5, 9, 6, 7, 2]
result = []
N = split_value #split_value being the value required to split the list
for i in range(0,len(list),N):
result.append(list[i:i+N])
print(result)
Whitout numpy....
a = [8, 3, 4, 1, 5, 9, 6, 7, 2]
splitedSize = 3
a_splited = [a[x:x+splitedSize] for x in range(0, len(a), splitedSize)]
print(a_splited)

How to create a recursive separator?

I am trying to learn recursion and am separating odd and even values in two lists and merging them to another list as below:
Code:
def separateNumbers(L):
evenList = []
oddList = []
main = []
if len(L)==0:
return L
if L[0] % 2 == 0:
evenList.append(L[0])
separateNumbers(L[1:])
if L[0] % 2 == 1:
oddList.append(L[0])
separateNumbers(L[1:])
main.append(evenList)
main.append(oddList)
return main
inputList = [1,2,3,4,5,6,7,8,9,10]
L = separateNumbers(inputList)
print(L)
Input:
L = [1,2,3,4,5,6]
Output:
[[1,3,5], [2,4,6]]
The even and odd arrays reset everytime the recursive function is called, how can I fix this?
Tried with inner function:
def separateNumbers(L):
evenList = []
oddList = []
main = []
def inner(L):
if len(L)==0:
return L
if L[0] % 2 == 0:
evenList.append(L[0])
inner(L[1:])
if L[0] % 2 == 1:
oddList.append(L[0])
inner(L[1:])
main.append(evenList)
main.append(oddList)
return main
a = inner(L)
return a
Output:
[[2, 4, 6, 8, 10], [1, 3, 5, 7, 9], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9], [2, 4, 6, 8,
10], [1, 3, 5, 7, 9], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]
You don't need a nested function. try:
def separate_numbers(lst):
if not lst: # empty list
return [], []
odd, even = separate_numbers(lst[1:]) # recursion call
if lst[0] % 2: # if the first item is odd
return [lst[0], *odd], even
else: # if even
return odd, [lst[0], *even]
lst = [1,2,3,4,5,6,7,8,9,10]
print(separate_numbers(lst)) # ([1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
The function calls itself using the tail part of the input list, receiving two lists: odd for odd numbers and even for even numbers. Then it returns those lists, after attaching the head element lst[0] to one of the lists.

How do I improve the run time to receive the training samples?

I have the following problems the following code snippet is correct only this one is slow. For example, I need 10 minutes to go through this. However, I don't know how to speed it up. Does somebody has any idea?
#Dataframe:
list_l = [[0, 3, 8, 0], [0, 8, 7, 0], [0, 2, 9, 0], [1, 10, 10, 1], [2, 3, 8, 2], [2, 10, 10, 2], [3, 4, 12, 3], [3, 12, 4, 3], [3, 3, 8, 3], [4, 12, 4, 4], [4, 3, 8, 4], [4, 4, 12, 4], [5, 8, 7, 5], [5, 6, 13, 5], [5, 3, 8, 5], [6, 0, 3, 6], [6, 5, 11, 6], [6, 12, 4, 6], [7, 9, 6, 7], [7, 9, 6, 7], [8, 13, 5, 8], [9, 1, 0, 9], [9, 7, 2, 9], [9, 11, 1, 9], [9, 11, 1, 9]]
# Note: location isn't relevant
df = DataFrame (list_l ,columns=['buyerid','itemid', 'group', 'location'])
#train_mat:
# trainmat
# How have to generate train_mat by yourself
# df_main = complete dataframe, data = splitted dataframe (complete dataframe is also ok)
def generate_matrix(df_main,data):
num_users = df_main["buyerid"].nunique()
num_items = df_main["itemid"].nunique()
print(num_users)
print(num_items)
mat = sp.dok_matrix((num_users, num_items), dtype=np.float32)
for buyerid, itemidin zip(data['buyerid'], data['itemid']):
mat[buyerid, itemid] = 1.0
print(mat)
return mat
#num_negatives:
# num_negatives = 4
Code:
# allData = complete Dataframe, train_mat = one hot encoding matrix, num_negatives = integer
def get_train_samples(allData, train_mat, num_negatives):
user_input, item_input, labels = [], [], []
num_user, num_item = train_mat.shape
for (u, i) in train_mat.keys():
user_input.append(u)
item_input.append(i)
labels.append(1)
# negative instances
for t in range(num_negatives):
j = np.random.randint(num_item)
if allData.loc[(allData['buyerid'] == u)&(allData['itemid'] == i)].empty:
j = np.random.randint(num_item)
user_input.append(u)
item_input.append(j)
labels.append(0)
return user_input, item_input, labels
some things to improve here:
for t in range(num_negatives):
j = np.random.randint(num_item)
if allData.loc[(allData['buyerid'] == u)&(allData['itemid'] == i)].empty:
j = np.random.randint(num_item)
you essentially say "j is a random number, if some stuff is true, set j to a random number". Isn't that just "j is a random number" with extra steps?
I'd say this does the same but faster
for t in range(num_negatives):
j = np.random.randint(num_item)
edit: removing brain fart

How can I make this triple Sudoku for loop work

I am having some trouble with this algorithm. I am only able to grab one sub grid. I've only included the sub grid part here as I've done checkRows and checkColumns on my own. How can I connect this code to capture the rest? Your help is greatly appreciated. Thanks.
class Sudoku_Checker:
def __init__(self,board):
self.board = board
def board_validater(self,board):
self.checkSquares(board)
return self.checkSquares(board) == True
def checkSquares(self,board):
compare = [1,2,3,4,5,6,7,8,9]
hold = []
row = 0
column = 0
square = 0
for p in range(square, square+3):
for i in range(row, row + 3):
for j in range(column, column + 3):
hold.append(board[i][j])
if len(hold)==9:
if sorted(hold) == compare:
hold =[]
continue
else:
return False
square +=3
row += 3
return True
board = [ [5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 0],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9]]
s = Sudoku_Checker(board)
s.board_validater(board)
So in my exemple with line and column variable i get the upper left corner of eaxh 3x3 matrix and then i iterate from there to construct the square.
Please let me know if this is what you are looking for.
board = [
[5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 0],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9]
]
for line in range(0, 9, 3):
for column in range(0, 9, 3):
square = [[board[l][c] for c in range(column, column + 3)] for l in range(line, line + 3)]
print(square)
Result:
[[5, 3, 4], [6, 7, 2], [1, 9, 8]]
[[6, 7, 8], [1, 9, 5], [3, 4, 2]]
[[9, 1, 2], [3, 4, 8], [5, 6, 0]]
[[8, 5, 9], [4, 2, 6], [7, 1, 3]]
[[7, 6, 1], [8, 5, 3], [9, 2, 4]]
[[4, 2, 3], [7, 9, 1], [8, 5, 6]]
[[9, 6, 1], [2, 8, 7], [3, 4, 5]]
[[5, 3, 7], [4, 1, 9], [2, 8, 6]]
[[2, 8, 4], [6, 3, 5], [1, 7, 9]]
Hopefully someone finds this useful. I prefer this implementation because it is more readable and understandable to me. The other commentor also has a good solution except for the list comprehension which is too much of a loop.
class Sudoku_Checker:
def __init__(self,board):
self.board = board
def board_validater(self,board):
return self.checkSquares(board) == True
def checkSquares(self,board):
compare = range(1,10)
for i in range(0, 9, 3):
for j in range(0, 9, 3):
nums = board[i][j:j+3] + board[i+1][j:j+3] + board[i+2][j:j+3]
if sorted(nums) == compare:
continue
else:
return False
return True
board = [ [5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 0],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9]]
s = Sudoku_Checker(board)
s.board_validater(board)

How to make a random sample of chunk in an array/list (with replacement) instead of sampling the individual elements in the list list with python

I able to split a list into array of chunks from a list as demonstrated in the bellow python code:
def split_list(the_list, chunk_size):
result_list = []
while the_list:
result_list.append(the_list[:chunk_size])
the_list = the_list[chunk_size:]
return result_list
a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print split_list(a_list, 3)
which yield the bellow result of array of chunks:
# [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
I am also aware of making a random sample through numpy.random.choice (even with replacement) as demonstrated bellow:
import numpy as np
a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
np.random.choice(a_list, size=20,
replace=True)
which yields the bellow result:
#array([ 6, 9, 4, 9, 1, 1, 6, 10, 8, 5, 10, 6, 2, 6, 7, 1, 3,
2, 7, 6])
What I want
I want to sample chunk in the array (while the elements of each chunk is left as it is) with replacement.
I am looking forward to get a code that will produce something like this:
# [[7, 8, 9], [1, 2, 3], [4, 5, 6], [7, 8, 9], [10], [1, 2, 3], [1, 2, 3], [10], [1, 2, 3], [7, 8, 9], [1, 2, 3], [1, 2, 3], [10], [4, 5, 6], [4, 5, 6], [10], [10], [7, 8, 9],, [1, 2, 3], [7, 8, 9]]
I picked the above sample of chunk myself, I need help to get a working python code to do that for me.
You can determine the number of different chunks in your list (4 in your example), then randomly choose the index of the one you want (between 0 and 3 in your example).
So, you could do:
import math
import random
def random_chunk(lst, chunk_size):
nb_chunks = int(math.ceil(len(lst)/chunk_size))
choice = random.randrange(nb_chunks) # 0 <= choice < nb_chunks
return lst[choice*chunk_size:(choice+1)*chunk_size]
a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
out = [random_chunk(a_list, chunk_size=3) for _ in range(20)]
print(out)
# [[10], [7, 8, 9], [4, 5, 6], [4, 5, 6], [1, 2, 3], [7, 8, 9], [7, 8, 9], [4, 5, 6],
# [10], [7, 8, 9], [10], [10], [10], [7, 8, 9], [10], [10], [10], [4, 5, 6], [4, 5, 6], [10]]

Categories