How to find figures with even areas - python

We have shape with n angles and its coordinates. I need to divide that figure into 2 figures with the same area. Division is performed in parallel to the axis y. The task is to find such x-coordinate, which would comply with the terms.
Test,E.g
4 (n angles)
0 0
0 2
2 2
2 0
The output must be 1
I wrote
n = int(input())
coordinates = []
for i in range(n):
x,y = map(int,input().split())
coordinates.append([x,y])
s = 0
for i in range(len(coordinates)-1):
s += coordinates[i][0]*coordinates[i+1][1]
s -= coordinates[i][1]*coordinates[i+1][0]
s = s/2
x = 0
print(s)
And after that I don't have any ideas what to do next..

Related

How to use numpy/python to make a "chain reaction"?

I am trying to implement a "chain reaction". For example, for a 3x3 matrix all elements are initialized to zero, then one element (randomly) is assigned 1. A first iteration occurs and all the elements neighbouring 1 (up/down/left/right) gets changed from 0 -> 1. Now second iteration occurs and the process continues till all the elements in a(1) column become 1.
I have thought of using nested loops (for, for if, if elif..) but the code becomes kind of ugly (imo) and time consuming. I was wondering if this can be done with any other approach.
My Approach: Initialize with the help of np.zeros, then randomly assign any one element to 1.
import numpy as np
from random import randint, choice
import time
n = int(input("Enter number of modes(n):"))
start = time.time()
m1 = [i+1 for i in range(n)]
print(m1)
# initializing
m = []
ones = [1,1,1,1,1]
for i in range(n):
a = np.zeros(n)
m.append(a)
m1 = choice(m)
A = randint(0, len(m1)-1)
B = randint(0, len(ones)-1)
m1[A]=ones[B]
# game begins here:
print("----Initializing----")
print("1st iteration")
print(np.array(m))
One approach is to use np.argwhere() to get the indices of nonzero elements at each iteration. That way you don't need to go through the entire matrix at each iteration, but you will need to do some if-else checking to see if you're on a boundary.
import numpy as np
def flood_fill_naive(n):
A = np.zeros((n,n)) # Initialize an array of zeros.
snapshots = [] # Copies of the matrix after each change.
def fill_entry(i,j):
"""Set A[i,j] = 1 if (i,j) is a valid index pair for A."""
if 0 <= i < A.shape[0] and 0 <= j < A.shape[1]:
A[i,j] = 1
snapshots.append(A.copy())
# Fill in a single random entry to start.
i,j = np.random.randint(A.shape)
fill_entry(i,j)
# Do the reaction until all entries are 1.
while np.count_nonzero(A) != A.size:
# Find the indices of nonzero elements.
for i,j in np.argwhere(A):
# Set 0 -> 1 on neighbors, except at boundaries.
fill_entry(i-1,j) # Up
fill_entry(i,j-1) # Left
fill_entry(i,j+1) # Right
fill_entry(i+1,j) # Down
return snapshots
if __name__ == "__main__":
n = int(input("Enter integer size of matrix: "))
for snap in flood_fill_naive(n):
print(snap)
But notice that this approach does a lot of repeat work. For example, the initial 1 only updates its neighbors once, and then you can forget about it. So at each step, you really only need to remember the spaces that were just updated, since they are the only ones that potentially have neighbors that are 0.
0 0 0 0 0 0 0 1 0 0 0 1 x 1 0 1 x x x 1
0 0 1 0 0 0 1 x 1 0 1 x x x 1 x x x x x
0 0 0 0 0 --> 0 0 1 0 0 --> 0 1 x 1 0 --> 1 x x x 1 --> ...
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 x 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
So let's just try to keep track of the indices of the "current 1s" and "previous 1s" (marked as x's above). In fact, what we're doing here is a breadth-first search. See BFS and Flood Fill on Wikipedia.
def flood_fill_bfs(n):
A = np.zeros((n,n)) # Initialize an array of zeros.
snapshots = [] # Copies of the matrix after each change.
visit_queue = [] # List of indices to visit in the future.
visited = set() # Set of indices already visited.
def fill_entry(i,j):
"""If (i,j) has not been visited, visit it by setting A[i,j] = 1
and adding it to the visit queue.
"""
# Do nothing if this index has been visited.
if (i,j) in visited:
return
# If the index has not been visited but is valid,
if 0 <= i < A.shape[0] and 0 <= j < A.shape[1]:
A[i,j] = 1
visited.add((i,j))
visit_queue.append((i,j))
snapshots.append(A.copy())
# Fill in a single random entry to start.
i,j = np.random.randint(A.shape)
fill_entry(i,j)
# Fill in neighbors of 1's until all entries are 1.
while np.count_nonzero(A) != A.size:
i,j = visit_queue.pop(0)
# Set 0 -> 1 on neighbors, except at boundaries.
fill_entry(i-1,j) # Up
fill_entry(i,j-1) # Left
fill_entry(i,j+1) # Right
fill_entry(i+1,j) # Down
return snapshots
if __name__ == "__main__":
n = int(input("Enter integer size of matrix: "))
for snap in flood_fill_bfs(n):
print(snap)
You can guess which routine will be faster:
In [1]: %time _ = flood_fill_naive(100)
CPU times: user 6.21 s, sys: 258 ms, total: 6.47 s
Wall time: 6.49 s
In [2]: %time _ = flood_fill_bfs(100)
CPU times: user 709 ms, sys: 310 ms, total: 1.02 s
Wall time: 1.03 s

How can I recursively divide the grid in my maze?

I am trying to create a maze generator using recursive division. I use this link:
Maze generation - recursive division (how it works?) as my guide as to how to approach the problem.
Here is my code so far:
import random
# Maze: 0 - N : 4 x 4 Grid
# Grid: 0 - (2n + 1) : 9 x 9 Array
# TODO: Now, Find a way to save the previous walls and not just only one at a time
rows = 9
cols = 9
start = 2
end = 7
# -------------------------------------------------------------------------------------
# Lists for all even / odd numbers in given range
evens = [n for n in range(start, end+1) if n % 2 == 0]
odds = [m for m in range(start, end+1) if m % 2 != 0]
# Generate random even/odd integer value for walls/ passages respectively
# Walls: Not sure if 2 variables are necessary-----------------------------------------
wallX = random.choice(evens)
wallY = random.choice(evens)
# Passages
passageX = random.choice(odds)
passageY = random.choice(odds)
#--------------------------------------------------------------------------------------
# Random direction: True = Horizontal Slice, False = Vertical Slice
randomDirection = random.choice([True, False])
arr = [['0' for i in range(cols)] for j in range(rows)]
def displayBoard(arr):
print()
for i in range(len(arr)):
for j in range(len(arr[i])):
# Print just the edges
if i == 0 or i == 8 or j == 0 or j == 8:
print('*', end = ' ')
# Print wall
elif arr[i][j] == 1:
print('.', end = ' ')
else:
print (' ', end = ' ')
print()
# Function choose direction to slice
def chooseDir(arr):
for i in range(len(arr)):
for j in range(len(arr[i])):
# Horizontal Direction Slice
if randomDirection:
arr[wallX][j] = 1
arr[wallX][passageY] = 2
print(arr[i][j], end = ' ')
# Vertical Slice
else:
arr[i][wallY] = 1
arr[passageX][wallY] = 2
print(arr[i][j], end = ' ')
print()
displayBoard(arr)
print()
mazeX = 0
mazeY = 0
# Write the recursive division function:
def divide():
chooseDir(arr)
print()
divide()
What this produces is a grid that is randomly sliced at an even index (creating walls) and creates passages at odd indices.
Output: 1 = wall, 2 = passage made
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 2 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
* * * * * * * * *
* . *
* . *
* *
* . *
* . *
* . *
* . *
* * * * * * * * *
My issue is that I don't know how to write my recursive function. Do I call division on the two new cells created when a wall is made and continuously divide the "sub cells".
Or I know that a 4 x 4 cell grid will provide an array of 9 x 9 and I will have 16 cells total.
Then I can call division until a certain condition is met, increment to the next cell until all 16 were visited.
In both cases, I am not sure how to represent the new walls/cells created so that I can write the division function. Up until now, I've been using the grid coordinates.
You asked "Do I call division on the two new cells created when a wall is made and continuously divide the "sub cells"". Yes, that is the essence of recursion. Take a big problem and make smaller problem(s). Repeat with the smaller problems. Eventually, the problems are small enough to easily solve. Then put all the small problems back together to solve the original problem.
For the maze, the first wall split the maze into two smaller mazes. Use the same algorithm to split each of them and there are not 4 smaller mazes. Repeat until the sub-mazes are too small to split any more.
Your code that splits the maze should go in a function. If the sub-maze is big enough to split, the function splits the sub-maze and then calls itself on the two smaller sub-mazes.

Ternary function for Hamming distance, where '2' is wildcard

Let say I have the following array of vectors x, where the possible values are 0,1,2 :
import numpy as np
x = np.random.randint(0,3,(10,5), dtype=np.int8)
I want to do similarity match for all vectors with Hamming Distance zero or one, where the rules for matching are :
1. 0 == 0 and 1 == 1 i.e. hamming distance is 0
2. 2 match both 1 and 0 i.e. hamming distance is 0
3. otherwise Hamming distance is 1
i.e. find some arithmetic operation that will return:
0 x 0 = 0
1 x 1 = 0
0 x 1 = 1
1 x 0 = 1
0 x 2 = 0
1 x 2 = 0
And my output should be the Hamming distance between each vector (row of) x, and arbitary vector z:
z = np.random.randint(0,2,5)
np.sum(np.add(x,z) == 1, axis=1)
int(x+y == 1)
Is there something in this question I'm missing???
Wouldn't this do the trick?
((x!=y) ^ (x==2) ^ (y==2)).sum() <=1
Or if you want to allow two on either and both sides
((x!=y) ^ (x==2) | (y==2)).sum() <=1

Kadane's Algorithm for 2D array with known boundaries

I have implemented the Kadane's algorithm for a 2D array in Python 2 with known boundaries, but I'm using the implementation for an online contest and the time it takes is more than the time given.
So that made me think if there is maybe another algorithm similar to Kadane's that has a smaller complexity, or if my code can be optimized in a way. My implementation works for any array with dimensions N x M and a subarray with dimensions maxRows x maxCols.
maxSumSubarray.py
import numpy as np
# returns the maximum sum for the given vector using kadane's algorithm, with
# maxRows maximum members in the sum
def kadane1DwithBounds(maxRows):
global temp
m = s = sum(temp[i] for i in xrange(maxRows))
k = 0
for i in xrange(1, N - maxRows + 1):
s -= temp[k]
s += temp[maxRows + i - 1]
k += 1
m = max(m, s)
return m
# prints the maximum "area" given by the values of an NxM array inside a
# subarray with dimensions maxRows x maxCols. temp holds the latest vector to be
# given to kadane1DwithBounds()
def kadane2DwithBounds(maxRows, maxCols):
global temp
for i in xrange(N):
temp[i] = sum(table[i][j] for j in xrange(maxCols))
m = kadane1DwithBounds(maxRows)
k = 0
for j in xrange(1, M - maxCols + 1):
for i in xrange(N):
temp[i] -= table[i][k]
temp[i] += table[i][maxCols + j - 1]
k += 1
m = max(m, kadane1DwithBounds(maxRows))
print m
line = map(int, raw_input().split())
N = line[0]
M = line[1]
maxRows = line[2]
maxCols = line[3]
table = []
temp = np.empty(N, dtype = int)
for _ in xrange(N):
table.append(map(int, raw_input().split()))
kadane2DwithBounds(maxRows, maxCols)
test.txt
4 8 2 3
1 1 2 3 3 1 1 1
2 2 2 2 2 2 2 2
3 3 3 1 1 3 3 4
0 0 1 1 3 2 2 1
Run with
python maxSumSubarray.py < test.txt
it gives
16
which is correct and is the following rectangle:
2 2 2
3 3 4
I've tried with other dimensions too and I'm pretty sure it works fine. Only problem is time/complexity. Any help would be appreciated! Thanks for your time.

Gernerate all the possible undirected graphs

What is an efficient solution to generate all the possible graphs using an incidence matrix?
The problems is equivalent of generating all the possible binary triangular matrix.
My first idea was to use python with itertools. For instance, for generating all the possibile 4x4 matrix
for b in itertools.combinations_with_replacement((0,1), n-3):
b_1=[i for i in b]
for c in itertools.combinations_with_replacement((0,1), n-2):
c_1=[i for i in c]
for d in itertools.combinations_with_replacement((0,1), n-1):
d_1=[i for i in d]
and then you create the matrix adding the respective number of zeroes..
But this is not correct since we skip some graphs...
So, any ideas?
Perhaps i can use the isomorphism between R^n matrix and R^(n*n) vector, and generate all the possibile vector of 0 and 1, and then cut it into my matrix, but i think there's a more efficient solutions.
Thank you
I add the matlab tab because it's a problem you can have in numerical analysis and matlab.
I assume you want lower triangular matrices, and that the diagonal needs not be zero. The code can be easily modified if that's not the case.
n = 4; %// matrix size
vals = dec2bin(0:2^(n*(n+1)/2)-1)-'0'; %// each row of `vals` codes a matrix
mask = tril(reshape(1:n^2, n, n))>0; %// decoding mask
for v = vals.' %'// `for` picks one column each time
matrix = zeros(n); %// initiallize to zeros
matrix(mask) = v; %// decode into matrix
disp(matrix) %// Do something with `matrix`
end
Each iteration gives one possible matrix. For example, the first matrices for n=4 are
matrix =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
matrix =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 1
matrix =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 1 0
matrix =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 1 1
Here is an example solution using numpy that generates all simple graphs:
It first generates the indices of the upper triangular part iu. The loop converts the number k to it's binary representation and then assigns it to the upper triangular part G[iu].
import numpy as np
n = 4
iu = np.triu_indices(n,1) # Start at first minor diagonal
G = np.zeros([n,n])
def dec2bin(k, bitlength=0):
return [1 if digit=='1' else 0 for digit in bin(k)[2:].zfill(bitlength)]
for k in range(0,2**(iu[0].size)):
G[iu] = dec2bin(k, iu[0].size)
print(G)

Categories

Resources