This is my first time coding. I'm doing it as ab elective module. I have to program an ai_player to go from playing randomly to winning and I'm stuck. Any advice would be appreciated. The game is Connect 4. i keep getting "object has no attribute" error.
import random
import time
def board():
for i in range(0, 8, 1):
for j in range(0, 10, 1):
board[i][j] = 0
return board
def move(board, valid_move):
start_time = time.time()
x = 0
while x == 0:
i = range(7, -1, -1)
j = range(0, 10, 1)
first_move = board[i][j]
board[7][4] = 1
if board[i-1][j] == 0: #above
first_move = [i, j]
x = 1
print " valid above"
return j
elif (board[i][j+1] == 0 and (i <= 7 and j <= 9)) or (board[i-1][j+1] == 0 and (i <= 7 and j <= 9)) or (board[i-1][j+1] == 0 and (i <= 7 and j <= 9)): #right
first_move = [i, (j+1)]
x = 1
print " valid right"
return (j+1)
elif board[i][j-1] == 0 or board[i-1][j-1] == 0 or board[i-1][j-1] == 0: #left
first_move = [i, (j-1)]
x = 1
print " valid left"
return (j-1)
else:
r = random.randint(0, 7)
c = random.randint(0, 9)
first_move = [r, c]
x = 1
print " random move"
return c
end_time = time.time() - start_time
print end_time
return first_move
File "F:/5. Fifth year/1st Semester/MPR 213 2016/Project 2016/attempts.py", line 20, in board
board[i][j] = 0
TypeError: 'function' object has no attribute '__getitem__'
It looks like you're trying to create a multidimensional list called board. This is not how you do that though, what you've actually done is created a function called board, and then you try to index that function, which fails since it's not a list.
To create board, use something like
board = [[0] * 10 for i in range(0, 8)]
Related
I am trying to get all solutions for a Mixed Integer program through ortools. I have two lists x and y of size 4. I want to get all solutions which satisfy sum(x) = 4 * sum(y). I created a function which takes list of past solutions as input and returns next solution. I am able to get only 2 solutions even though there are more. What am I doing wrong here?
I am expecting the following solutions
Solution 1:
xs1 = [0,0,0,0], ys1 = [0,0,0,0]
Solution 2:
xs2 = [4,0,0,0], ys2 = [1,0,0,0]
Solution 3:
xs3 = [0,4,0,0], ys3 = [1,0,0,0]
Solution 4:
xs4 = [0,0,4,0], ys4 = [0,0,1,0]
and soon on
from ortools.linear_solver import pywraplp
def opt(xs, ys):
solver = pywraplp.Solver.CreateSolver('SCIP')
infinity = solver.infinity()
# x and y are integer non-negative variables.
n = 4
M = 20
x = [0]* n
y = [0]* n
w = [[0]* n]*len(xs)
δ = [[0]* n]*len(xs)
for i in range(0,n):
x[i] = solver.IntVar(0, 20, 'x'+str(i))
y[i] = solver.IntVar(0, 20, 'y'+str(i))
for j in range(len(xs)):
w[j][i] = solver.IntVar(0, 20, 'zp'+str(j)+ '-' + str(i))
δ[j][i] = solver.IntVar(0, 1, 'δ'+str(j)+ '-' + str(i))
for j in (range(len(xs))):
for i in range(0,n):
solver.Add((w[j][i] - x[i] + xs[j][i]) >=0)
solver.Add((w[j][i] - x[i] + xs[j][i]) <= M*(1-δ[j][i]))
solver.Add((w[j][i] + x[i] - xs[j][i]) >=0)
solver.Add((w[j][i] + x[i] - xs[j][i]) <= M*δ[j][i])
for j in range(len(xs)):
solver.Add(solver.Sum([w[j][i] for i in range(0,n)]) >= 1)
solver.Add(solver.Sum([x[i] for i in range(0, n)]) - 4 * solver.Sum([y[i] for i in range(0, n)]) == 0)
solver.Minimize(solver.Sum([x[i] for i in range(0, n)]))
status = solver.Solve()
if status == pywraplp.Solver.OPTIMAL:
solver_x = [0]*n
solver_y = [0]*n
for i in range(0,n):
solver_x[i] = x[i].solution_value()
solver_y[i] = y[i].solution_value()
return ([solver_x, solver_y, solver.Objective().Value()])
else:
print('No Solution')
return ([[0], [0]], -1)
psx = [[0,0,0,0], [0,4,0,0]]
psy = [[0,0,0,0], [1,0,0,0]]
ns = opt(psx, psy)
print(ns)
Output:
No Solution
([[0], [0]], -1)
Reference:
Finding multiple solutions to general integer linear programs
How to write constraints for sum of absolutes
If you have a pure integer programming model, you can use the CP-SAT solver which allows you to print all the solutions [See this].
I'm trying to plot two files of data of this type:
name1.fits 0 0 2.40359218172
name2.fits 0 0 2.15961244263
The third column has values from 0 to 5. I want to plot column 2 vs column 4, but, for lines with values in col 3 less than 2 (0 and 1), I want to shift col 2 by -0.1, and for lines with values greater than 3 (4 and 5) I want to shift col 2 by +0.1.
However my code seems to be shifting all values by +0.1. Here is what I have so far:
import matplotlib.pyplot as plt
import numpy as np
with open('file1.txt') as data, open('file2.txt') as stds:
lines1 = data.readlines()
lines2 = stds.readlines()
x1a = []
x2a = []
x1b = []
x2b = []
x1c = []
x2c = []
y1a = []
y2a = []
y1b = []
y2b = []
y1c = []
y2c = []
for line1 in lines1:
p = line1.split()
if p[2] < 2:
x1a.append(float(p[1]))
y1a.append(float(p[3]))
elif 1 < p[2] < 4:
x1b.append(float(p[1]))
y1b.append(float(p[3]))
elif p[2] > 3:
x1c.append(float(p[1]))
y1c.append(float(p[3]))
for line2 in lines2:
q = line2.split()
if q[2] < 2:
x2a.append(float(q[1]))
y2a.append(float(q[3]))
elif 1 < q[2] < 4:
x2b.append(float(q[1]))
y2b.append(float(q[3]))
elif q[2] > 3:
x2c.append(float(q[1]))
y2c.append(float(q[3]))
x1a = np.array(x1a)
x2a = np.array(x2a)
x1b = np.array(x1b)
x2b = np.array(x2b)
x1c = np.array(x1c)
x2c = np.array(x2c)
y1a = np.array(y1a)
y2a = np.array(y2a)
y1b = np.array(y1b)
y2b = np.array(y2b)
y1c = np.array(y1c)
y2c = np.array(y2c)
minorLocator = AutoMinorLocator(5)
fig, ax = plt.subplots(figsize=(8, 8))
fig.subplots_adjust(left=0.11, right=0.95, top=0.94)
plt.plot(x1a-0.1,y1a,'b^',mec='blue',label=r'B0',ms=8)
plt.plot(x2a-0.1,y2a,'r^',mec='red',fillstyle='none',mew=0.8,ms=8)
plt.plot(x1b,y1b,'bo',mec='blue',label=r'B0',ms=8)
plt.plot(x2b,y2b,'ro',mec='red',fillstyle='none',mew=0.8,ms=8)
plt.plot(x1c+0.1,y1c,'bx',mec='blue',label=r'B0',ms=8)
plt.plot(x2c+0.1,y2c,'rx',mec='red',fillstyle='none',mew=0.8,ms=8)
plt.axis([-1.0, 3.0, 0., 4])
ax.xaxis.set_tick_params(labeltop='on')
ax.yaxis.set_minor_locator(minorLocator)
plt.show()
Here is the plot:
plot
I'm pretty sure the problem is in my "ifs". I hope you can clear the way and/or show me a better option for this.
When you do your queries (if) you must ensure the conversion happens before the question so:
for line1 in lines1:
p = line1.split()
if p[2] < 2:
x1a.append(float(p[1]))
y1a.append(float(p[3]))
elif 1 < p[2] < 4:
x1b.append(float(p[1]))
y1b.append(float(p[3]))
elif p[2] > 3:
x1c.append(float(p[1]))
y1c.append(float(p[3]))
, should actually be:
for line1 in lines1:
p = line1.split()
if float(p[2]) < 2: # changed here
x1a.append(float(p[1]))
y1a.append(float(p[3]))
elif 1 < float(p[2]) < 4: # There seems to be a problem with this if
x1b.append(float(p[1]))
y1b.append(float(p[3]))
elif float(p[2]) > 3: # changed here
x1c.append(float(p[1]))
y1c.append(float(p[3]))
The same for your q variables. Also notice that asking 1 < x < 4 will intercept with x > 3 and x < 2. You should also correct this.
I am trying to implement the merge sort algorithm using the following code but am getting a list index is out of range error.
def mergeSort (unSortedList):
if len(unSortedList) == 1 :
return unSortedList
else:
midpoint = len(unSortedList)//2
A = mergeSort (unSortedList[:midpoint] )
B = mergeSort (unSortedList[midpoint:] )
i = 0
j = 0
C = []
for k in range(len(unSortedList)):
if A[i] >= B[j]:
C.append(A[i])
if i == len(A):
C.append(B[j:])
else:
i += 1
elif A[i] < B[j] :
C.append(B[j])
if j == len(B):
C.append(A[i:])
else:
j += 1
return C
testlist = [2,1,4,2,5,6,8,9]
print (mergeSort(testlist))
Any help would be appreciated.
Here is my version of your mergeSort, with the merge function extracted:
def mergeSort (unSortedList):
if len(unSortedList) == 1 :
return unSortedList
else:
midpoint = len(unSortedList)//2
A = mergeSort (unSortedList[:midpoint] )
B = mergeSort (unSortedList[midpoint:] )
return merge(A, B)
def merge(a, b):
i = 0
j = 0
c = []
while True:
if a[i] < b[j]:
c.append(b[j])
j += 1
elif a[i] >= b[j]:
c.append(a[i])
i += 1
if i == len(a):
c.extend(b[j:])
break
if j == len(b):
c.extend(a[i:])
break
return c
Output:
>>> testlist = [2,1,4,2,5,6,8,9]
>>> mergeSort(testlist)
[9, 8, 6, 5, 4, 2, 2, 1]
Couple of things to note:
Appending a list to a list. When you do C.append(A[j:]) you end up with nested lists. That is because A[j:] always returns a list. You either need to use list addition - C += A[j:] - or call extend - C.extend(A[j:])
Missing breaks. When your i or j got to the end of their lists you correctly appended the rest of the other list but you did not terminate the loop. That is what caused the range error because in the next iteration (which should not happen) you tried to get an item at the index equal to the length of the list which is out of range.
for merge sort i wrote this code:
I have tested merge function that works correctly. but in mergeSort function i coudn't handle the arrays. it returns the same list as the input list.
def mergeSort(a):
l, h = 0, len(a)-1
mid = (l+h)/2
if (l<h-1): #the lowest length must be 2
mergeSort(a[l:mid+1])
mergeSort(a[mid+1:h+1])
return merge(a[l:mid+1],a[mid+1:h+1])
def merge(a,b):
n_a = len(a)
n_b = len(b)
c = [[] for i in range(n_a + n_b)]
i,j,k=0,0,0
while (i<n_a and j<n_b):
if a[i]<b[j]:
c[k] = a[i]
i += 1
else:
c[k]= b[j]
j += 1
k += 1
while(i<n_a):
c[k] = a[i]
k+=1
i+=1
while(j< n_b):
c[k] = b[j]
k+=1
j+=1
return c
I would rewrite merge as so:
def mergeSort(a):
h = len(a)
mid = h / 2
if h >= 2:
return merge(mergeSort(a[:mid]), mergeSort(a[mid:]))
else:
return a
A few notes:
l is always 0, might as well remove it
h is len(a) - 1, but then you use h + 1, might as well use h = len(a)
Actually writting h >= 2 makes it clearer that you need at least 2 items in your list
mid can be len(a) / 2.
when taking the complete beginning/end of an array in a slice, the first/last bound is not required
I am trying to build an efficient function for splitting a list of any size by any given number of indices. This method works and it took me a few hours to get it right (I hate how easy it is to get things wrong when using indexes)
Am I over-thinking this?
Code:
def lindexsplit(List,*lindex):
index = list(lindex)
index.sort()
templist1 = []
templist2 = []
templist3 = []
breakcounter = 0
itemcounter = 0
finalcounter = 0
numberofbreaks = len(index)
totalitems = len(List)
lastindexval = index[(len(index)-1)]
finalcounttrigger = (totalitems-(lastindexval+1))
for item in List:
itemcounter += 1
indexofitem = itemcounter - 1
nextbreakindex = index[breakcounter]
#Less than the last cut
if breakcounter <= numberofbreaks:
if indexofitem < nextbreakindex:
templist1.append(item)
elif breakcounter < (numberofbreaks - 1):
templist1.append(item)
templist2.append(templist1)
templist1 = []
breakcounter +=1
else:
if indexofitem <= lastindexval and indexofitem <= totalitems:
templist1.append(item)
templist2.append(templist1)
templist1 = []
else:
if indexofitem >= lastindexval and indexofitem < totalitems + 1:
finalcounter += 1
templist3.append(item)
if finalcounter == finalcounttrigger:
templist2.append(templist3)
return templist2