So far I have this code that displays the 92 solutions for an 8x8 board for the N-Queens problem. Instead of displaying ALL 92 solutions, I am wanting to try and get it to just display 1 random solution each time it is ran. How can I do this?
import sys
from ortools.constraint_solver import pywrapcp
# by default, solve the 8x8 problem
n = 8 if len(sys.argv) < 2 else int(sys.argv[1])
# creates the solver
solver = pywrapcp.Solver("n-queens")
# creates the variables
# the array index is the row, and the value is the column
queens = [solver.IntVar(0, n - 1, "x%i" % i) for i in range(n)]
# creates the constraints
# all columns must be different
solver.Add(solver.AllDifferent(queens))
# no two queens can be on the same diagonal
solver.Add(solver.AllDifferent([queens[i] + i for i in range(n)]))
solver.Add(solver.AllDifferent([queens[i] - i for i in range(n)]))
# tells solver what to solve
db = solver.Phase(queens, solver.CHOOSE_MIN_SIZE_LOWEST_MAX, solver.ASSIGN_CENTER_VALUE)
solver.NewSearch(db)
# iterates through the solutions
num_solutions = 0
while solver.NextSolution():
queen_columns = [int(queens[i].Value()) for i in range(n)]
# displays the solutions
for i in range(n):
for j in range(n):
if queen_columns[i] == j:
print "Q",
else:
print "_",
print
print
num_solutions += 1
solver.EndSearch()
print
print "Solutions found:", num_solutions
Generate the list of solutions, then pick one:
solutions = []
while solver.NextSolution():
queen_columns = [int(queens[i].Value()) for i in range(n)]
solutions.append(queen_columns)
import random
queen_columns = random.choice(solutions)
Related
As a newbie to python, I've come across a task that I'm having trouble completing. I am supposed to create a new matrix, taking into consideration the original one, inputted by the user, where each element corresponds to the number of adjacent elements greater or equal to the corresponding one in the original matrix. Since English is not my native language, I might not have presented it properly so here is an example:
input:
3x3 matrix
9 14 13
3 0 7
8 15 15
output:
3x3 matrix
2 5 2
1 0 1
2 5 3
So, if it isn't clear, the new matrix determines how many adjacent elements are greater or equal to an element in the original one. 9 is greater than 3 & 0, so that results in "2", 14 is greater than all the adjacent ones so it prints out "5", etc... It also takes diagonals into consideration, of course.
So far, I've got down the input of the original matrix but I'm unsure how to proceed further. I am not someone who's got access to university materials, professors or peer help and my experimentation and search online has been futile so far. I do not need a complete solution, rather than pointers and concept explanation.
This is the code so far:
# matrix input
rOne = int(input("Number of rows:"))
cOne = int(input("Number of columns:"))
# initialize matrix
matrixOne = []
print("Enter elements rowwise:")
# user input
for i in range(rOne): # for loop za redove
a =[]
for j in range(cOne): # for loop za kolone
a.append(int(input()))
matrixOne.append(a)
# print matrix one
for i in range(rOne):
for j in range(cOne):
print(matrixOne[i][j], end = " ")
print()
Here is a function that can do the exact thing:
def adj_matrix(matrixOne, rOne, cOne):
new_lst = []
for i in range(rOne):
a = []
for j in range(cOne):
count = 0
x, y = (i, j) # matrix values here
cells = list(starmap(lambda a,b: (x+a, y+b), product((0,-1,+1), (0,-1,+1)))) # this will find all the adjacent index
filtered_cell = [p for p in cells if (sum(p)>=0 and prod(p)>=0)] # this filters out all the negative indexs
filtered_cell = [p for p in filtered_cell if p[0]<rOne and p[1]<cOne] # this filters out index that are greater than matrix
for z in filtered_cell:
if matrixOne[i][j] >= matrixOne[z[0]][z[1]]:
count += 1
a.append(count-1)
new_lst.append(a)
return new_lst
also import:
from itertools import product, starmap
from math import prod
Actually managed to solve the thing, feels amazing :D
def get_neighbor_elements(current_row, current_col, total_rows, total_cols):
neighbors = []
for i in [-1, 0, 1]: # red pre, isti red, red posle
for j in [-1, 0, 1]: # kolona pre, ista kolona, kolona posle
row = current_row + i
col = current_col + j
if row < 0 or col < 0 or row >= total_rows or col >= total_cols: # preskace se ako se izaslo iz granica matrice
continue
if row == current_row and col == current_col:# ako su red i kolona isti, preskace se(to je taj isti element)
continue
neighbor = [row, col]
neighbors.append(neighbor)
return neighbors
def make_new_matrix(old_matrix):
new_matrix = []
for i in range(len(old_matrix)):
new_matrix.append([])
for i in range(len(old_matrix)): # iteriramo kroz redove stare matrice
for j in range(len(old_matrix[i])): # iteriramo kroz kolone stare matrice
neighbors = get_neighbor_elements(i, j, len(old_matrix), len(old_matrix[i])) # dobavljamo komsije
count = 0
for neighbor in neighbors: # sad gledamo da li je trenutni element veci ili jednak susednim
if old_matrix[i][j] >= old_matrix[neighbor[0]][neighbor[1]]:
count += 1
new_matrix[i].append(count)
return new_matrix
def print_matrix(matrix):
for i in range(len(matrix)):
for j in range(len(matrix[i])):
print(str(matrix[i][j]) + " ", end='')
print()
if __name__ == '__main__':
matrix = [[12, 10], [2, 10]]
print("Old matrix: ")
print_matrix(matrix)
new_matrix = make_new_matrix(matrix)
print("New matrix")
print_matrix(new_matrix)
I am doing the Project Euler #67 in Python. My program, which worked for Project 18, does not work for Project 67.
Code (excludes the opening of the file and the processing of information):
for i in range(len(temp)):
list1 = temp[i]
try:
list2 = temp[i+1]
trynum1 = list1[lastinput] + max(list2[lastinput],list2[lastinput+1])
try:
trynum2 = list1[lastinput+1] + max(list2[lastinput+1],list2[lastinput+2])
if trynum1 > trynum2:
outputlist.append(list1[lastinput])
else:
outputlist.append(list1[lastinput+1])
lastinput += 1
except IndexError:
outputlist.append(list1[0])
except IndexError:
if list1[lastinput] > list1[lastinput+1]:
outputlist.append(list1[lastinput])
else:
outputlist.append(list1[lastinput+1])
Variables:
temp is the triangle of integers
outputlist is a list which stores the numbers chosen by the program
I know the answer is 7273, but my program finds 6542. I cannot find an error which causes the situation. Please may you help me on it.
Logic
My approach to this program is to find one number (list1[lastinput]) and add it up with the larger number of the two below it (trynum1), compare with the number to the right of the first number (list1[lastinput+1]), adding the larger number of two below it (trynum2). I append the larger one to the output list.
This approach is logically flawed. When you're in row 1, you don't have enough information to know whether moving right or left will lead you to the largest sum, not with only a 2-row lookahead. You would need to look all the way to the bottom to ensure getting the best path.
As others have suggested, start at the bottom and work up. Remember, you don't need the entire path, just the sum. At each node, add the amount of the better of the two available paths (that's the score you get in taking that node to the bottom). When you get back to the top, temp[0][0], that number should be your final answer.
I thought day and night about problem 18 and I solved it, the same way I solved this one.
P.S. 100_triangle.txt is without 1st string '59'.
# Maximum path sum II
import time
def e67():
start = time.time()
f=open("100_triangle.txt")
summ=[59]
for s in f:
slst=s.split()
lst=[int(item) for item in slst]
for i in range(len(lst)):
if i==0:
lst[i]+=summ[i]
elif i==len(lst)-1:
lst[i]+=summ[i-1]
elif (lst[i]+summ[i-1])>(lst[i]+summ[i]):
lst[i]+=summ[i-1]
else:
lst[i]+=summ[i]
summ=lst
end = time.time() - start
print("Runtime =", end)
f.close()
return max(summ)
print(e67()) #7273
Though starting from the bottom is more efficient, I wanted to see if I could implement Dijkstra's algorithm on this one; it works well and only takes a few seconds (didn't time it precisely):
from math import inf
f = open("p067_triangle.txt", "r")
tpyramid = f.read().splitlines()
f.close()
n = len(tpyramid)
pyramid = [[100 - int(tpyramid[i].split()[j]) for j in range(i+1)] for i in range(n)]
paths = [[inf for j in range(i+1)] for i in range(n)]
paths[0][0] = pyramid[0][0]
def mini_index(pyr):
m = inf
for i in range(n):
mr = min([i for i in pyr[i] if i >= 0]+[inf])
if mr < m:
m, a, b = mr, i, pyr[i].index(mr)
return m, a, b
counter = 0
omega = inf
while counter < n*(n+1)/2:
min_weight, i, j = mini_index(paths)
if i != n-1:
paths[i+1][j] = min( paths[i+1][j], min_weight + pyramid[i+1][j])
paths[i+1][j+1] = min( paths[i+1][j+1], min_weight + pyramid[i+1][j+1])
else:
omega = min(omega, min_weight)
paths[i][j] = -1
counter += 1
print(100*n - omega)
Here is my solution. Indeed you have to take the bottom - up approach.
Result confirmed with PE. Thanks!
def get_triangle(listLink):
triangle = [[int(number) for number in row.split()] for row in open(listLink)]
return triangle
listOfLists = get_triangle('D:\\Development\\triangle.txt')
for i in range(len(listOfLists) - 2, -1, -1):
for j in range(len(listOfLists[i])):
listOfLists[i][j] += max(listOfLists[i+1][j], listOfLists[i+1][j+1])
print(listOfLists[0][0])
Think of the Unit Circle x 2. What I have done is create two lists, one for x and one for y, producing 500 pairs of random (x,y). Then I created r=x2+y2 in my while loop, where r is the radius and x2=x**2 and y2=y**2. What I want to be able to do is count the number of times r=<2. I assume my if statement needs to be in the while loop, but I don't know how to actually count the number of times the condition r=<2is met. Do I need to create a list for the r values?
import random
from math import *
def randomgen(N):
rlg1=[]
rlg2=[]
a=random.randint(0,N)
b=float(a)/N
return b
i=0
rlg=[]
rlg2=[]
countlist=[]
while i<500:
x=randomgen(100)*2
y=randomgen(100)*2
x2=x**2
y2=y**2
r=x2+y2
rlg.append(x)
rlg2.append(y)
print rlg[i],rlg2[i]
i+=1
if r<=2:
import random
from math import *
def randomgen(N):
rlg1=[]
rlg2=[]
a=random.randint(0,N)
b=float(a)/N
return b
i=0
rlg=[]
rlg2=[]
countlist=[]
amount = 0
while i<500:
x=randomgen(100)*2
y=randomgen(100)*2
x2=x**2
y2=y**2
r=x2+y2
rlg.append(x)
rlg2.append(y)
print rlg[i],rlg2[i]
i+=1
if r<=2:
amount += 1
You need two counters here. One for the total number of points (i) and one for the number of points that lie within your circle r <= 2 (I'm calling this one isInside). You only want to increment the isInside counter if the point lies within your circle (r <= 2).
i = 0
rlg = []
rlg2 = []
countlist = []
isInside = 0
while i < 500:
x=randomgen(100)*2
y=randomgen(100)*2
x2=x**2
y2=y**2
r=x2+y2
rlg.append(x)
rlg2.append(y)
print rlg[i],rlg2[i]
i+=1
if r <= 2:
# increment your isInside counter
isInside += 1
I'm making the game of life and I want to have a window (in my code called Grid) that is refreshing with the 2nd Grid (called SecGrid) information
import numpy as np
import pylab as pl
from random import randint
i = 0
o = 0
#Chose Grid size
m = int(input("Enter the width and length of the Grid: ",))
n = m
print("Your Grid will be",m,"x",n)
Grid = np.zeros((m+2,n+2))
SecGrid = np.zeros((m+2,n+2))
#Random /Grid filling in
while(i <= n/3*m):
i = i+1
Grid[randint(1,m), randint(1,n)] = 1
img = pl.imshow(Grid, cmap = 'PuRd', interpolation = 'none')
#Main algo
while (o < 2):
print(o)
v = input("continue: ")
o = o + 1
for i in range(1,m):
for j in range(1,n):
#Nbr of entities
nbr = 0
for k in range(-1,1):
for l in range(-1,1):
nbr = nbr + Grid[i+k,j+l]
#cells that are alive
if Grid[i,j] == 1:
if nbr > 1 and nbr < 4:
SecGrid[i,j] = 1
else:
SecGrid[i,j] = 0
#cells that are dead
else:
if nbr == 3:
SecGrid[i,j] = 1
else:
SecGrid[i,j] = 0
How can I refresh my grid with new information ?
I tried this
Grid = SecGrid
pl.draw(img)
img.set_data(Grid)
But I new to python so I have no clue ._. pls help meh :3
The pylab draw method does not take any arguments. Take a look at the draw documentation running python from the command line.
For example:
$ python
>>> import pylab as pl
>>> help(pl.draw)
In regards to your question "How can I refresh my grid with new information ?", as you are updating values in your Grid below your "Random /Grid filling in" comment I will assume that your asking how to update that data in your img object. If so, see the following:
# Note: entered in your code line by line into python at command line then
>>> help(img.set_data)
Help on method set_data in module matplotlib.image:
set_data(self, A) method of matplotlib.image.AxesImage instance
Set the image array
ACCEPTS: numpy/PIL Image A
I am stuck in a code in python which takes in number of dices and number of rolls and returns the sum of numbers obtained. It should also print the histogram of the sum. I am stuck in the first part of the code. Can someone help me fix this? Not sure where i am going wrong. Any help for the second part (returning histogram) would be helpful for me to learn it in python.
from random import choice
def roll(rolls,dice):
d = []
for _ in range(rolls):
d[sum(choice(range(1,7)) for _ in range(dice))] += 1
return(d)
Your problem here is that you can't arbitrarily index into an empty list:
l = []
l[13] += 1 # fails with IndexError
Instead, you could use a defaultdict, which is a special type of dictionary that doesn't mind if a key hasn't been used yet:
from collections import defaultdict
d = defaultdict(int) # default to integer (0)
d[13] += 1 # works fine, adds 1 to the default
or Counter, which is designed for cases like this ("provided to support convenient and rapid tallies") and provides extra handy functions (like most_common(n), to get the n most common entries):
from collections import Counter
c = Counter()
c[13] += 1
To manually use a standard dict to do this, just add a check:
d = {}
if 13 in d: # already there
d[13] += 1 # increment
else: # not already there
d[13] = 1 # create
Try this,
from random import choice
import pylab
def roll( rolls, dice ):
s = list()
for d in range( dice ):
for r in range( rolls ):
s.append( choice( range(1,7) ) )
return s
s = roll( rolls, dice )
sum_of_rolls = sum( s )
# then to plot..
pylab.hist( s )
This should do it
import random
def rolls(N, r): # N=number of dice. r=number of rolls
myDie = [1,2,3,4,5,6]
answer = {}
for _rolling in range(r):
rolls = []
for _die in range(N):
rolls.append(random.choice(myDie))
total = 0
for roll in rolls:
total += roll
if total not in answer:
answer[total] = 0
answer[total] += 1
return answer