List index out of range, but why? - list

def list_2d_locations(rows, columns, low_range, high_range):
matrix = list_2d_generate(rows, columns, low_range, high_range)
print(matrix)
low_val = high_val = matrix[0][0]
for i in range(rows):
for j in range(columns):
if matrix[i][j] < low_val:
low_val = matrix[i][j]
low_loc = [i][j]
if matrix[i][j] > high_val:
high_val = matrix[i][j]
high_loc = [i][j]
return low_val, high_val, low_loc, high_loc
I have here a function which is supposed to find the smallest and largest number within a list of lists (i.e. a matrix) and return the actual value, and the position of that value within the matrix. Now my problem is that both high_loc = [i][j] and low_loc = [i][j] give me the error of "list index out of range" and I don't understand why. Wouldn't the if statements also be out of range then by the same logic?

The problem is in the line low_loc = [i][j]. In the expression on the right-hand side of the = sign, [i] is a list with a single element, and [i][j] represents an attempt to extract the element at position j from that list. That will fail unless j == 0. Perhaps you wanted low_loc = [i, j] or low_loc = (i, j) instead? (The same comments apply to the line high_loc = [i][j], of course.)

Here is a solution. It is clean. However, for big matrices it should be optimized to iterate only once over them and collect all info during that iteration.
m = [[3,5,1], [56,43,12], [4,52,673]]
def f(matrix):
cols = len(matrix[0])
flatten = [val for row in matrix for val in row]
min_val, max_val = min(flatten), max(flatten)
min_i, max_i = flatten.index(min_val), flatten.index(max_val)
return min_val, max_val, divmod(min_i, cols), divmod(max_i, cols)
>>> f(m)
(1, 673, (0, 2), (2, 2))
EDIT: You know what, here is the optimized version:
def f(matrix):
try:
min_val, max_val = matrix[0][0], matrix[0][0]
except IndexError:
raise ValueError("Expected a real matrix.") from None
genexp = (val for row in matrix for val in row)
cols = len(matrix[0])
min_i, max_i = (0, 0), (0, 0)
for i, val in enumerate(genexp):
if val < min_val:
min_val, min_i = val, divmod(i, cols)
elif val > max_val:
max_val, max_i = val, divmod(i, cols)
return min_val, max_val, min_i, max_i
EDIT2:
Here are an experience for better understanding which could be done either by you. I suggest you do the same if you want to understand a code.
>>> matrix = [[3,5,1], [56,43,12], [4,52,673]]
>>> flatten = [val for row in matrix for val in row]
>>> flatten
[3, 5, 1, 56, 43, 12, 4, 52, 673]
>>> flatten.index(56)
3
>>> divmod(3,3)
(1, 0)
>>> for elem in enumerate(["one", "two", "three"]):
... elem
...
(0, 'one')
(1, 'two')
(2, 'three')

Related

Maximum difference between sum of even and odd position elements: How to memoize the brute-force approach?

I have the following code for a problem.
The problem is: Maximize the absolute difference between the sum of elements at the even and odd positions of an array. To do so, you may delete as many elements you want.
I did it by brute-force by using backtracking. My logic is that, for each index I have 2 options:
a) either delete it (in this case, I put it in a set)
b) don't delete it (in this case, I removed the index from the set and backtracked).
I took the local maximum of two cases and updated the global maximum value appropriately.
void maxAns(vector<int> &arr, int index, set<int> &removed, int &res)
{
if (index<0)
return;
int k=0;
int s3=0,s4=0;
for (int i=0;i<arr.size();i++)
{
if (i!=index)
{
set<int>::iterator it=removed.find(i);
if (it==removed.end())
{
if( k%2==0)
s3+=arr[i];
else
s4+=arr[i];
k++;
}
}
else //don't delete the element
{
if (k%2==0)
s3+=arr[i];
else
s4+=arr[i];
k++;
}
}
k=0;
int s1=0, s2=0;
for (int i=0;i<arr.size();i++)
{
if (i!=index)
{
set<int>::iterator it=removed.find(i);
if (it==removed.end())
{
if (k%2==0)
s1+=arr[i];
else
s2+=arr[i];
k++;
}
}
else //delete the element
{
//add index into the removed set
removed.insert(index);
}
}
//delete the index element
int t1=abs(s1-s2);
maxAns(arr,index-1,removed,res);
//don't delete the index element, and then backtrack
set<int>::iterator itr=removed.find(index);
removed.erase(itr);
int t2=abs(s3-s4);
maxAns(arr,index-1,removed,res);
//choose the max value
res=max(res,max(t1,t2));
}
Please suggest how to memoize this solution as I think it's quite inefficient. Feel free to share any interesting approach.
Hint: divide and conquer. Consider that a fixed length list as a left part of a larger list, maximised (or minimised) for the actual, rather than abdolute difference and depending on the parity of its length, would pair better with a right part that does not depend on the parity of its length.
[0,3] ++ [0,3] -> diff -3 -3 = -6
[0,3] ++ [9,13,1] -> diff -3 -3 = -6
We can also easily create base cases for max_actual_diff and min_actual_diff of lists with lengths 1 and 2. Note that the best choice for those might include ommiting one or more of those few elements.
JavaScript code:
function max_diff(A, el, er, memo){
if (memo[['mx', el, er]])
return memo[['mx', el, er]]
if (er == el)
return memo[['mx', el, er]] = [A[el], 1, 0, 0]
var best = [A[el], 1, 0, 0]
if (er == el + 1){
if (A[el] - A[er] > best[2]){
best[2] = A[el] - A[er]
best[3] = 2
}
if (A[er] > best[0]){
best[0] = A[er]
best[1] = 1
}
return memo[['mx', el, er]] = best
}
const mid = el + ((er - el) >> 1)
const left = max_diff(A, el, mid, memo)
const right_min = min_diff(A, mid + 1, er, memo)
const right_max = max_diff(A, mid + 1, er, memo)
// Best odd = odd + even
if (left[0] - right_min[2] > best[0]){
best[0] = left[0] - right_min[2]
best[1] = left[1] + right_min[3]
}
// Best odd = even + odd
if (left[2] + right_max[0] > best[0]){
best[0] = left[2] + right_max[0]
best[1] = left[3] + right_max[1]
}
// Best even = odd + odd
if (left[0] - right_min[0] > best[2]){
best[2] = left[0] - right_min[0]
best[3] = left[1] + right_min[1]
}
// Best even = even + even
if (left[2] + right_max[2] > best[2]){
best[2] = left[2] + right_max[2]
best[3] = left[3] + right_max[3]
}
return memo[['mx', el, er]] = best
}
function min_diff(A, el, er, memo){
if (memo[['mn', el, er]])
return memo[['mn', el, er]]
if (er == el)
return memo[['mn', el, er]] = [A[el], 1, 0, 0]
var best = [A[el], 1, 0, 0]
if (er == el + 1){
if (A[el] - A[er] < best[2]){
best[2] = A[el] - A[er]
best[3] = 2
}
if (A[er] < best[0]){
best[0] = A[er]
best[1] = 1
}
return memo[['mn', el, er]] = best
}
const mid = el + ((er - el) >> 1)
const left = min_diff(A, el, mid, memo)
const right_min = min_diff(A, mid + 1, er, memo)
const right_max = max_diff(A, mid + 1, er, memo)
// Best odd = odd + even
if (left[0] - right_max[2] < best[0]){
best[0] = left[0] - right_max[2]
best[1] = left[1] + right_max[3]
}
// Best odd = even + odd
if (left[2] + right_min[0] < best[0]){
best[0] = left[2] + right_min[0]
best[1] = left[3] + right_min[1]
}
// Best even = odd + odd
if (left[0] - right_max[0] < best[2]){
best[2] = left[0] - right_max[0]
best[3] = left[1] + right_max[1]
}
// Best even = even + even
if (left[2] + right_min[2] < best[2]){
best[2] = left[2] + right_min[2]
best[3] = left[3] + right_min[3]
}
return memo[['mn', el, er]] = best
}
var memo = {}
var A = [1, 2, 3, 4, 5]
console.log(`A: ${ JSON.stringify(A) }`)
console.log(
JSON.stringify(max_diff(A, 0, A.length-1, memo)) + ' // [odd max, len, even max, len]')
console.log(
JSON.stringify(min_diff(A, 0, A.length-1, memo)) + ' // [odd min, len, even min, len]')
console.log('\nmemo:\n' + JSON.stringify(memo))
Maximize the absolute difference between the sum of elements at the odd and even positions of an array. To do so, you may delete as many elements as you want.
Example
A = [9, 5, 2, 9, 4]
Ans = 16 => [9, 2, 9] = 9-2+9
A = [8, 6, 2, 7, 7, 2, 7]
Ans = 18 => [8, 2, 7, 2, 7] = 8-2+7-2+7
Hint:
At the position "i+1", Let the maximum and minimum possible difference for all the subsequences of subarray A[i+1,n] be Max, Min respectively
Hence at position "i", the maximum and minimum possible difference for all the subsequences of subarray A[i, n] can be calculated as
Include the current element arr[i]
Don't Include the current element arr[I]
Max = MAX(Max, arr[i] - Min)
Min = MIN(Min, arr[i] - Max)
Explanation:
A = 9, 5, 2, 9, 4
Max = 16, 12, 9, 9, 4
Min = -7, -7, -7, 0, 0
Final Answer: Max(Max[0], Min[0]) = Max(16, -7) = 16
Time Complexity: O(n)
Space Complexity: O(1) * As Just 2 variables Max, Min were used*
Let's say we always add the values at even positions and we always rest the values at odd positions. Now, we will iterate from 1 to 𝑛nΒ and make choices: keep the element or delete it; the thing is that when we keep an element, we need to know if it is at an even position or an odd position, so we will do Dynamic Programming:
𝑑𝑝[𝑖][0]dp[i][0]: max possible sum using the elements inΒ π‘Ž1,π‘Ž2,…,π‘Žπ‘–a1,a2,…,aiΒ and the resulting array is of even length.
𝑑𝑝[𝑖][1]dp[i][1]: same as above, but now the resulting array is of odd length.
Transitions are: keep it or delete it.
𝑑𝑝[𝑖][π‘Ÿ]=max(𝑑𝑝[π‘–βˆ’1][π‘Ÿ],𝑑𝑝[π‘–βˆ’1][!π‘Ÿ]+π‘Ž[𝑖]βˆ—((π‘Ÿ==0)?1:βˆ’1)dp[i][r]=max(dp[iβˆ’1][r],dp[iβˆ’1][!r]+a[i]βˆ—((r==0)?1:βˆ’1);
Now it's when someone says: Wait minute, you are always adding at even positions and resting at odd positions, what if it's of the other way. Well, for this, perform again the DP but adding at odd positions and resting at even positions. You stay with the maximum of both solutions

How to find N points on an infinite axis so that sum of distances from M points to its nearest N is smallest?

Consider there are N houses on a single road. I have M lightpoles. Given that M < N. Distance between all adjacent houses are different. Lightpole can be placed at the house only. And I have to place all lightpoles at house so that sum of distances from each house to its nearest lightpole is smallest. How can I code this problem?
After a little research I came to know that I have to use dynamic programming for this problem. But I don't know how to approach it to this problem.
Here's a naive dynamic program with search space O(n^2 * m). Perhaps others know of another speedup? The recurrence should be clear from the function f in the code.
JavaScript code:
// We can calculate these in O(1)
// by using our prefixes (ps) and
// the formula for a subarray, (j, i),
// reaching for a pole at i:
//
// ps[i] - ps[j-1] - (A[i] - A[j-1]) * j
//
// Examples:
// A: [1,2,5,10]
// ps: [0,1,7,22]
// (2, 3) =>
// 22 - 1 - (10 - 2) * 2
// = 5
// = 10-5
// (1, 3) =>
// 22 - 0 - (10 - 1) * 1
// = 13
// = 10-5 + 10-2
function sumParts(A, j, i, isAssigned){
let result = 0
for (let k=j; k<=i; k++){
if (isAssigned)
result += Math.min(A[k] - A[j], A[i] - A[k])
else
result += A[k] - A[j]
}
return result
}
function f(A, ps, i, m, isAssigned){
if (m == 1 && isAssigned)
return ps[i]
const start = m - (isAssigned ? 2 : 1)
const _m = m - (isAssigned ? 1 : 0)
let result = Infinity
for (let j=start; j<i; j++)
result = Math.min(
result,
sumParts(A, j, i, isAssigned)
+ f(A, ps, j, _m, true)
)
return result
}
var A = [1, 2, 5, 10]
var m = 2
var ps = [0]
for (let i=1; i<A.length; i++)
ps[i] = ps[i-1] + (A[i] - A[i-1]) * i
var result = Math.min(
f(A, ps, A.length - 1, m, true),
f(A, ps, A.length - 1, m, false))
console.log(`A: ${ JSON.stringify(A) }`)
console.log(`ps: ${ JSON.stringify(ps) }`)
console.log(`m: ${ m }`)
console.log(`Result: ${ result }`)
I got you covered bud. I will write to explain the dynamic programming algorithm first and if you are not able to code it, let me know.
A-> array containing points so that A[i]-A[i-1] will be the distance between A[i] and A[i-1]. A[0] is the first point. When you are doing memoization top-down, you will have to handle cases when you would want to place a light pole at the current house or you would want to place it at a lower index. If you place it now, you recurse with one less light pole available and calculate the sum of distances with previous houses. You handle the base case when you are not left with any ligh pole or you are done with all the houses.

Cant input numbers into mtarix. why index goes out of range?

Cant input numbers in matrix.Why I get IndexError: list assignment index out of range?
i, j = 5, 7;
matrix = [[x + y for x in xrange(i)] for y in xrange(j)]
print (matrix)
for w in xrange(i):
print (w)
for h in xrange(j):
tmp = int(input('Enter element of matrix'))
matrix[w][h] = tmp
sums = map( lambda row: sum(row), matrix)
print (matrix)
print (sums)
print ('max:', sums.index(max(sums)))
print ('min:', sums.index(min(sums)))
matrix = [[x + y for x in xrange(i)] for y in xrange(j)]
The above line makes the number of columns = i and rows = j, because it will create a j lists with i variables where each list acts as a row.
for w in xrange(i):
print (w)
for h in xrange(j):
tmp = int(input('Enter element of matrix'))
matrix[w][h] = tmp
and in this loop you are using w as rows which is ranging from 0 to i-1 instead it should be 0 to j-1
similarly h should range from 0 to i-1 not 0 to j-1
so your loop should be like this -
for w in xrange(j): #note this changed from i to j
print (w)
for h in xrange(i): #and this from j to i
tmp = int(input('Enter element of matrix'))
matrix[w][h] = tmp

Finding the two closest numbers in a list using sorting

If I am given a list of integers/floats, how would I find the two closest numbers using sorting?
Such a method will do what you want:
>>> def minDistance(lst):
lst = sorted(lst)
index = -1
distance = max(lst) - min(lst)
for i in range(len(lst)-1):
if lst[i+1] - lst[i] < distance:
distance = lst[i+1] - lst[i]
index = i
for i in range(len(lst)-1):
if lst[i+1] - lst[i] == distance:
print lst[i],lst[i+1]
In the first for loop we find out the minimum distance, and in the second loop, we print all the pairs with this distance. Works as below:
>>> lst = (1,2,3,6,12,9,1.4,145,12,83,53,12,3.4,2,7.5)
>>> minDistance(lst)
2 2
12 12
12 12
>>>
It could be more than one possibilities. Consider this list
[0,1, 20, 25, 30, 200, 201]
[0,1] and [200, 201] are equal closest.
Jose has a valid point. However, you could just consider these cases equal and not care about returning one or the other.
I don't think you need a sorting algorithm, per say, but maybe just a sort of 'champion' algorithm like this one:
def smallestDistance(self, arr):
championI = -1
championJ = -1
champDistance = sys.maxint
i = 0
while i < arr.length:
j = i + 1
while j < arr.length:
if math.fabs(arr[i] - arr[j]) < champDistance:
championI = i
championJ = j
champDistance = math.fabs(arr[i] - arr[j])
j += 1
i += 1
r = [arr[championI], arr[championJ]]
return r
This function will return a sub array with the two values that are closest together. Note that this will only work given an array of at least two long. Otherwise, you will throw some error.
I think the popular sorting algorithm known as bubble sort would do this quite well. Though running at possible O(n^2) time if that kind of thing matters to you...
Here is standard bubble sort based on the sorting of arrays by integer size.
def bubblesort( A ):
for i in range( len( A ) ):
for k in range( len( A ) - 1, i, -1 ):
if ( A[k] < A[k - 1] ):
swap( A, k, k - 1 )
def swap( A, x, y ):
tmp = A[x]
A[x] = A[y]
A[y] = tmp
You can just modify the algorithm slightly to fit your purposes if you insist on doing this using a sorting algorithm. However, I think the initial function works as well...
hope that helps.

Enumeration all possible matrices with constraints

I'm attempting to enumerate all possible matrices of size r by r with a few constraints.
Row and column sums must be in non-ascending order.
Starting from the top left element down the main diagonal, each row and column subset from that entry must be made up of combinations with replacements from 0 to the value in that upper left entry (inclusive).
The row and column sums must all be less than or equal to a predetermined n value.
The main diagonal must be in non-ascending order.
Important note is that I need every combination to be store somewhere, or if written in c++, to be ran through another few functions after finding them
r and n are values that range from 2 to say 100.
I've tried a recursive way to do this, along with an iterative, but keep getting hung up on keeping track column and row sums, along with all the data in a manageable sense.
I have attached my most recent attempt (which is far from completed), but may give you an idea of what is going on.
The function first_section(): builds row zero and column zero correctly, but other than that I don't have anything successful.
I need more than a push to get this going, the logic is a pain in the butt, and is swallowing me whole. I need to have this written in either python or C++.
import numpy as np
from itertools import combinations_with_replacement
global r
global n
r = 4
n = 8
global myarray
myarray = np.zeros((r,r))
global arraysums
arraysums = np.zeros((r,2))
def first_section():
bigData = []
myarray = np.zeros((r,r))
arraysums = np.zeros((r,2))
for i in reversed(range(1,n+1)):
myarray[0,0] = i
stuff = []
stuff = list(combinations_with_replacement(range(i),r-1))
for j in range(len(stuff)):
myarray[0,1:] = list(reversed(stuff[j]))
arraysums[0,0] = sum(myarray[0,:])
for k in range(len(stuff)):
myarray[1:,0] = list(reversed(stuff[k]))
arraysums[0,1] = sum(myarray[:,0])
if arraysums.max() > n:
break
bigData.append(np.hstack((myarray[0,:],myarray[1:,0])))
if printing: print 'myarray \n%s' %(myarray)
return bigData
def one_more_section(bigData,index):
newData = []
for item in bigData:
if printing: print 'item = %s' %(item)
upperbound = int(item[index-1]) # will need to have logic worked out
if printing: print 'upperbound = %s' % (upperbound)
for i in reversed(range(1,upperbound+1)):
myarray[index,index] = i
stuff = []
stuff = list(combinations_with_replacement(range(i),r-1))
for j in range(len(stuff)):
myarray[index,index+1:] = list(reversed(stuff[j]))
arraysums[index,0] = sum(myarray[index,:])
for k in range(len(stuff)):
myarray[index+1:,index] = list(reversed(stuff[k]))
arraysums[index,1] = sum(myarray[:,index])
if arraysums.max() > n:
break
if printing: print 'index = %s' %(index)
newData.append(np.hstack((myarray[index,index:],myarray[index+1:,index])))
if printing: print 'myarray \n%s' %(myarray)
return newData
bigData = first_section()
bigData = one_more_section(bigData,1)
A possible matrix could look like this:
r = 4, n >= 6
|3 2 0 0| = 5
|3 2 0 0| = 5
|0 0 2 1| = 3
|0 0 0 1| = 1
6 4 2 2
Here's a solution in numpy and python 2.7. Note that all the rows and columns are in non-increasing order, because you only specified that they should be combinations with replacement, and not their sortedness (and generating combinations is the simplest with sorted lists).
The code could be optimized somewhat by keeping row and column sums around as arguments instead of recomputing them.
import numpy as np
r = 2 #matrix dimension
maxs = 5 #maximum sum of row/column
def generate(r, maxs):
# We create an extra row and column for the starting "dummy" values.
# Filling in the matrix becomes much simpler when we do not have to treat cells with
# one or two zero indices in special way. Thus, we start iteration from the
# (1, 1) index.
m = np.zeros((r + 1, r + 1), dtype = np.int32)
m[0] = m[:,0] = maxs + 1
def go(n, i, j):
# If we completely filled the matrix, yield a copy of the non-dummy parts.
if (i, j) == (r, r):
yield m[1:, 1:].copy()
return
# We compute the next indices in row major order (the choice is arbitrary).
(i2, j2) = (i + 1, 1) if j == r else (i, j + 1)
# Computing the maximum possible value for the current cell.
max_val = min(
maxs - m[i, 1:].sum(),
maxs - m[1:, j].sum(),
m[i, j-1],
m[i-1, j])
for n2 in xrange(max_val, -1, -1):
m[i, j] = n2
for matrix in go(n2, i2, j2):
yield matrix
return go(maxs, 1, 1) #note that this is a generator object
# testing
for matrix in generate(r, maxs):
print
print matrix
If you'd like to have all the valid permutations in the rows and columns, this code below should work.
def generate(r, maxs):
m = np.zeros((r + 1, r + 1), dtype = np.int32)
rows = [0]*(r+1) # We avoid recomputing row/col sums on each cell.
cols = [0]*(r+1)
rows[0] = cols[0] = m[0, 0] = maxs
def go(i, j):
if (i, j) == (r, r):
yield m[1:, 1:].copy()
return
(i2, j2) = (i + 1, 1) if j == r else (i, j + 1)
max_val = min(rows[i-1] - rows[i], cols[j-1] - cols[j])
if i == j:
max_val = min(max_val, m[i-1, j-1])
if (i, j) != (1, 1):
max_val = min(max_val, m[1, 1])
for n in xrange(max_val, -1, -1):
m[i, j] = n
rows[i] += n
cols[j] += n
for matrix in go(i2, j2):
yield matrix
rows[i] -= n
cols[j] -= n
return go(1, 1)