I'm a newbie in python , so I was creating this project to create Sudoku using brute force method. To some extent I was successful but I am not able to figure out why sometimes the program hangs randomly while generating. Hope someone can pinpoint the issue.
I have tried debugging the code but still am not able to pinpoint what's causing the issue. The most close I have come to figuring something about the bug is that it is caused somewhere in the brute_generator() function.
A little Info on how the code is intended to work :-
The Sudoku is generated row by row by calling the brute_generator()function 9 times.
In the function brute_generator() the rows are generated using trial and error where a random number is picked up from possibilities list which is from number 1-9 and then it is treated as first number of row , now check_1() and check_2() function are called to check if the number has already been repeated in its column in previous rows if any and its 3x3 square as per the rules of Sudoku , if yes then the number is added to blacklist list and another number is chosen till the right number is obtained. When the right number is obtained it is appended to a temp_array while being removed from possibilities list so that it cannot be chosen again and counter is increased by 1 . This repeats till the row is generated (i.e counter = 9) or no number from possibilities list can be placed in a given cell of row (i.e len(blacklist)==len(possibilities) , all possibilities are blacklisted) in which case the row being generated is scraped by returning all variables to their default values and a new row is generated . This happens until the perfect row is obtained which is then appended to sudoku_array()
def check_1(x , temp_array , sudoku_array) : # Check for recurrence in the Block in which the cell exist
flag_1 = True
if len(temp_array) < 3 :
j = 2
l = 0
elif len(temp_array) < 6 :
j = 5
l = 3
else :
j = 8
l = 6
i = len(sudoku_array)
if len(sudoku_array) < 3 :
o = 0
elif len(sudoku_array) < 6 :
o = 3
else :
o = 6
for m in range(o,i) :
for n in range(l,j+1) :
if x == sudoku_array[m][n] :
flag_1 = False
break
if x == sudoku_array[m][n] :
break
return flag_1
def check_2(x, counter, sudoku_array) : # Check for the recurrence of number in its consequent column
flag_2 = True
for k in range(len(sudoku_array)) :
if x == sudoku_array[k][counter] :
flag_2 = False
break
return flag_2
def brute_generator(sudoku_array) : # The main sudoku Generating Algo.
all_possibilities = [1,2,3,4,5,6,7,8,9]
possibilities = all_possibilities.copy()
blacklist = []
counter = 0
temp_array = []
while counter != 9 :
if len(blacklist) == len(possibilities) :
all_possibilities = [1,2,3,4,5,6,7,8,9]
possibilities = all_possibilities.copy()
blacklist = []
counter = 0
temp_array = []
continue
x = random.choice(possibilities)
if x not in blacklist :
if len(sudoku_array) != 0 :
if check_1(x, temp_array , sudoku_array) == False :
blacklist.append(x)
continue
elif check_2(x, counter , sudoku_array) == False :
blacklist.append(x)
continue
possibilities.remove(x)
counter+=1
temp_array.append(x)
blacklist = []
sudoku_array.append(temp_array)
sudoku_array = [] # This will be the generated sudoku
for i in range(9) :
brute_generator(sudoku_array)
The Traceback calls show the following after the program is stuck
Traceback (most recent call last):
File "c:\program files (x86)\microsoft visual studio\2017\community\common7\ide\extensions\microsoft\python\core\ptvsd_launcher.py", line 119, in <module>
vspd.debug(filename, port_num, debug_id, debug_options, run_as)
File "c:\program files (x86)\microsoft visual studio\2017\community\common7\ide\extensions\microsoft\python\core\Packages\ptvsd\debugger.py", line 37, in debug
run(address, filename, *args, **kwargs)
File "c:\program files (x86)\microsoft visual studio\2017\community\common7\ide\extensions\microsoft\python\core\Packages\ptvsd\_local.py", line 64, in run_file
run(argv, addr, **kwargs)
File "c:\program files (x86)\microsoft visual studio\2017\community\common7\ide\extensions\microsoft\python\core\Packages\ptvsd\_local.py", line 125, in _run
_pydevd.main()
File "c:\program files (x86)\microsoft visual studio\2017\community\common7\ide\extensions\microsoft\python\core\Packages\ptvsd\_vendored\pydevd\pydevd.py", line 1752, in main
globals = debugger.run(setup['file'], None, None, is_module)
File "c:\program files (x86)\microsoft visual studio\2017\community\common7\ide\extensions\microsoft\python\core\Packages\ptvsd\_vendored\pydevd\pydevd.py", line 1099, in run
return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
File "c:\program files (x86)\microsoft visual studio\2017\community\common7\ide\extensions\microsoft\python\core\Packages\ptvsd\_vendored\pydevd\pydevd.py", line 1106, in _exec
pydev_imports.execfile(file, globals, locals) # execute the script
File "c:\program files (x86)\microsoft visual studio\2017\community\common7\ide\extensions\microsoft\python\core\Packages\ptvsd\_vendored\pydevd\_pydev_imps\_pydev_execfile.py", line 25, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "C:\Users\groot\source\repos\PythonApplication5\PythonApplication5\PythonApplication5.py", line 145, in <module>
brute_generator(sudoku_array)
File "C:\Users\groot\source\repos\PythonApplication5\PythonApplication5\PythonApplication5.py", line 109, in brute_generator
x = random.choice(possibilities)
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\random.py", line 255, in choice
def choice(self, seq):
File "c:\program files (x86)\microsoft visual studio\2017\community\common7\ide\extensions\microsoft\python\core\Packages\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_trace_dispatch_regular.py", line 273, in __call__
frame_cache_key = (frame.f_code.co_firstlineno, frame.f_code.co_name, frame.f_code.co_filename)
KeyboardInterrupt
Hope someone can pinpoint the issue.
The issue is that for i in range(9) : brute_generator(sudoku_array) can create a partial sudoku_array which is impossible to complete, e. g. the five rows:
[1, 5, 7, 2, 3, 6, 8, 4, 9],
[9, 8, 2, 5, 4, 7, 6, 3, 1],
[4, 3, 6, 8, 1, 9, 7, 2, 5],
[5, 7, 9, 4, 2, 1, 3, 6, 8],
[6, 1, 3, 9, 5, 8, 2, 7, 4]
Now the function keeps searching for an appropriate sixth row which it never finds, and it never backtracks, which would mean throwing away previously generated rows to get out of the dead end.
Related
I am trying to learn about loops and conditions. Therefore I coded a generator, which randomly create lotto/lottery numbers. However I created a global variable 'valCount', which stores the generation count. But still got this error:
Bitte die Anzahl zu erzeugender Lottoscheine angeben: 2
Input is an integer number. Number = 2
Traceback (most recent call last):
File "/Volumes/HDD/Users/Stephan/PycharmProjects/LottZahlenGeneratorLoop/main.py", line 87, in
check_user_input(userCountInput)
File "/Volumes/HDD/Users/Stephan/PycharmProjects/LottZahlenGeneratorLoop/main.py", line 70, in check_user_input
outPutCount()
File "/Volumes/HDD/Users/Stephan/PycharmProjects/LottZahlenGeneratorLoop/main.py", line 55, in outPutCount
for x in range(valCount):
NameError: name 'valCount' is not defined
Correct behaviour:
User needs to input a number. This number get validated, if it is a digit or a letter. If this is a digit, the lotto/lottery numbers should be created by the count of users input. Otherwise, user is asked to enter number.
My code:
# IMPORTS
import random
from datetime import datetime
import os
# CLEAR CONSOLE
def clearConsole():
command = 'clear'
if os.name in ('nt', 'dos'): # If Machine is running on Windows, use cls
command = 'cls'
os.system(command)
# VARIABLES
date = datetime.now()
dateFormat = str(date.strftime("%d-%m-%Y %H:%M:%S"))
mainNumbers = [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, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
superNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
mainNumbersLotto = mainNumbers
del mainNumbersLotto[49] # löscht die 49. Stelle von mainnumbers, da Lotto 6aus49 nur Zahlen von 1-49 existieren
global valCount
# countToCreate = input("Bitte geben sie die Anzahl zum generieren an.")
# FUNCTION EUROJACKPOT GENERATOR
def eurojackpotFunc():
global eurojackpotOutput
RandomMainNumbers = str(sorted(random.sample(mainNumbers, 5)))
RandomSuperNumbers = str(sorted(random.sample(superNumbers, 2)))
eurojackpotOutput = "\nEurojackpot\n5 aus 50: " + RandomMainNumbers + "\nEurozahlen: " + RandomSuperNumbers
print(eurojackpotOutput)
# FUNCTION Lotto6aus49 GENERATOR
def lottoNumbersFunc():
global lottoNumbersOutput
RandomLottoNumber = str(sorted(random.sample(mainNumbersLotto, 6)))
lottoNumbersOutput = "\nLotto6aus49\n6 aus 49: " + RandomLottoNumber
print(lottoNumbersOutput)
# FUNCTION GENERATE TEXTFILE WITH RESULT
def generateTxtFile():
f = open("Lottozahle" + "- " + dateFormat + ".txt", "+w")
f.write(eurojackpotOutput + "\n " + lottoNumbersOutput)
def check_user_input(input):
try:
# Convert it into integer
valCount = int(input)
print("Input is an integer number. Number = ", valCount)
outPutCount()
except ValueError:
try:
# Convert it into float
valCount = float(input)
print("Input is a float number. Number = ", valCount)
userCountInputFunc()
except ValueError:
print("No.. input is not a number. It's a string")
userCountInputFunc()
def userCountInputFunc():
global userCountInput
userCountInput = input("Bitte die Anzahl zu erzeugender Lottoscheine angeben: ")
#
def outPutCount():
# LOOP FOR GENERATING COUNT
global valCount
xCount = 0
for x in range(valCount):
xCount = xCount + 1
print("\n#################")
print(xCount, ". Generation")
eurojackpotFunc()
lottoNumbersFunc()
generateTxtFile()
valCount = str(valCount)
print("\nEs wurden erfolgreich " + valCount + " Lottoscheine generiert.")
userCountInputFunc()
check_user_input(userCountInput)
The error message shows NameError: name 'valCount' is not defined (within your loop), and from the looks of it, you're attempting to define it twice– within outPutCount and in the true global scope. As an aside, no matter where you use the keyword global, it will always belong to the global scope.
Anyways, this is the problem with global variables (especially ones that have no value assigned to them before run-time)– figuring out their value while letting various areas in the code mutate them is a self-induced headache worth avoiding.
Try passing the value you want into the function by way of its arguments. You can implement this entire program without the usage of a global variable.
Hope that helps, and keep learning!
I'm 63 and just started with Python (My first steps with Udemy).
I'm Croatian so this is croatian language in program but you will understand when you run a program. I know it can be cleaner, shorter, more elegant etc, but as I mentioned before - I'm beginner.
import random
jedan = random.sample(range(1,99),15)
dva = random.sample(range(1,99),15)
def raspaljot(jedan, dva, i):
for x in jedan:
for y in dva:
if y == x:
index1 = jedan.index(x)
index1_str = str(index1)
index2 = dva.index(y)
index2_str = str(index2)
i += 1
x = str(x)
print(" Broj \033[31m" + x + "\033[0m,je dupli i nalazi se u listi jedan: na poziciji: \033[34m"
+ index1_str + "\033[0m a u listi dva na poziciji: \033[35m"+ index2_str + "\033[0m")
print()
print(jedan)
print(dva)
if i != 0:
print("\n *** Ukupno ima ", i, 'duplih brojeva. ***')
elif i == 0:
print("Nema duplih brojeva. :) ")
i = 0
raspaljot(jedan, dva,i)
What program do is finding duplicates in 2 random lists, them print duplicates in color and detecting position inside list[1] and list[2].
What I trying to do is printing list1 and list2 but showing duplicates in color.
For example:
[14, 78, 85, 31, 5, 54, 13, 46, 83, 4, 35, 41, 52, 51, 32]
[72, 40, 67, 85, 54, 76, 77, 39, 51, 36, 91, 70, 71, 38, 55]
here we have 3 duplicates (85,54,51). This above example on the console End was printed in white color, but I wanna these 3 numbers in red color in those two lines above.
Is this possible? I couldn't find a solution.
PS. Wing Pro version 7 on Fedora 33 Workstation / In WIngIde colors are only displayed in an external console and not the Debug I/O tool. :)
Simple solution would be something like this:
# Change list to string
jedan_str = str(jedan)
# Create set with numbers that need new color
num_set = {"85", "54", "51"}
# Iterate over every number and wrap it with color change
for i in num_set:
# Note that I used f-string to format string
# But you can also do this as "\033[31m" + i + "\033[0m"
jedan_str = jedan_str.replace("85", f"\033[31m{i}\033[0m")
# Print string that represent list
print(jedan_str)
Following the idea of using a set to determine which elements are in both lists (as Cv4niak proposed in his answer), I created a function to print the output as you desire. There are numerous other ways of achieving it, but I think this is a simple yet effective way.
The idea is to use the cprint() function from the termcolor package. You can install it with pip install termcolor, and then print normally all elements, except the ones that are duplicates, which will be printed using cprint(item, "red").
The "{:0>2d}" formatting in each ìtem print serves only to pad the number with zeros (so 2 will be printed as 02, for example), in order for the output of both lists to be aligned.
import random
from termcolor import cprint
def mark_duplicates(first, second):
duplicates = list(set(first).intersection(second))
if duplicates:
for list_ in [first, second]:
print("[", end="")
for item in list_:
if item in duplicates:
cprint("{:0>2d}".format(item), "red", end=",")
else:
print("{:0>2d}".format(item), end=",")
print("\b]")
else:
print("No duplicates.")
jedan = random.sample(range(1, 99), 15)
dva = random.sample(range(1, 99), 15)
mark_duplicates(jedan, dva)
With this, if there are no duplicates, the No duplicates. string will be printed. Also you can change the color with not much effort, and use other nice functionalities from termcolor package.
Instructions:
When you divide the successive powers of 10 by 13 you get the following remainders of the integer divisions:
1, 10, 9, 12, 3, 4.
Then the whole pattern repeats.
Hence the following method: Multiply the right most digit of the number with the left most number in the sequence shown above, the second right most digit to the second left most digit of the number in the sequence. The cycle goes on and you sum all these products. Repeat this process until the sequence of sums is stationary.
...........................................................................
Example: What is the remainder when 1234567 is divided by 13?
7×1 + 6×10 + 5×9 + 4×12 + 3×3 + 2×4 + 1×1 = 178
We repeat the process with 178:
8x1 + 7x10 + 1x9 = 87
and again with 87:
7x1 + 8x10 = 87
...........................................................................
From now on the sequence is stationary and the remainder of 1234567 by 13 is the same as the remainder of 87 by 13: 9
Call thirt the function which processes this sequence of operations on an integer n (>=0). thirt will return the stationary number.
thirt(1234567) calculates 178, then 87, then 87 and returns 87.
thirt(321) calculates 48, 48 and returns 48
My Code:
def thirt(n):
a = []
n = [int(i) for i in list(str(n))][::-1]
l = [1, 10, 9, 12, 3, 4][:len(n)]
y = sum([a * b for a,b in zip(n,l)])
a.append(y)
for c in a:
if a.count(c) == 1:
thirt(c)
else:
return c
thirt(5634)
When I run this I get an error
Traceback (most recent call last):
File "main.py", line 5, in <module>
Test.assert_equals(thirt(8529), 79)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
[Previous line repeated 994 more times]
File "/home/codewarrior/solution.py", line 3, in thirt
n = [int(i) for i in list(str(n))][::-1]
RecursionError: maximum recursion depth exceeded while getting the str of an object
when I remove some part of the code and leave it like
def thirt(n):
n = [int(i) for i in list(str(n))][::-1]
l = [1, 10, 9, 12, 3, 4][:len(n)]
y = sum([a * b for a,b in zip(n,l)])
return y
thirt(5634)
I get 148 in the output, and then I thirt(148), I get 57, which is the desired answer, same goes for other examples as well.
so I just need a proper way to recur this function, and I just want it to stop as soon as the values start repeating, i.e. I want the loop of recursion to break as soon as I get two 57's in a row, and then I need it to return 57.
But I can't figure out a proper way to do it, because this is the first time I've applied recursion in a function, my code is really messed up, I'll really appreciate any help.
You are getting the error depth exceeded while getting the str of an object because you are assigning the list of digits n to the same variable name as the function parameter n. That means after the first recursive call, you are running [int(i) for i in list(str(n))][::-1] on a list of individual digits, and then a list of lists, and so on, rather than a single input number as you're expecting.
Once you fix that, you run into the issue of how you are checking for whether to make the recursive call:
a = []
a.append(y)
for c in a:
if a.count(c) == 1:
thirt(c)
I can see what you're trying to do, and it will not work in recursion because every time the function is called, a is reset to an empty list. That means a.count(c) == 1 is always true, and your function will go into an infinite recursive loop.
Instead, for this algorithm all you need to do is check whether your newly calculated y is equal to the number n that was passed to the function. If they're the same, that means you've gotten the same number twice in a row, so the algorithm is done.
After that is fixed, it will look like you're getting somewhere. You can use this logic:
if n != y:
thirt(y)
else:
print(y) # expected answer outputted to console
return y
Except when you call thirt(1234567), the value returned is None ! What the heck? I printed y and it's correct, it's right there! What is happening is, the inner-most call to thirt is returning the number you need, but then the next level up in the function call stack doesn't do anything with it. So the function ends and returns None. To fix this, you need each level of the recursive call to pass its return value up the chain. So use return thirt(y) instead of just thirt(y).
Finally, you need to account for the case when the number passed to the function is longer than 6 digits. Your l list needs to repeat in a cycle, not stop with the 6 numbers you've listed. You can get the list to be the length you need by multiplying it by the length of n divided by six, rounded up whenever there's a remainder.
After all that, you'll end up with something like the following:
def thirt(n):
nList = [int(i) for i in list(str(n))][::-1]
remainders = [1, 10, 9, 12, 3, 4] * (
len(nList) // 6 + min(1, len(nList) % 6)
)
y = sum([a * b for a,b in zip(nList,remainders)])
if n != y:
return thirt(y)
else:
return y
print(thirt(1234567)) #87
Isn't this what you mean?
def thirt(n_raw):
a = []
n = [int(i) for i in list(str(n_raw))][::-1]
l = [1, 10, 9, 12, 3, 4]*(len(n)//6+1)
y = sum([a * b for a,b in zip(n,l)])
if(y==n_raw): return y
else: return thirt(y)
I think you just went in a very wrong direction with the second half of your function, but I might misunderstood the premise behind...
I'd like to convert a list of integers to a singe variable.
I tried this (found on another question):
r = len(message) -1
res = 0
for n in message:
res += n * 10 ** r
r -= 1
This does not work for me at all.
I basically need this:
message = [17, 71, 34, 83, 81]
(This can vary in length as I use a variable to change each one)
To convert into this:
new_message = 1771348381
A combination of join, map and str will do.
message = [17, 71, 34, 83, 81]
new_message = int(''.join(map(str, message)))
# 1771348381
I have a list with 4 element which contain integers
data = [134, 2, 4, 170]
hexdata = [0x86, 0x2, 0x4, 0xAA]
i need to get hex data from two last elements eg. (0x04 and 0xAA)
concatenate them to this view 0x04AA and convert to int
in the end i need to get integer with value = 1194.
i am stuck in this task/
data = [134, 2, 4, 170]
for x in data:
print("0x%x" % (x), end=" ")
print()
c = "0x%x%x" % (data[2], data[3])
print(c)
print(int(c))
Traceback (most recent call last):
File "123.py", line 7, in <module>
print(int(c))
ValueError: invalid literal for int() with base 10: '0x4aa'
You don't need to bother with string formatting here - use int.from_bytes instead, eg:
data = [134, 2, 4, 170]
res = int.from_bytes(data[-2:], 'big')
# 1194
data = [134, 2, 4, 170]
result = data[-2] << 8 | data[-1]
Simply multiply the 4 accordingly and add it up? No need to go hex on it ...
data = [134, 2, 4, 170]
rv = data[2]*256 + data[3] # 0x04AA == 0x04*256 + 0xAA
print(rv)
Output:
1194