Array diagonals python - arrays

I have an array 10x10 and I need to address all the points that are on the diagonal between two points and check if there are in a list. I did this but I don't know why it isn't working:
To put you in context:
a = [i,j] b = [i,j], i and j = range(11)
The code below is supposed to work for a = [5,4] b = [8,7] for example.
...
elif (b[1] - a[1]) == (b[0] - a[0]):
#to southeast, code for the other 3 cases are almost the same
if b[0] > a[0] and b[1] > a[1]:
n = a[0]
m = a[1]
while (n != b[0]) and (m != b[1]):
n +=1
m +=1
#don't think this part below is relevant
if board[n][m] in somelist:
mov_inv += 1
else:
mov_inv += 0
This is inside a function that returns False if mov_inv > 1 and True if mov_inv = 0 but it is not working that way. Hope you understand what I mean. Thanks

def diag(pointa, pointb):
""" pointa and pointb are tuples
returns a generator that yields values along the diagonal
from pointa to pointb"""
if abs(pointa[0] - pointb[0]) != abs(pointa[1] - pointb[1]):
#Sanity check. Diagonal are equal along x and y
raise ValueError("Points {} and {} are not diagonal".format(pointa, pointb))
x_dir = 1 if pointa[0] < pointb[0] else -1
y_dir = 1 if pointa[1] < pointb[1] else -1
while pointa != pointb:
pointa = (pointa[0] + x_dir, pointa[1] + y_dir)
yield pointa
The above doesn't yield pointb because you already know it

board=xrange(10*10)
diagonal1=[board[C:(10-C)*10:10+1] for C in xrange(10)]
diagonal2=[board[C:(C*10)+1:10-1] for C in xrange(10)]
print 'diagonal ASC ',diagonal1
print 'diagonal DESC ',diagonal2
then you just check if a and b in same diagonal
assume a,b= [5,4] , [8,7]
def Square(m,n):
return 10*(m-1)+n;
m,n=a
A=Square(m,n)
m,n=b
B=Square(m,n)
**print ('ASCENDENT',[diagonal1[x] for x in xrange(10) if A in diagonal[x] and B in diagonal[x]])**

Related

Rank and unrank combinations to distribute k balls into n bins of different capacities

I want to distribute k balls into n bins of different capacities. How can I rank and unrank the distributions given n, k, and the bin capacities?
Example:
n := 3
k := 4
bin capacities := 3,2,1
Balls in bins:
1,2,1, 2,1,1, 2,2,0, 3,0,1, 3,1,0 := 5
Is there a formula?
I do not know if there is a standard name for this technique, but this is a kind of problem that I have successfully solved many times with a twist on dynamic programming.
What I do using dynamic programming to build a data structure from which the rank/unrank can happen, and then build logic to do the rank/unrank thing.
The dynamic programming piece is hardest.
import collections
BallSolutions = collections.namedtuple('BallSolutions', 'bin count balls next_bin_solutions next_balls_solutions');
def find_ball_solutions (balls, bin_capacities):
# How many balls can fit in the remaining bins?
capacity_sum = [0 for _ in bin_capacities]
capacity_sum[-1] = bin_capacities[-1]
for i in range(len(bin_capacities) - 2, -1, -1):
capacity_sum[i] = capacity_sum[i+1] + bin_capacities[i]
cache = {}
def _search (bin_index, remaining_balls):
if len(bin_capacities) <= bin_index:
return None
elif capacity_sum[bin_index] < remaining_balls:
return None
elif (bin_index, remaining_balls) not in cache:
if bin_index + 1 == len(bin_capacities):
cache[(bin_index, remaining_balls)] = BallSolutions(
bin=bin_index, count=1, balls=remaining_balls, next_bin_solutions=None, next_balls_solutions=None)
else:
this_solution = None
for this_balls in range(min([remaining_balls, bin_capacities[bin_index]]), -1, -1):
next_bin_solutions = _search(bin_index+1, remaining_balls - this_balls)
if next_bin_solutions is None:
break # We already found the fewest balls that can go in this bin.
else:
this_count = next_bin_solutions.count
if this_solution is not None:
this_count = this_count + this_solution.count
next_solution = BallSolutions(
bin=bin_index, count=this_count,
balls=this_balls, next_bin_solutions=next_bin_solutions,
next_balls_solutions=this_solution)
this_solution = next_solution
cache[(bin_index, remaining_balls)] = this_solution
return cache[(bin_index, remaining_balls)]
return _search(0, balls)
Here is code to produce a ranked solution:
def find_ranked_solution (solutions, n):
if solutions is None:
return None
elif n < 0:
return None
elif solutions.next_bin_solutions is None:
if n == 0:
return [solutions.balls]
else:
return None
elif n < solutions.next_bin_solutions.count:
return [solutions.balls] + find_ranked_solution(solutions.next_bin_solutions, n)
else:
return find_ranked_solution(solutions.next_balls_solutions, n - solutions.next_bin_solutions.count)
Here is code to produce the rank for a solution. Note that it will blow up if provided with an invalid answer.
def find_solution_rank (solutions, solution):
n = 0
while solutions.balls < solution[0]:
n = n + solutions.next_bin_solutions.count
solutions = solutions.next_balls_solutions
if 1 < len(solution):
n = n + find_solution_rank(solutions.next_bin_solutions, solution[1:])
return n
And here is some test code:
s = find_ball_solutions(4, [3, 2, 1])
for i in range(6):
r = find_ranked_solution(s, i)
print((i, r, find_solution_rank(s, r)))
You can define the number of such combinations recursively. Given k balls and bin capacities q_1, ..., q_n, for each j between 0 andq_1, place j balls in q_1 and allocate the remaining k-j balls among other bins.
Here is a quick Python implementation:
from functools import lru_cache
#lru_cache(None)
def f(n, *qs):
if not qs:
return 1 if n == 0 else 0
q = qs[0]
return sum(f(n-j, *qs[1:]) for j in range(q+1))
f(4, 3, 2, 1)
# 5
Here's a way (in pseudocode), though it doesn't look very efficient. It would probably be smart to add some short-circuiting in places where the number of balls won't fit in the total remaining capacity. Perhaps some clever caching could help, if a given list of capacities will be used many times.
All numbers are non-negative integers. Function ArrayTail(array a) is the subarray whose elements are all elements of the input array after the first. Function ArrayCon(number head, array a) is the array whose elements are head followed by the elements of a.
function Count(array capacities, number balls) -> number
If balls == 0:
return 1
Else if capacities is empty:
return 0
Else:
Let sum: number
sum <- 0
For b from 0 to max(balls, capacities[0]):
sum <- sum + Count(ArrayTail(capacities), b)
End For
return sum
End If/Else
End function
function Rank(array capacities, array counts) -> number
Precondition: length(capacities) == length(counts)
Precondition: counts[i] <= capacities[i] for all i < length(counts)
If counts is empty:
return 0
Else:
Let total: number
total <- 0
For c in counts:
total <- total + c
End For
Let r: number
r <- Rank(ArrayTail(capacities), ArrayTail(counts))
For b from 0 to (counts[0]-1):
r <- r + Count(ArrayTail(capacities), total - b)
End For
return r
End If/Else
End function
function Unrank(array capacities, number balls, number rank) -> array
Precondition: rank < Count(capacities, balls)
If capacities is empty:
return empty array
Else
Let c0: number
c0 <- 0
Loop until "return":
Let subcount: number
subcount <- Count(ArrayTail(capacities), balls-c0)
If subcount <= rank:
c0 <- c0 + 1
rank <- rank - subcount
Else
return ArrayCon(c0, Unrank(ArrayTail(capacities), balls-c0, rank))
End If/Else
End Loop
End If/Else
End function

Vectorizing a code that requires to complement some elements of a binary array

I have a matrix A of dimension m-by-n composed of zeros and ones, and a matrix J of dimension m-by-1 reporting some integers from [1,...,n].
I want to construct a matrix B of dimension m-by-n such that for i = 1,...,m
B(i,j) = A(i,j) for j=1,...,n-1
B(i,n) = abs(A(i,n)-1)
If sum(B(i,:)) is odd then B(i,J(i)) = abs(B(i,J(i))-1)
This code does what I want:
m = 4;
n = 5;
A = [1 1 1 1 1; ...
0 0 1 0 0; ...
1 0 1 0 1; ...
0 1 0 0 1];
J = [1;2;1;4];
B = zeros(m,n);
for i = 1:m
B(i,n) = abs(A(i,n)-1);
for j = 1:n-1
B(i,j) = A(i,j);
end
if mod(sum(B(i,:)),2)~=0
B(i,J(i)) = abs(B(i,J(i))-1);
end
end
Can you suggest more efficient algorithms, that do not use the nested loop?
No for loops are required for your question. It just needs an effective use of the colon operator and logical-indexing as follows:
% First initialize B to all zeros
B = zeros(size(A));
% Assign all but last columns of A to B
B(:, 1:end-1) = A(:, 1:end-1);
% Assign the last column of B based on the last column of A
B(:, end) = abs(A(:, end) - 1);
% Set all cells to required value
% Original code which does not work: B(oddRow, J(oddRow)) = abs(B(oddRow, J(oddRow)) - 1);
% Correct code:
% Find all rows in B with an odd sum
oddRow = find(mod(sum(B, 2), 2) ~= 0);
for ii = 1:numel(oddRow)
B(oddRow(ii), J(oddRow(ii))) = abs(B(oddRow(ii), J(oddRow(ii))) - 1);
end
I guess for the last part it is best to use a for loop.
Edit: See the neat trick by EBH to do the last part without a for loop
Just to add to #ammportal good answer, also the last part can be done without a loop with the use of linear indices. For that, sub2ind is useful. So adopting the last part of the previous answer, this can be done:
% Find all rows in B with an odd sum
oddRow = find(mod(sum(B, 2), 2) ~= 0);
% convert the locations to linear indices
ind = sub2ind(size(B),oddRow,J(oddRow));
B(ind) = abs(B(ind)- 1);

Trying to understand how to iterate over more-dim Arrays

I am trying to learn how to iterate over arrays and therefore made up my own scenarios to practise on.
Let's say my given matrix is a two-dimensional, therefore an two-dim. Array.
mat =[[1,2,300,-400],[0,3,-1,9],[3,4,-5,1]]
Task 1) Return the Array with the highest sum of the values.
Task 2) Given that this Array could produce a nxm matrix, return the value of the row and column for which the sum of the enclosing number is the highest.
To make it easier to understand let us use a different matrix here.
mat= [[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4]]
So it would look like this:
1111
2222
3333
4444
And the result would be [2,1] or [2,2]
since the sum for those numbers (2+2+2+3+3+4+4+4) = 24 would be the highest.
Here are my implementations so far:
Task 1)
I only can solve this with adding a sum function to the class Array.
def max_row(mat)
return mat.max{|a,b| a.sum <=> b.sum }
end
class Array
def sum
sum = 0
self.each(){|x|
sum += x
}
return sum
end
end
I do want to solve it without using an extra method so, but I do not know how to.
my idea so far :
def max_row(mat)
sum_ary = []
mat.each(){|ary|
sum = 0
ary.each(){|x|
sum += x
}
sum_ary << [sum]
}
I tried find_index on my sum_ary, but as implemented it returns the first value which is not false, therefore I cannot use it to search for the biggest value.
Implementation Task 2):
mat = [[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4]]
def max_neighbor_sum(mat)
sum_result = []
for n in 0...mat.size()
for m in 0...mat.size()
sum = 0
for a in (n-1)..(n+1)
for b in (m-1)..(m+1)
if m != nil && n !=nil && a>=0 && b>=0 && a<= (mat.size()-1)
# print "n:#{n} m:#{m} a:#{a} b:#{b} \n"
# p mat[a][b]
if mat[a][b] !=nil && !(n==a && m==b)
sum += mat[a][b]
end
end
end
end
sum_result << sum
# p sum_result
end
end
return sum_result
end
I calculated all the sums correctly, but have no idea how I get the index for the row and column now.
I hope you can understand where I need some help.
Problem 1:
arrays.map(&:sum).max
Calls sum for each of the arrays, then chooses the biggest of them
Problem 2 can't be solved so easily, but this should work:
max_sum = 0
max_index = []
for n in 0...mat.size
for m in 0...mat.size
sum = 0
for a in (n-1)..(n+1)
for b in (m-1)..(m+1)
sum += mat[a][b] unless mat[a].nil? || mat[a][b].nil?
end
end
if sum > max_sum
max_sum = sum
max_index = [n,m]
end
end
end
max_sum # => maximum sum of all neighbours
max_index # => a pair of indexes which have the max sum
If you want to keep all of max indexes, just replace it with an array of pairs and push if the sum is equal to max_sum.
Here is my solution to task 2 which I came up with thanks to Piotr Kruczek.
Thanks for the kind help!
def max_neighbour_sum(mat)
sum_result = []
max_sum = 0
for n in 0...mat.size()
for m in 0...mat.size()
sum = 0
for a in (n-1)..(n+1)
for b in (m-1)..(m+1)
if m != nil && n !=nil && a>=0 && b>=0 && a<= (mat.size()-1)
# print "n:#{n} m:#{m} a:#{a} b:#{b} \n"
# p mat[a][b]
if mat[a][b] !=nil && !(n==a && m==b)
sum += mat[a][b]
end
end
end
end
if sum > max_sum
max_sum = sum
sum_result = [n,m]
end
# p sum_result
end
end
return sum_result
end

MATLAB: Finding the entry number of the first '1' in a logical array

I have created a logical array of 1's and 0's using the following code:
nWindow = 10;
LowerTotInitial = std(LowerTot(1:nWindow));
UpperTotInitial = std(UpperTot(1:nWindow));
flag = 0;
flagArray = zeros(length(LowerTot), 1);
for n = 1 : nData0 - nWindow
for k = 0 : nWindow - 1
if LowerTot(n + k) < 0.1*LowerTotInitial || UpperTot(n + k) < 0.1*UpperTotInitial
flag = 1;
flagArray(n) = 1;
else
flag = 0;
end
end
end
This returns flagArray, an array of 0's and 1's. I am trying to find the index of the first 1 in the array. ie. 1 = flagArray(index). I am confused as to what is the best way to accomplish this!
What you call an entry number is referred to as an index in MATLAB-speak. To find the index of the first matching element in an array you can use the FIND function:
>> x = [0 0 1 0 1 0];
>> find(x, 1, 'first')
ans =
3
Try this ind = find(flagArray, k, 'first')
with k =1
Read this Matlab Docs - find

Attempt to index field ? (a nil value)

I am writing a small RPG game engine with Lua/love2d, and I need to parse a file to a 2d array, but it don't work, and I am getting errors...
main.lua :
local fmap = love.filesystem.read("map.txt")
map = {}
for c in fmap:gmatch(".") do
if c == "\n" then
y = 0
x = x + 1
else
map[x][y] = c -- this won't work
y = y + 1
end
end
map.txt :
6777633333
6558633333
6555614133
7757711112
2111111112
2111111112
2222222222
You can't use multi-dimensional array like this. See Matrices and Multi-Dimensional Arrays
You can transform your code like this :
local fmap = love.filesystem.read("map.txt")
map = {}
x = 0
y = 0
map[x] = {}
for c in fmap:gmatch(".") do
if c == "\n" then
y = 0
x = x + 1
map[x] = {}
else
map[x][y] = c -- this won't work
y = y + 1
end
end
I know that this has already been answered, but you'd probably find my (in progress) tile tutorial useful. The strings section deals with exactly the issue you are having.

Resources