Python class returning old value of attribute - python

I have a main class, a second class that handles getting a sudoku grid (2D array), and a third class that solves the puzzle and is supposed to return a completed puzzle. When I run the program, the solve method works fine and prints out the solved puzzle. However, when I call SudokuSolver.get_grid() from another class, the original, unsolved grid that was passed into SudokuSolver is being returned. Also, when I tried to return self.grid from the solve() method, it always returns [[None]].
Here is my solver class:
import numpy as np
class SudokuSolver:
def __init__(self, in_grid):
self.grid = in_grid
def get_grid(self):
return self.grid
def solve(self):
for y in range(9):
for x in range(9):
if self.grid[y][x] == 0:
for n in range(1, 10):
if self.possible(y, x, n):
self.grid[y][x] = n
self.solve()
self.grid[y][x] = 0
return
print('Solved')
print(np.matrix(self.grid))
def possible(self, y, x, n):
for i in range(0, 9):
if self.grid[y][i] == n:
return False
for i in range(0, 9):
if self.grid[i][x] == n:
return False
x0 = (x//3) * 3
y0 = (y//3) * 3
for i in range(0, 3):
for j in range(0, 3):
if self.grid[y0 + i][x0 + j] == n:
return False
return True
Second Class:
solver = SudokuSolver(self.get_grid())
solver.solve()
completed = solver.get_grid()
print('Completed')
print(np.matrix(completed))
Why is SudokuSolver returning the old grid value that was passed in, and not the completed one printed at the end of the solve() method?

This line:
self.grid[y][x] = 0
is getting called repeatedly after the solution is complete. To verify, put any print statement immediately before or after it. You'll see that its output will appear both before and after your "Solved" output.
I am not well-versed in Sudoku theory, but this simple fix worked for me. Initialize a solved attribute in the initializer:
self.solved = False
When you know you're done, set it to True:
print('Solved')
print(np.matrix(self.grid))
self.solved = True
And then nest the zeroing code in a conditional:
if not self.solved:
self.grid[y][x] = 0
Now that command will be skipped if your puzzle is already solved. There may be a more elegant way to implement the algorithm, but this fixes the functionality of your code.
(Note that as pointed out in Ian Wilson's answer, in your current code, solver.grid and the containing class's self.grid are one and the same, so the solver is actively changing the original grid supplied to it. This may or may not be what you intended.)

Since python passes lists by reference, you are passing a reference to the old solver's grid. You need to initialize your solver with a copy of the other grid like this:
import copy
class OtherClass():
def start_solver(self):
grid_copy = copy.deepcopy(self.get_grid())
solver = SudokuSolver(grid_copy)
#...
Because you have a list of lists, you have to use deep copy. If it was just a single level list you could use grid.copy() or grid[:] to do a shallow copy.
It might be a good idea to move the copy operation into the constructor of the solver or into get_grid().
deep copy
pass by reference

Related

is there any way to write a function such that when call it save the passing data

Is it possible to write a function such that in every call it save data; for example- the following function takes two arguments x & y; where x is a data and y is the array size.
Call the function first time, it would create y dimensional array, fill the first position with x value and in the second call it would fill the 2nd position of the array and continue and it will return a average when at least 2 values are in that array. The array size would be fixed, if call the function more than y times, it will delete first data (FIFO).
def storedata(x,y):
return z
you can use global variables to keep your data in them and call them between your functions.
check out this page: What is the pythonic way of saving data between function calls? maybe solve your problem if you want to use the class and attribute solution.
You should use a class when you want to store data.
An small example is given below, but please look online for tutorial and examples to fully understand the working of classes and OOP in python.
class Storedata:
def __init__(self, x, y):
self.arr = []
self.max_arr_size = y
self.add_data(x)
def add_data(self, x):
if len(self.arr) < self.max_arr_size:
self.arr.append(x)
def __call__(self):
return sum(self.arr)/len(self.arr)
storedata = Storedata(3, 5)
print(storedata.arr)
>>> [3]
print( storedata() )
>>> 3.0
storedata.add_data(5)
print( storedata() )
>>> 4.0
Thanks everyone for the solutions. Using a class is a good way but I think I was looking for the following code.
def storedata(x, y):
if not hasattr(storedata, 'z'):
storedata.z = np.zeros(y, dtype=float)
storedata.z = np.roll(storedata.z, 1)
storedata.z[0] = x
storedata.z[storedata.z == 0] = np.nan
return storedata.z, np.nanmean(storedata.z)
for i in range(1, 11):
print(storedata(x=i, y=10))

Why recursive function is considering last element in an array twice?

Trying to understand recursive functions and so created this program but the output is incorrect. Would like to understand what am I doing wrong here
class Recursive:
def __init__(self, arr):
self.arr = arr
self.sum = 0
def sumRecursive(self):
if len(self.arr) == 0:
return self.sum
self.sum = self.arr.pop(0)
return self.sum + self.sumRecursive()
def main():
recur = Recursive([1,2,3])
print(recur.sumRecursive())
main()
output: 9
There are two types of recursion to consider: tail recursion, where the return value of a single recursive call is returned as-is, and "regular" recursion, where you do something with the return value(s) of the recursive call(s) before returning yourself.
You are combining the two. You either add a value from the list to the recursive sum, using no accumulator:
def non_tail_recursive(self):
if len(self.arr) == 0:
return 0
return self.arr.pop(0) + self.non_tail_recursive()
or you use an accumulator:
def tail_recursive(self):
if len(self.arr) == 0:
return self.sum
self.sum += self.arr.pop(0)
return self.tail_recursive()
You don't usually use an object with state to implement recursion. If you're keeping state, then you often don't need a recursive solution at all.
Here's how to do a "stateless" recursive sum.
def sumRecursive(arr):
if not arr:
return 0
return arr[0] + sumRecursive(arr[1:])
def main():
print(sumRecursive([1,2,3]))
main()
Your self.sum attribute is redundant. The information being processed by a recursive algorithm rarely needs members to pass information along.
class Recursive:
def __init__(self, arr):
self.arr = arr
def sumRecursive(self):
if not len(self.arr):
return 0
return self.arr.pop(0) + self.sumRecursive()
def main():
recur = Recursive([1,2,3])
print(recur.sumRecursive())
main()
Output: 6
To answer your question without rewriting your code (since obviously there are better ways to sum arrays), the answer is that the last leg of your recursion calls self.sum + self.sumRecursive which hits your sumRecursive function one last time which returns (from your if statement) self.sum which is the last element in your list (which you already summed).
Instead when the array is empty, return 0.
class Recursive:
def __init__(self, arr):
self.arr = arr
self.sum = 0
def sumRecursive(self):
if len(self.arr) == 0:
return 0
self.sum = self.arr.pop(0)
return self.sum + self.sumRecursive()
def main():
recur = Recursive([1,2,3,4])
print(recur.sumRecursive())
main()
Optionally move your if to the bottom where I personally think it makes more sense:
def sumRecursive(self):
self.sum = self.arr.pop(0)
if len(self.arr) == 0:
return self.sum
else:
return self.sum + self.sumRecursive()
fundamentals
You are making this more challenging for yourself because you are tangling your sum function with the class. The sum function simply needs to work on a list but the context of your object, self, is making it hard for you to focus.
Recursion is a functional heritage and this means writing your code in a functional and modular way. It's easier to read/write small, single-purpose functions and it promotes reuse within other areas of your program. Next time you need to sum a list in another class, do you want to rewrite sumRecursive again?
Write your summing function once and then import it where it's needed -
# mymath.py
def mysum(t):
if not t:
return 0
else:
return t.pop() + mysum(t)
See how mysum has no concern for context, self? Why should it? All it does it sum the elements of a list.
Now write your recursive module -
# recursive.py
from mymath import mysum
class Recursive:
def __init__(self, arr): self.arr = arr
def sum(self): return mysum(self.arr)
See how Recursive.sum just hands off self.arr to mysum? It doesn't have to be more complicated than that. mysum will work on every list, not just lists within your Recursive module. We don't have to know how mysum works, that is the concern of the mymath module.
Now we write the main module. Each module represents a barrier of abstraction. This means that the details of a module shouldn't spill over into other modules. We don't know how Recursive actually sums the input, and from the caller's point of view, we don't care. That is the concern of Recursive module.
# main.py
from recursive import Recursive
recur = Recursive([1,2,3])
print(recur.sum())
6
going functional
Above we wrote mysum using the .pop technique in your question. I did this because that seems to be how you are understanding the problem right now. But watch what happens when we do this -
x = [1,2,3]
print(mysum(x)) # 6
print(mysum(x)) # 0
Why does the mysum return a different answer the second time? Because as it is written now, mysum uses t.pop(), which mutates t. When mysum is finished running, t is completely emptied!
By why would we write our function like this? What if 5 + x returned a different result each time we called it?
x = 3
print(5 + x) # 8
print(5 + x) # 8
How annoying it would be if we could not depend on values not to change. The sum of the input, [1,2,3], is 6. But as it is written, the sum of the input is to return 6 and empty the input. This second part of emptying (changing) the input is known as a side effect. Ie, the desired effect is to sum and emptying of the input list is unintended but a consequence of us using .pop to calculate the result. This is not the functional way. Functional style means avoiding mutations, variable reassignments, and other side effects.
def mysum(t):
if not t:
return 0
else:
return t[0] + mysum(t[1:])
When written in this way, t, is not changed. This allows us to use equational reasoning whereby we can substitute any function call for its return value and always get the correct answer
x = [1,2,3]
mysum(x)
== 1 + mysum([2,3])
== 1 + 2 + mysum([3])
== 1 + 2 + 3 + mysum([])
== 1 + 2 + 3 + 0
== 1 + 2 + 3
== 1 + 5
== 6
And x was not changed as a result of running mysum -
print(x)
# [1,2,3]
Note, the Recursive module does not need to make any change to receive the benefit of rewriting mysum in this way. Before the change, we would've seen this behavior -
# main.py
from recursive import Recursive
recur = Recursive([1,2,3])
print(recur.sum())
print(recur.sum())
6
0
Because the first call to sum passes self.arr to mysum which empties self.arr as a side effect. A second call to recur.sum() will sum an empty self.arr! After fixing mysum we get the intended behaviour -
# main.py
from recursive import Recursive
recur = Recursive([1,2,3])
print(recur.sum())
print(recur.sum())
6
6
additional reading
I've written extensively about the techniques used in this answer. Follow the links to see them used in other contexts with additional explanation provided -
I want to reverse the stack but i dont know how to use recursion for reversing this… How can i reverse the stack without using Recursion
Finding all maze solutions with Python
Return middle node of linked list with recursion
How do i recursively find a size of subtree based on any given node? (BST)
Deleting node in BST Python

Appending values to a Python member variable

I am new to Python and OO programming in general and so please forgive the, probably, very poorly designed code (any tips would be greatly appreciated).
In this, contrived, MWE which is purely to illustrate a similar problem in my larger project. I want to iterate through a 3x3 grid and fill it, so that it contains all the digits 1-9, the only values I can change are ones which are currently set a 0. i.e. If the grid currently has the digits 1-7 and two positions are 0 then one of these 0s becomes an 8 and one becomes a 9, in this instance there are two solutions since the order of the 8 and 9 can also be swapped.
I have designed a backtracking solver (runSolver()) and it does solve this problem, what I am struggling to do though is store the solutions when I reach them. I have added a print statement for when a solution is reached and this prints out the solution as expected, I then try to append this solution to a list and instead of appending the solution that has just been found it instead appends the initial, unsolved, grid.
class Grid:
def __init__(self):
self.grid = np.zeros((3, 3))
def writeGrid(self, grid):
self.grid = grid
def printGrid(self):
print(self.grid)
def getValue(self, col, row):
return self.grid[row][col]
def setValue(self, col, row, num):
self.grid[row][col] = num
class Solver:
def __init__(self, grid):
self.grid = grid
self.solutions = []
self.n_solutions = 0
def isValid(self, num):
for i in range(3):
for j in range(3):
if self.grid.getValue(i, j) == num:
return False
return True
def runSolver(self):
for row in range(3):
for col in range(3):
if (self.grid.getValue(col, row)) == 0:
for num in range(1,10):
if self.isValid(num):
self.grid.setValue(col, row, num)
self.runSolver()
self.grid.setValue(col, row, 0)
return
self.grid.printGrid() # this line prints the actual solutions when reached (it works)
self.solutions.append(self.grid) # this should append the solution to 'solutions'
self.n_solutions += 1 # keeps track of how many solutions there are
The main function which actually shows the problem is then,
# Set up game
gameGrid = Grid()
gameGrid.writeGrid([[1, 4, 5],
[0, 6, 0],
[7, 8, 9]])
solverGrid = Solver(gameGrid)
# Run the solver
solverGrid.runSolver()
# This should print out the found solutions,
# It actually prints out the initial, unsolved, grid twice
for i in range(solverGrid.n_solutions):
solverGrid.solutions[i].printGrid()
From some searching online I think that I may be getting confused between instance attributes and class attributes and the scope with which they are accessible however I am really not sure.
When you run self.solutions.append(self.grid) you basically just append a reference to the self.grid to self.solutions. So at the end of your runSolver you have a list of references in self.solutions that all point to the same object.
This has to do with the fact that both your Grid object and Numpy arrays are mutable objects. In contrast to Python strings, for example, when you modify them (with self.grid.setValue(col, row, num) for example), the same object is modified in place instead of a new object being created.
Here is the same issue illustrated with a list of lists:
>>> l = []
>>> x = [1]
>>> l.append(x)
>>> l
[[1]]
>>> x.append(2)
>>> l.append(x)
>>> l
[[1, 2], [1, 2]]
You'll have to create a copy of the grid every time you add it to self.solutions so that you can have a "snapshot" of the grid as it was at that point.
You could do something like this:
class Grid:
def __init__(self, grid=None):
if grid == None:
self.grid = np.zeros((3, 3))
else:
# Copy the array, otherwise we'll have the same mutability issue as above.
self.grid = np.copy(grid)
In runSolver:
grid_copy = Grid(self.grid.grid)
self.solutions.append(grid_copy) # this should append the solution to 'solutions'

Why am I getting this error "NameError:name 'self' is not defined."

As a way of practicing python I'm trying to write a little program that creates sudoku puzzles. I've found multiple questions similar to my issue but none seem to exactly relate.
#!usr/bin/python3
from random import randint
class Puzzle :
def __init__(self, **puzzle):
puzzle = [[0 for x in range(9)]for y in range(9)]
def createEasy(self):
count = 0
while(count < 32):
i = randint(0,8)
j = randint(8,9)
k = randint(1,9)
if (self.puzzle[i][j] != 0):
self.puzzle[i][j] = k
count += 1
def createMedium(self):
count = 0
while(count < 30):
i = randint(0,8)
j = randint(8,9)
k = randint(1,9)
if (self.puzzle[i][j] != 0):
self.puzzle[i][j] = k
count += 1
def createHard(self):
count = 0
while(count < 26):
i = randint(0,8)
j = randint(8,9)
k = randint(1,9)
if (self.puzzle[i][j] != 0):
self.puzzle[i][j] = k
count += 1
def main():
print("Welcome to sudoku!!!")
answer = input( "what level of difficultly do you want today?")
if (answer == "easy"):
self.createEasy()
for x in Puzzle.puzzle:
for y in x:
print(y)
print('\n')
Puzzle.main()
Most answers I found either had to do with functions not being defined in the right order or not putting "self" in the parameter list of all the functions. One answer even said to get rid of "self" parameter in the init function but that didn't help either. I also found this answer though I don't think it relates either. NameError: name 'self' is not defined The only thing I can think of is that I need to declare the list called puzzle elsewhere since it's suppose to be a class variable but from python code I've I don't think that's true not to I'm not sure since it's 2d and writing puzzle = [][] is wrong.
Sorry here's the whole output with error.
Welcome to sudoku!!!
what level of difficultly do you want today?easy
Traceback (most recent call last):
File "sudoku_maker.py", line 49, in <module>
Puzzle.main()
File "sudoku_maker.py", line 43, in main
self.createEasy(self)
NameError: name 'self' is not defined
It seems like you want main() to be a class method or a static method rather than an instance method. Class methods are methods that are not bound to an object but to a class. In that case, you need to define it clearly.
https://docs.python.org/3.5/library/functions.html#classmethod
https://docs.python.org/3.5/library/functions.html#staticmethod
This answer clearly explains the difference between class methods and static methods.
What is the difference between #staticmethod and #classmethod in Python?
One more way of solving your problem is :
Make main() as an instance method by passing self as an argument.
main(self)
Create an object of Puzzle.
puzzle = Puzzle()
Call the object's main method.
puzzle.main()
The error disappears if you make the following changes:
Add self as a parameter of the main() function.
Create an instance of the class: p = Puzzle() and call p.main() then.
Write self.puzzle in the __init__ function instead of just puzzle.
(Then there are different errors though not related to this one)
First of all, in __init__ method when you declare puzzle attribute, you forgot the self, so it is not declared:
def __init__(self, **puzzle):
self.puzzle = [[0 for x in range(9)] for y in range(9)]
You also forgot de self when declaring the main function. And, inside of this one you got an error too, when you call Puzzle.puzzle, it should be with the self instance:
def main(self):
print("Welcome to sudoku!!!")
answer = input( "what level of difficultly do you want today? ")
if (answer == "easy"):
self.createEasy()
for x in self.puzzle:
for y in x:
print(y)
print('\n')
And finally, when you call the function. You need to create the instance of Puzzle first, but you are using Puzzle.main, so your not initializing the object, so the self instance will not exist.
You have to do it like this:
Puzzle().main()
However, there's another error when using randint(a, b), because this function generate a random int between a and b, but including the limits, so when you call it in createEasy, the 9 should not be in the limits.

Call Function of inside function in Python

I have some Python code in below written in Python 2.7 and I have problem with calling a function form inside another function.
class CSP:
def __init__(self, matrix):
self.X = []
self.D = []
self.C = []
self.matrix = util.copyMatrix(matrix)
self.counter = 0
# Matrix to Vector
vector = [item for line in self.matrix for item in line]
chars = map(str, vector)
result = ['*' if item == '0' else item for item in chars]
def solve(self):
""" Returns the result matrix.
The sudoku matrix is self.matrix.
Use util.printMatrix in purpose of debugging if needed. """
"*** YOUR CODE HERE ***"
def init(self,result):
for i in range(9):
for j in range(1,10):
var = var_char[i]+str(j)
self.X.append(var)
domain = set([1,2,3,4,5,6,7,8,9])
self.D.append(domain)
gamelist = result
for i in range(len(gamelist)):
if(re.match("\d+",gamelist[i])):
self.D[i] = set([int(gamelist[i])])
self.set_constraints()
#########################################################################
def set_constraints(self):
for x in self.X:
for y in self.X:
if((x[0] == y[0] and x[1] != y[1]) or (x[1] == y[1] and x[0] != y[0])):
flag = True
for c in self.C:
if(x in c and y in c):
flag = False
if(flag):
self.C.append(set([x,y]))
for a in [0,3,6]:
for b in [0,3,6]:
self.set_cube_constraints(a,b)
How to call init() function in solve() and also call self.set_constraint() inside init() function?
Within function solve(), init() is a function, not a method. Therefore it can only be called in the same manner that any other unbound function can be called: by passing the correct number of arguments to it. This would work:
init(self, results)
Note that you need to explicitly pass a reference to the object in self because init() is not a method. Within solve() self refers to the CSP instance, so this should work.
However, set_constraints() is also a normal function, so you can not call it from init() with self.set_constraints(), but set_constraints(self) should work. Note that you need to declare function set_constraints() before init() otherwise you will get a "referenced before assignment" error.
Having said all that, this is just awful. Why not make init() and set_constraints() proper methods of the class?
set_constraints is not a part of the class and therefore cannot be called with self.
If you put it one level up (remove one indentation level of it) then your code should work better.
I can see that this is some kind of coding exercise and you are told to write code in one particular place. I think you may be overcomplicating the answer because what you are coding here looks very messy by design and you should probably split out your functionality a lot more if this should be considerered clean code.

Categories

Resources