I am currently finishing a hackerrank challenge. The solution I wrote works for half the test but fail for the other tests. I noticed that when manually adding the numbers, it does not equal to the expected answer. For example, in the test data below, I can't find any combinations that adds to the expected output.
I tried debugging it manually and using pdb but I do not recognize the problem.
Here is the test data :
1 1 1 0 0 0
0 1 0 0 0 0
1 1 1 0 0 0
0 9 2 -4 -4 0
0 0 0 -2 0 0
0 0 -1 -2 -4 0
Here is the expected output :
13
Here is the script :
#!/bin/python3
def get_hourglasses(array):
hourglasses = list()
row_list = list()
# Extract rows
for row in range(len(array)):
for col in range(len(array[row])):
try:
to_append = [array[row][col], array[row][col+1], array[row][col+2]]
row_list.append(to_append)
except IndexError:
break
# Construct hourglass
for row in range(len(row_list)):
try:
hourglass = [row_list[row], row_list[row+4], row_list[row+8]]
hourglasses.append(hourglass)
except:
break
return hourglasses
def get_maximum_hourglass_sum(array):
hourglass_sums = list()
hourglasses = get_hourglasses(array)
# add all the hourglasses
sums = int()
for hourglass in hourglasses:
hourglass_sums.append(sums)
sums = 0
for row in hourglass:
sums += sum(row)
return sorted(hourglass_sums)[-1]
if __name__ == '__main__':
arr = []
for _ in range(6):
arr.append(list(map(int, input().rstrip().split())))
print(get_maximum_hourglass_sum(arr))
I agree with #Barmar, and thus I understand your misunderstanding.
However, correct me if I'm wrong but I have some doubts about your get_maximum_hourglass_sum function because it seems to me that you are actually taking all of the middle row of an hourglass into account (instead of taking only the middle point)
PS : I ran your code on hackerank and I failed most of the test due to RunTimeError though
Related
I am assigning stations to tasks with different types of stations/machines, where every station can have exactly one of the types available. My problem is that in the solution point Output I get the following:
# Objective value = 8.0028043478260865e+04
y[1,BTC1] 0
y[1,BOC1] 1
y[2,BTC1] 0
y[2,BOC1] 1
y[3,BTC1] 1
y[3,BOC1] 0
x[1,BTC1,w01] 0.5
x[1,BTC1,w02] 2.1739130434782608e-01
x[1,BTC1,w03] 0
x[1,BOC1,w01] 0
x[1,BOC1,w02] 0
x[1,BOC1,w03] 0
x[2,BTC1,w01] 0.5
x[2,BTC1,w02] 2.1739130434782608e-01
x[2,BTC1,w03] 0
x[2,BOC1,w01] 0
x[2,BOC1,w02] 0
x[2,BOC1,w03] 0
x[3,BTC1,w01] 0
x[3,BTC1,w02] 5.6521739130434789e-01
x[3,BTC1,w03] 0
x[3,BOC1,w01] 0
x[3,BOC1,w02] 0
x[3,BOC1,w03] 1
Note: [station,type,task]. My problem is now that there is a assignment to x [1,BTC1,'w01'] for example but indeed the station y[1,BTC1] doesnt even exist. Therefore it should not be possible to assign anything like x [1,BTC1,every task]. To avoid this I thought of making a if staitment.
In python gurobi I saw many articles of how to implement if to constraints and I know that it is not possible in a direct way. In the examples I saw something like if x >= y do this and else do this. But for my problem I need to say if y[i,j] == 0 than x[i,j,k] should be also 0 and if y != 0 than x is also != 0. So with this I want to ensure that no assignment to x is made until the y variable is not 1 for that exact combination of station and type. How would I do this?
How do I find the rows(indices) of my array, where its values change?
for example I have an array:
0 -0.638127 0.805294 1.30671
1 -0.638127 0.805294 1.30671
2 -0.085362 0.523378 0.550509
3 -0.085362 0.523378 0.550509
4 -0.323397 0.94502 0.49001
5 -0.323397 0.94502 0.49001
6 -0.323397 0.94502 0.49001
7 -0.291798 0.421398 0.962115
I want a result like:
[0 2 4 7]
I am happy to use existing librarys and I am not limited to anything. All I want are the numbers of the rows. How would I calculate that?
I tried
a = []
for i, row in enumerate(vecarray):
if i > 0:
a[i] = vecarray[i] - vecarray[i-1]
b = np.where(a != 0)
but that gives me IndexError: list assignment index out of range
arr = [
(-0.638127, 0.805294, 1.30671),
(-0.638127, 0.805294, 1.30671),
(-0.085362, 0.523378, 0.550509),
(-0.085362, 0.523378, 0.550509),
(-0.323397, 0.94502, 0.49001),
(-0.323397, 0.94502, 0.49001),
(-0.323397, 0.94502, 0.49001),
(-0.291798, 0.421398, 0.962115)
]
i = 0
prev_t = None
for t in arr:
if t != prev_t:
prev_t = t
print(i)
i += 1
I have a constraint problem that I'm trying to solve with python-constraint
So let's say I have 3 locations: loc1,...loc3
Also, I have 7 devices: device1,...device7
Max amount of devices in each location: loc1:3, loc2:4, loc3:2
(for example maximum of 3 devices in loc1 and so on...)
And some constraints about the locations and the devices:
loc1: device1, device3, device7,
loc2: device1, device3, device4, device5, device6, device7
loc3: device2, device4, device5, device6
(meaning for example only device1, device3 and device7 can be in loc1.)
I'm trying to get a set of possible options for devices in locations.
from constraint import *
problem = Problem()
for key in locations_devices_dict:
problem.addVariable(key,locations_devices_dict[key])
# problem.addVariable("loc1", ['device1', 'device3', 'device7'])
problem.addConstraint(AllDifferentConstraint())
and I'm stuck on how to do the constrains. I've tried:
problem.addConstraint(MaxSumConstraint(3), 'loc1')
but it doesn't work, MaxSumConstraint does not sum what I need.
All devices must be placed somewhere
possible solution:
loc1: device1, device3
loc2: device4, device6, device7
loc3: device2, device5
Anyone has an idea?
(another python package/not to use any package, is also good idea if someone has any suggestions...)
This is simple assignment-like model:
So we have a binary variable indicating if device d is assigned to location L. The linear constraints are just:
assign each device to one location
each location has a maximum number of devices
make sure to use only allowed assignments (modeled above by allowed(L,d))
This problem can be handled by any constraint solver.
Enumerating all possible solutions is a bit dangerous. For large instances there are just way too many. Even for this small problem we already have 25 solutions:
For large problems this number will be astronomically large.
Using the Python constraint package this can look like:
from constraint import *
D = 7 # number of devices
L = 3 # number of locations
maxdev = [3,4,2]
allowed = [[1,3,7],[1,3,4,5,6,7],[2,4,5,6]]
problem = Problem()
problem.addVariables(["x_L%d_d%d" %(loc+1,d+1) for loc in range(L) for d in range(D) if d+1 in allowed[loc]],[0,1])
for loc in range(L):
problem.addConstraint(MaxSumConstraint(maxdev[loc]),["x_L%d_d%d" %(loc+1,d+1) for d in range(D) if d+1 in allowed[loc]])
for d in range(D):
problem.addConstraint(ExactSumConstraint(1),["x_L%d_d%d" %(loc+1,d+1) for loc in range(L) if d+1 in allowed[loc]])
S = problem.getSolutions()
n = len(S)
n
For large problems you may want to use dicts to speed things up.
edit: I wrote this answer before I saw #ErwinKalvelagen's code. So I did not check his solution...
So I used #ErwinKalvelagen approach and created a matrix that represented the probelm.
for each (i,j), x[i,j]=1 if device i can go to location j, 0 otherwise.
Then, I used addConstraint(MaxSumConstraint(maxAmount[i]), row) for each row - this is the constraint that represent the maximum devices in each location.
and addConstraint(ExactSumConstraint(1), col) for each column - this is the constraint that each device can be placed only in one location.
next, I took all x[i,j]=0 (device i can not be in location j) and for each t(i,j) addConstraint(lambda var, val=0: var == val, (t,))
This problem is similar to the sudoku problem, and I used this example for help
The matrix for my example above is:
(devices:) 1 2 3 4 5 6 7
loc1: 1 0 1 0 0 0 1
loc2: 1 0 1 1 1 1 1
loc3: 0 1 0 1 1 1 0
My code:
problem = Problem()
rows = range(locations_amount)
cols = range(devices_amount)
matrix = [(row, col) for row in rows for col in cols]
problem.addVariables(matrix, range(0, 2)) #each cell can get 0 or 1
rowSet = [zip([el] * len(cols), cols) for el in rows]
colSet = [zip(rows, [el] * len(rows)) for el in cols]
rowsConstrains = getRowConstrains() # list that has the maximum amount in each location(3,4,2)
#from my example: loc1:3, loc2:4, loc3:2
for i,row in enumerate(rowSet):
problem.addConstraint(MaxSumConstraint(rowsConstrains[i]), row)
for col in colSet:
problem.addConstraint(ExactSumConstraint(1), col)
s = getLocationsSet() # set that has all the tuples that x[i,j] = 1
for i, loc in enumerate(locations_list):
for j, iot in enumerate(devices_list):
t=(i,j)
if t in s:
continue
problem.addConstraint(lambda var, val=0: var == val, (t,)) # the value in these cells must be 0
solver = problem.getSolution()
example for a solution:
(devices:) 1 2 3 4 5 6 7
loc1: 1 0 1 0 0 0 1
loc2: 0 0 0 1 1 1 0
loc3: 0 1 0 0 0 0 0
I started learning Python < 2 weeks ago.
I'm trying to make a function to compute a 7 day moving average for data. Something wasn't going right so I tried it without the function.
moving_average = np.array([])
i = 0
for i in range(len(temp)-6):
sum_7 = np.array([])
avg_7 = 0
missing = 0
total = 7
j = 0
for j in range(i,i+7):
if pd.isnull(temp[j]):
total -= 1
missing += 1
if missing == 7:
moving_average = np.append(moving_average, np.nan)
break
if not pd.isnull(temp[j]):
sum_7 = np.append(sum_7, temp[j])
if j == (i+6):
avg_7 = sum(sum_7)/total
moving_average = np.append(moving_average, avg_7)
If I run this and look at the value of sum_7, it's just a single value in the numpy array which made all the moving_average values wrong. But if I remove the first for loop with the variable i and manually set i = 0 or any number in the range of the data set and run the exact same code from the inner for loop, sum_7 comes out as a length 7 numpy array. Originally, I just did sum += temp[j] but the same problem occurred, the total sum ended up as just the single value.
I've been staring at this trying to fix it for 3 hours and I'm clueless what's wrong. Originally I wrote the function in R so all I had to do was convert to python language and I don't know why sum_7 is coming up as a single value when there are two for loops. I tried to manually add an index variable to act as i to use it in the range(i, i+7) but got some weird error instead. I also don't know why that is.
https://gyazo.com/d900d1d7917074f336567b971c8a5cee
https://gyazo.com/132733df8bbdaf2847944d1be02e57d2
Hey you can using rolling() function and mean() function from pandas.
Link to the documentation :
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.rolling.html
df['moving_avg'] = df['your_column'].rolling(7).mean()
This would give you some NaN values also, but that is a part of rolling mean because you don't have all past 7 data points for first 6 values.
Seems like you misindented the important line:
moving_average = np.array([])
i = 0
for i in range(len(temp)-6):
sum_7 = np.array([])
avg_7 = 0
missing = 0
total = 7
j = 0
for j in range(i,i+7):
if pd.isnull(temp[j]):
total -= 1
missing += 1
if missing == 7:
moving_average = np.append(moving_average, np.nan)
break
# The following condition should be indented one more level
if not pd.isnull(temp[j]):
sum_7 = np.append(sum_7, temp[j])
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if j == (i+6):
# this ^ condition does not do what you meant
# you should use a flag instead
avg_7 = sum(sum_7)/total
moving_average = np.append(moving_average, avg_7)
Instead of a flag you can use a for-else construct, but this is not readable. Here's the relevant documentation.
Shorter way to do this:
moving_average = np.array([])
for i in range(len(temp)-6):
ngram_7 = [t for t in temp[i:i+7] if not pd.isnull(t)]
average = (sum(ngram_7) / len(ngram_7)) if ngram_7 else np.nan
moving_average = np.append(moving_average, average)
This could be refactored further:
def average(ngram):
valid = [t for t in temp[i:i+7] if not pd.isnull(t)]
if not valid:
return np.nan
return sum(valid) / len(valid)
def ngrams(seq, n):
for i in range(len(seq) - n):
yield seq[i:i+n]
moving_average = [average(k) for k in ngrams(temp, 7)]
How can I write a filter for python imaging library for pgm plain ascii format (P2). Problem here is that basic PIL filter assumes constant number of bytes per pixel.
My goal is to open feep.pgm with Image.open(). See http://netpbm.sourceforge.net/doc/pgm.html or below.
Alternative solution is that I find other well documented ascii grayscale format that is supported by PIL and all major graphics programs. Any suggestions?
feep.pgm:
P2
# feep.pgm
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
edit: Thanks for the answer, It works... but I need a solution that uses Image.open(). Most of python programs out there use PIL for graphics manipulation (google: python image open). Thus, I need to be able to register a filter to PIL. Then, I can use any software that uses PIL. I now think mostly scipy, pylab, etc. dependent programs.
edit Ok, I think I got it now. Below is the wrapper pgm2pil.py:
import Image
import numpy
def pgm2pil(filename):
try:
inFile = open(filename)
header = None
size = None
maxGray = None
data = []
for line in inFile:
stripped = line.strip()
if stripped[0] == '#':
continue
elif header == None:
if stripped != 'P2': return None
header = stripped
elif size == None:
size = map(int, stripped.split())
elif maxGray == None:
maxGray = int(stripped)
else:
for item in stripped.split():
data.append(int(item.strip()))
data = numpy.reshape(data, (size[1],size[0]))/float(maxGray)*255
return numpy.flipud(data)
except:
pass
return None
def imageOpenWrapper(fname):
pgm = pgm2pil(fname)
if pgm is not None:
return Image.fromarray(pgm)
return origImageOpen(fname)
origImageOpen = Image.open
Image.open = imageOpenWrapper
There is a slight upgrade to misha's answer. Image.open has to be saved in order to prevent never ending loops. If pgm2pil returns None wrapper calls pgm2pil which returns None which calls pgm2pil...
Below is the test function (feep_false.pgm is a malformed pgm e.g. "P2" -> "FOO" and lena.pgm is just the image file):
import pgm2pil
import pylab
try:
pylab.imread('feep_false.pgm')
except IOError:
pass
else:
raise ValueError("feep_false should fail")
pylab.subplot(2,1,1)
a = pylab.imread('feep.pgm')
pylab.imshow(a)
pylab.subplot(2,1,2)
b = pylab.imread('lena.png')
pylab.imshow(b)
pylab.show()
The way I currently deal with this is through numpy:
Read image into a 2D numpy array. You don't need to use numpy, but I've found it easier to use than the regular Python 2D arrays
Convert 2D numpy array into PIL.Image object using PIL.Image.fromarray
If you insist on using PIL.Image.open, you could write a wrapper that attempts to load a PGM file first (by looking at the header). If it's a PGM, load the image using the steps above, otherwise just hands off responsibility to PIL.Image.open.
Here's some code that I use to get a PBM image into a numpy array.
import re
import numpy
def pbm2numpy(filename):
"""
Read a PBM into a numpy array. Only supports ASCII PBM for now.
"""
fin = None
debug = True
try:
fin = open(filename, 'r')
while True:
header = fin.readline().strip()
if header.startswith('#'):
continue
elif header == 'P1':
break
elif header == 'P4':
assert False, 'Raw PBM reading not implemented yet'
else:
#
# Unexpected header.
#
if debug:
print 'Bad mode:', header
return None
rows, cols = 0, 0
while True:
header = fin.readline().strip()
if header.startswith('#'):
continue
match = re.match('^(\d+) (\d+)$', header)
if match == None:
if debug:
print 'Bad size:', repr(header)
return None
cols, rows = match.groups()
break
rows = int(rows)
cols = int(cols)
assert (rows, cols) != (0, 0)
if debug:
print 'Rows: %d, cols: %d' % (rows, cols)
#
# Initialise a 2D numpy array
#
result = numpy.zeros((rows, cols), numpy.int8)
pxs = []
#
# Read to EOF.
#
while True:
line = fin.readline().strip()
if line == '':
break
for c in line:
if c == ' ':
continue
pxs.append(int(c))
if len(pxs) != rows*cols:
if debug:
print 'Insufficient image data:', len(pxs)
return None
for r in range(rows):
for c in range(cols):
#
# Index into the numpy array and set the pixel value.
#
result[r, c] = pxs[r*cols + c]
return result
finally:
if fin != None:
fin.close()
fin = None
return None
You will have to modify it slightly to fit your purposes, namely:
Deal with P2 (ASCII, greyscale) instead of P1 (ASCII, bilevel).
Use a different container if you're not using numpy. Normal Python 2D arrays will work just fine.
EDIT
Here is how I would handle a wrapper:
def pgm2pil(fname):
#
# This method returns a PIL.Image. Use pbm2numpy function above as a
# guide. If it can't load the image, it returns None.
#
pass
def wrapper(fname):
pgm = pgm2pil(fname)
if pgm is not None:
return pgm
return PIL.Image.open(fname)
#
# This is the line that "adds" the wrapper
#
PIL.Image.open = wrapper
I didn't write pgm2pil because it's going to be very similar to pgm2numpy. The only difference will be that it's storing the result in a PIL.Image as opposed to a numpy array. I also didn't test the wrapper code (sorry, a bit short on time at the moment) but it's a fairly common approach so I expect it to work.
Now, it sounds like you want other applications that use PIL for image loading to be able to handle PGMs. It's possible using the above approach, but you need to be sure that the above wrapper code gets added before the first call to PIL.Image.open. You can make sure that happens by adding the wrapper source code to the PIL source code (if you have access).