Related
In the long run this will be used to find groups of words that spell another. (For crosswords)
But for now I just want to know some kind of generalized algorithm to calc the ways to get to a number using sums.
So lets say I have a 6 letter word, the only possible way to "create" that word from sub words would be words of length 5,4,3,2,1 (and I guess the word and word anagrams of that word):
6 = 6
6 = 5 + 1
6 = 4 + 2
6 = 4 + 1 + 1
6 = 3 + 3
6 = 3 + 2 + 1
6 = 3 + 1 + 1 + 1
6 = 2 + 2 + 2
6 = 2 + 2 + 1 + 1
6 = 2 + 1 + 1 + 1 + 1
6 = 1 + 1 + 1 + 1 + 1 + 1
So I want code to generate me this in an array in python, so I can go look for words of combinations of lengths. I may want to exclude 1 letter words & same length words, but since there is just a max of 26 (and in English only I and A, and maybe if you include slang U) I don't think it'll make it too complex.
This doesn't need to be too optimized since usually like 15 is the highest I will go (I might even just type it all out and then I have it pre-solved, but it's going to be a fair amount for 15.
Here is a recursive solution to your question. We basically check all possible sum combinations until we find a valid one, then add it to our list of sums.
def find_sums(n):
sums = []
all_sums = []
find_sums_helper(n, n, sums, all_sums)
return all_sums
def find_sums_helper(n, n_max, sums, all_sums):
if n == 0:
all_sums.append(sums)
return
for i in reversed(range(1, min(n, n_max) + 1)):
find_sums_helper(n - i, i, sums + [i], all_sums)
print(find_sums(6))
Output:
[[6], [5, 1], [4, 2], [4, 1, 1], [3, 3], [3, 2, 1], [3, 1, 1, 1], [2, 2, 2], [2, 2, 1, 1], [2, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1]]
i was trying a pattern in Python
if n == 6
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
after trying to think a lot
i did it like this --->
n = 6
for i in range(1,n):
x = 1
countj = 0
for j in range(i,n):
countj +=1
print(j,end=" ")
if j == n-1 and countj < n-1 :
while countj < n-1:
print(x , end =" ")
countj +=1
x +=1
print()
but i don't think it is the best approach, I was trying to search some better approach , but not able to get the proper one, So that I came here,, is there any possible better approach for the problem?
I would do like this, using a rotating deque instance:
>>> from collections import deque
>>> n = 6
>>> d = deque(range(1, n))
>>> for _ in range(1, n):
... print(*d)
... d.rotate(-1)
...
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
There is a similar/shorter code possible just using range slicing, but maybe it's a bit harder to understand how it works:
>>> ns = range(1, 6)
>>> for i in ns:
... print(*ns[i-1:], *ns[:i-1])
...
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
You could also create a mathematical function of the coordinates, which might look something like this:
>>> for row in range(5):
... for col in range(5):
... print((row + col) % 5 + 1, end=" ")
... print()
...
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
A too-clever way using list comprehension:
>>> r = range(5)
>>> [[1 + r[i - j - 1] for i in r] for j in reversed(r)]
[[1, 2, 3, 4, 5],
[2, 3, 4, 5, 1],
[3, 4, 5, 1, 2],
[4, 5, 1, 2, 3],
[5, 1, 2, 3, 4]]
more-itertools has this function:
>>> from more_itertools import circular_shifts
>>> circular_shifts(range(1, 6))
[(1, 2, 3, 4, 5),
(2, 3, 4, 5, 1),
(3, 4, 5, 1, 2),
(4, 5, 1, 2, 3),
(5, 1, 2, 3, 4)]
You can use itertools.cycle to make the sequence generated from range repeat itself, and then use itertools.islice to slice the sequence according to the iteration count:
from itertools import cycle, islice
n = 6
for i in range(n - 1):
print(*islice(cycle(range(1, n)), i, i + n - 1))
This outputs:
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
Your 'pattern' is actually known as a Hankel matrix, commonly used in linear algebra.
So there's a scipy function for creating them.
from scipy.linalg import hankel
hankel([1, 2, 3, 4, 5], [5, 1, 2, 3, 4])
or
from scipy.linalg import hankel
import numpy as np
def my_hankel(n):
x = np.arange(1, n)
return hankel(x, np.roll(x, 1))
print(my_hankel(6))
Output:
[[1 2 3 4 5]
[2 3 4 5 1]
[3 4 5 1 2]
[4 5 1 2 3]
[5 1 2 3 4]]
Seeing lots of answers involving Python libraries. If you want a simple way to do it, here it is.
n = 5
arr = [[1 + (start + i) % n for i in range(n)] for start in range(n)]
arr_str = "\n".join(" ".join(str(cell) for cell in row) for row in arr)
print(arr_str)
Ok, I've been scratching my head over this for a few hours now..
My goal was to code a sudoku solver that uses the backtracking method and to show the progress of the algorithm using pygame. For this I have to keep track of the events, I did it by appending them to a list named registre as is shown in the code:
def solver(self):
self.t1 = time.time()
if self.t1-self.t0 > self.solve_time_max:
sys.exit(1)
for i in range(self.grid.shape[0]):
for j in range(self.grid.shape[1]):
if self.grid[i][j]==0:
for n in range(1,10):
self.registre.append([n,i,j])
if self.verify(n,i,j):
self.grid[i][j]=n
self.solver()
if 0 not in self.grid:
break
self.registre.append([0,i,j])
self.grid[i][j]=0
return self.grid
I actually succeeded and everything goes fine for most of the runs. But sometimes, for some reason I couldn't identify, this happens :
print(une_grille.grid0)
print(une_grille.grid)
print(une_grille.registre[:20])
[[0 8 0 7 0 0 0 0 2]
[5 0 0 0 0 9 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 1 0 0 6 0 0 0 0]
[4 0 0 9 0 0 0 0 0]
[0 0 9 0 8 0 0 0 4]
[2 0 0 0 0 0 0 8 0]
[0 0 0 0 0 0 0 0 0]]
[[1 8 3 7 4 5 6 9 2]
[5 2 4 6 1 9 3 7 8]
[6 9 7 2 3 8 1 4 5]
[3 5 2 8 7 1 4 6 9]
[9 1 8 3 6 4 2 5 7]
[4 7 6 9 5 2 8 1 3]
[7 3 9 1 8 6 5 2 4]
[2 4 1 5 9 3 7 8 6]
[8 6 5 4 2 7 9 3 1]]
[[1, 0, 0], [1, 0, 1], [0, 0, 1], [2, 0, 1], [0, 0, 1], [3, 0, 1], [1, 0,
2], [0, 0, 2], [2, 0, 2], [0, 0, 2], [3, 0, 2], [0, 0, 2], [4, 0, 2], [0,
0, 2], [5, 0, 2], [1, 0, 3], [0, 0, 3], [2, 0, 3], [0, 0, 3], [3, 0, 3]]
What is printed is simply the initialized grid, the solved grid and the first 20 events in self.registre. For this run the displaying on pygame didn't work, some numbers overlap themselves and others are left blank. I am almost sure it's not a displaying problem since the displaying function uses the list registre and it works just fine for most of the other runs. Also I don't understand these events.
Complete script :
import numpy as np
import random as rd
import time
import sys
class Grid():
"""
une Docstring
"""
def __init__(self, nval=15, dim=(9,9), tries_max=1000, init_time_max=5e-3, solve_time_max = 1):
self.nval = nval+1
self.dim = dim
self.t0 = 0
self.t1 = 0
self.tries_max = tries_max
self.k = 0
self.init_time_max = init_time_max
self.solve_time_max = solve_time_max
self.registre = []
self.grid = self.create_grid()
self.smthg = 0
def create_grid(self):
for tries in range(self.tries_max):
self.k = 0
if tries == self.tries_max -1:
print(f"Tried {self.tries_max} times, I have failed")
sys.exit(1)
self.grid0 = np.zeros([self.dim[0],self.dim[1]], dtype=int)
try:
self.grid0 = self.initialize_board()
except SystemExit:
print(f"TRY #{tries}: Spent too much time initializing board. Re-trying.")
continue
self.grid = np.copy(self.grid0)
try:
self.t0 = time.time()
self.grid = self.solver()
if 0 not in self.grid:
print(f"Found grid with solution after n = {tries+1} tries!")
return self.grid
else:
print(f"TRY #{tries} converged to null solution")
continue
except SystemExit:
print(f"TRY #{tries} too much time spent trying to solve current grid, continuing")
continue
print("Maximum tries reached")
def initialize_board(self):
for i in range(self.nval):
rx = rd.randint(0, self.grid0.shape[0]-1)
ry = rd.randint(0, self.grid0.shape[1]-1)
cx = int(rx/3)
cy = int(ry/3)
time0 = time.time()
while(self.grid0[rx][ry]==0):
if time.time()-time0 > self.init_time_max:
sys.exit(1)
r = rd.randint(1, 9)
if((r in self.grid0[rx,:]) or (r in self.grid0[:,ry]) or (r in self.grid0[3*cx:3*cx+3,3*cy:3*cy+3])):
continue
else:
self.grid0[rx][ry] = r
return self.grid0
def solver(self):
self.t1 = time.time()
if self.t1-self.t0 > self.solve_time_max:
sys.exit(1)
for i in range(self.grid.shape[0]):
for j in range(self.grid.shape[1]):
if self.grid[i][j]==0:
for n in range(1,10):
self.registre.append([n,i,j])
if self.verify(n,i,j):
self.grid[i][j]=n
self.solver()
if 0 not in self.grid:
break
self.registre.append([0,i,j])
self.grid[i][j]=0
return self.grid
def verify(self, number, x, y):
cx = int(x/3)
cy = int(y/3)
if((number in self.grid[x,:]) or (number in self.grid[:,y]) or (number in self.grid[3*cx:3*cx+3,3*cy:3*cy+3])):
return False
return True
game = Grid(nval = 35)
print(game.grid)
print(game.grid0)
print(game.registre[:20])
Another instance of the issue :
[[1 2 3 9 5 7 6 4 8]
[5 8 4 6 2 1 9 7 3]
[7 9 6 8 4 3 1 5 2]
[6 7 2 5 1 4 3 8 9]
[3 4 9 7 8 6 5 2 1]
[8 5 1 3 9 2 7 6 4]
[2 1 5 4 6 9 8 3 7]
[4 6 7 1 3 8 2 9 5]
[9 3 8 2 7 5 4 1 6]]
[[0 0 0 9 0 7 6 0 0]
[0 0 0 6 0 0 0 0 3]
[0 0 0 8 4 3 1 5 2]
[6 0 0 0 0 0 0 0 0]
[0 4 9 0 0 6 5 2 0]
[0 5 1 0 9 0 7 0 0]
[0 1 5 0 0 0 0 0 0]
[0 0 7 0 0 0 0 0 5]
[9 0 0 2 0 0 0 1 0]]
[[1, 0, 2], [0, 0, 2], [2, 0, 2], [0, 0, 2], [3, 0, 2], [1, 0, 3], [0, 0, 3], [2, 0, 3], [0, 0, 3], [3, 0, 3], [0, 0, 3], [4, 0, 3], [1, 0, 4], [0, 0, 4], [2, 0, 4], [0, 0, 4], [3, 0, 4], [0, 0, 4], [4, 0, 4], [0, 0, 4]]
I would really appreciate it if you could help me with this.
After you added the code that repeats the generation of grids, it becomes clear that you don't create a new instance of Grid, but mutate the existing one. In that process you should then take care to reset the state completely. You only do this partly, e.g. by resetting t0. But you don't reset registre, and so when you print the first 20 items, you are actually looking at the log of the first attempt, not the successful one.
I'd like to create two list (appearantly it doesnt need to be a list, can be tuple, array, numpy.array, see edit below) of a certain partern, lets call them list_1 and list_2
list_1 has the patern that can be described as (i is an integer)
{i}, {i, i + 17}, {i, i+17 , i + 17 + 17}, {i, i + 17, i + 17 + 17, i + 17 + 17 + 17},
But the pattern occurs twice, which means that the resulting list will look like
list_1 = [i, i, i + 17, i, i + 17 , i + 34, i, i + 17, i + 34, i + 51,
i, i, i + 17, i, i + 17 , i + 34, i, i + 17, i + 34, i + 51]
Currently I'm doing it as (with i = 2 in this example)
some_limit = 5
list_1 = [17 * x + i for b in range(some_limit + 1) for x in range(b)]
list_1 += list_1
result
[2, 2, 19, 2, 19, 36, 2, 19, 36, 53, 2, 19, 36, 53, 70, 2, 2, 19, 2, 19, 36, 2, 19, 36, 53, 2, 19, 36, 53, 70]
When some_limit is a big number this takes time. Is there a faster way?
list_2 has a pattern that can be described as (j is an integer)
{j} {j+1, j+1}, {j+2, j+2, j+2}, {j+3, j+3, j+3, j+3}
This pattern also occours twice but with a shift which means that the resulting list will look like
list_2 = [j, j+1, j+1, j+2, j+2, j+2, j+3, j+3, j+3, j+3,
j+shift, j+1+shift, j+1+shift, j+2+shift, j+2+shift, j+2+shift, j+3+shift, j+3+shift, j+3+shift, j+3+shift,
Currently I'm doing it as (with j = 0 in this example)
some_limit = 5
arithemic_list = [k for k in range(some_limit + 1)]
rows_index_temp = [item -1 + some_limit * j * 2 for item, count in zip(arithemic_list, arithemic_list) for k in range(count)]
rows_index_temp += [some_limit + elem for elem in rows_index_temp]
result
[0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9]
When some_limit is a big number this takes time. Is there a faster way?
Edit
This is used to create sparse matrices for the optimization package cvxopt. A matrix is built by providing elements with their row and column indicies. For example a 3x3 identity matrix is created by 3 lists, elements = [1,1,1], rows = [0, 1, 2] and columns = [0, 1, 2]. My matrix is very large which implies that the lists will be very large.
From the documentation
cvxopt.spmatrix(x, I, J[, size[, tc ] ])
I and J are sequences of integers (lists, tuples, array arrays, . . . ) or integer matrices (matrix objects with
typecode 'i'), containing the row and column indices of the nonzero entries. The lengths of I and J must
be equal. If they are matrices, they are treated as lists of indices stored in column-major order, i.e., as lists
list(I), respectively, list(J)
https://readthedocs.org/projects/cvxopt/downloads/pdf/1.2.0/
Example
Lets say we would like to create the following matrix:
[ 1.00e+00 0 0 0 0 ]
[ 2.00e+00 0 0 3.00e+00 0 ]
[ 0 0 0 0 4.00e+00]
We are only interested in the non-zero-elements and we can group them as
element row column
1 0 0
2 1 0
3 1 3
4 2 4
Thus, by having
elements = [1,2,3,4,0]
rows = [0,1,1,2, 3]
columns = [0,0, 3, 4, 4]
print(spmatrix(elements, rows, columns))
[ 1.00e+00 0 0 0 0 ]
[ 2.00e+00 0 0 3.00e+00 0 ]
[ 0 0 0 0 4.00e+00]
Notice that the order doesnt mather, as long as the element,row,column are grouped together. Thus this would be equivalent.
elements = [4,2,3,1]
rows = [2,1,1,0]
columns = [4,0, 3,0]
print(spmatrix(elements, rows, columns))
[ 1.00e+00 0 0 0 0 ]
[ 2.00e+00 0 0 3.00e+00 0 ]
[ 0 0 0 0 4.00e+00]
What am I trying to create? (some_limit = 3)
This is basically a concatination of two lower triangual matrix, with a constant shift between its elements. So how would we describe this matrix?
If we focus on the "upper" lower triangual part which contains -1:s.
We can group as
element row column
-1 0 2
-1 1 2
-1 1 19
-1 2 2
-1 2 19
-1 2 36
The "lower" triangular part with only 1:s can be grouped as
We can group as
element row column
1 3 2
1 4 2
1 4 19
1 5 2
1 5 19
1 5 36
Together this become
element row column
-1 0 2
-1 1 2
-1 1 19
-1 2 2
-1 2 19
-1 2 36
1 3 2
1 4 2
1 4 19
1 5 2
1 5 19
1 5 36
Or,
element row column
-1 0 2
-1 1 2
-1 1 2 + 17
-1 2 2
-1 2 2 + 17
-1 2 2 + 2*17
1 1 + 2 2
1 2 + 2 2
1 2 + 2 2 + 17
1 3 + 2 2
1 3 + 2 2 + 17
1 3 + 2 2 + 2*17
Since the order doesnt mather, as long as element, row, column is grouped togethere, there might be a "better" pattern which I havent consider.
The size of this matrix is directly correlated with the number of elements in the list describing the elements, rows, and columns. I wish to have some_limit >=4343 => the lenght of each of the list elements, rows, and columns will be
(4343*(4343 + 1)/2)*2 which explodes quite fast...
some_limit
4343
len(list_1)
18865992
#size_of_matrix
<34744x73831 sparse matrix, tc='d', nnz=75463969>
You can convert your list comprehensions to generator expressions, then you do not have to create the entire list at once but can generate values as needed. In particular note the additional loop I added so that you do not have to create the entire list, then add a copy to itself.
i, j, limit, shift = 2, 0, 5, 10
gen_1 = (17 * x + i for _ in range(2) # repeat twice
for b in range(limit) # len of subsegments
for x in range(b+1)) # multiplier
gen_2 = (j + b + s for s in (0, 10) # repeat with shift
for b in range(limit) # len of subsegments
for _ in range(b+1)) # repeat b times
You can then either iterate the values as needed (or still create a list from all the values):
for x in gen_1:
print(x)
print(list(gen_2))
I'm trying to iterate through a loop with a step of 2 indexes at the time and once it reaches the end to restart the same but from index 1 this time rather than zero.
I have already read different articles on stack like this with a while loop workaround. However, I'm looking for an option which will simply use the element in my for loop with range and without using itertool or other libraries or a nested loop:
Here is my code:
j = [0,0,1,1,2,2,3,3,9,11]
count = 0
for i in range(len(j)):
if i >= len(j)/2:
print(j[len(j)-i])
count += 1
else:
count +=1
print(j[i*2],i)
Here is the output:
0 0
1 1
2 2
3 3
9 4
2
2
1
1
0
The loop does not start back from where is supposed to.
Here is the desired output:
0 0
1 1
2 2
3 3
9 4
0 5
1 6
2 7
3 8
11 9
How can I fix it?
You can do that by combining two range() calls like:
Code:
j = [0, 0, 1, 1, 2, 2, 3, 3, 9, 11]
for i in (j[k] for k in
(list(range(0, len(j), 2)) + list(range(1, len(j), 2)))):
print(i)
and using an itertools solution:
import itertools as it
for i in it.chain.from_iterable((it.islice(j, 0, len(j), 2),
it.islice(j, 1, len(j), 2))):
print(i)
Results:
0
1
2
3
9
0
1
2
3
11
Another itertools solution:
import itertools as it
lst = [0, 0, 1, 1, 2, 2, 3, 3, 9, 11]
a, b = it.tee(lst)
next(b)
for i, x in enumerate(it.islice(it.chain(a, b), None, None, 2)):
print(x, i)
Output
0 0
1 1
2 2
3 3
9 4
0 5
1 6
2 7
3 8
11 9