Recently, I have encountered an interesting question in coding, where I would like to generate all combinations of choosing 2 elements from a collection. For fast indexing, I would like to have a function that maps original chosen indices to the index of that pair in the result. To be accurate, I'm thinking of a function f: {{i,j}: i,j in 0~(n-1), i!=j} -> 0~(n choose 2 - 1) that is a bijection. I've looked up unordered pairing function and hash functions, but they either include pairs where i == j, or they do not map into my desired range. Therefore, I'm wondering if it is possible to do so.
First I'd reorder (i, j) so that j > i.
Then the index:
p = i(2n - i - 3)/2 + j - 1
So for example, when n = 5:
i j p
- - -
(0,1) 0
(0,2) 1
(0,3) 2
(0,4) 3
(1,2) 4
(1,3) 5
(1,4) 6
(2,3) 7
(2,4) 8
(3,4) 9
Related
Problem : 5 monkeys, 5 snakes and 5 tigers are standing in a line in a grocery store, with animals of the same species being indistinguishable. A monkey stands in the front of the line, and a tiger stands at the end of the line. Unfortunately, tigers and monkeys are sworn enemies, so monkeys and tigers cannot stand in adjacent places in line. Compute the number of possible arrangements of the line.
Solving this problem by hand is daunting. I want to write a program to output the possible arrangements and also count the total arrangements. My first thought was to use a brute force. Monkeys, snakes, and tigers can be represented by the letters M, S, and T respectively. With 1 M at start of string and 1 T at the end, there are 13!/(4!4!5!) = 90,090 possibilities. I would then remove arrangements that do not satisfy the second condition about adjacency.
My second thought was to first compute the number of arrangements where M and T are adjacent and then subtract this number from 90,090. I am new to programming so I am not sure how to do this.
Is there a better way to approach these types of problems? Any hints?
Thank you.
TL;DR: python solution using sympy
import sympy # sympy.ntheory.multinomial_coefficients
import math # math.comb
def count_monkeytigers(n_monkeys, n_snakes, n_tigers):
return sum(
m * math.comb(n_monkeys - 1, mb_minus1) * math.comb(n_tigers - 1, tb_minus1)
for (mb_minus1, eb, tb_minus1), m in
sympy.ntheory.multinomial_coefficients(3, n_snakes-1).items()
)
Explanation
We already know that there is an M at the beginning, a T at the end, and five S in the string:
M?? S ?? S ?? S ?? S ?? S ??T
Since M and T cannot be adjacent, and the only way to separate them is with an S, you can think of the S as separators; the five S are cutting the string into 6 "bins". Every bin can either be empty, or contain one or more M, or contain one or more T. Furthermore, the first bin contains at least an M, and the last bin contains at least a T.
To count all permutations of the string, we can do the following:
Loop over the triplets (monkey_bins, empty_bins, tiger_bins) deciding how many bins have monkeys, are empty, or have tigers;
For the loop, we can use bounds 1 <= monkey_bins <= 5; 0 <= empty_bins <= 5 - monkey_bins; tiger_bins = 6 - monkey_bins - empty_bins;
Count the number m of ways to choose monkey_bins bins, empty_bins bins and tiger_bins bins among 6 bins (Multinomial coefficient);
Count the number monkey_partitions of ways to place n_monkeys 'M' into monkey_bins bins with at least one M per bin (Stars and bars theorem 1);
Count the number tiger_partitions of ways to place n_tigers 'T' into tiger_bins bins with at least one T per bin (Stars and bars theorem 1;
Add m * monkey_partitions * tiger_partitions to the count.
Python code with loops
import math
def multinomial(*params):
return math.prod(math.comb(sum(params[:i]), x) for i, x in enumerate(params, 1))
def count_monkeytigers(n_monkeys, n_snakes, n_tigers):
result = 0
for monkey_bins in range(1, n_snakes + 1):
for empty_bins in range(0, n_snakes + 1 - monkey_bins):
tiger_bins = n_snakes + 1 - monkey_bins - empty_bins
m = multinomial(monkey_bins - 1, empty_bins, tiger_bins - 1) # nb permutations of the 3 types of bins
monkey_partitions = math.comb(n_monkeys - 1, monkey_bins - 1)
tiger_partitions = math.comb(n_tigers - 1, tiger_bins - 1)
result += m * monkey_partitions * tiger_partitions
return result
print(count_monkeytigers(5, 5, 5))
# 1251
print(count_monkeytigers(2,2,2))
# 3
# = len(['MMSSTT', 'MSMSTT', 'MMSTST'])
The code for multinomial comes from this question:
Does python have a function which computes multinomial coefficients?
Note that we're only using a "trinomial" coefficient here, so you can replace function multinomial with this simpler function if you want:
def trinomial(k1,k2,k3):
return math.comb(k1+k2+k3, k1) * math.comb(k2+k3, k2)
Python code using sympy
In the previous python code, we're manually looping over the possible triplets (monkey_bins, empty_bins, tiger_bins) and using the corresponding binomial coefficients. As it turns out, sympy.ntheory.multinomial_coefficients(m, n) returns a dictionary that contains specifically those triplets as keys and the corresponding multinomial coefficients as values!
We can use that to shorten our code:
import sympy # sympy.ntheory.multinomial_coefficients
import math # math.comb
def count_monkeytigers(n_monkeys, n_snakes, n_tigers):
return sum(
m * math.comb(n_monkeys - 1, mb_minus1) * math.comb(n_tigers - 1, tb_minus1)
for (mb_minus1, eb, tb_minus1), m in
sympy.ntheory.multinomial_coefficients(3, n_snakes-1).items()
)
print(count_monkeytigers(5, 5, 5))
# 1251
print(count_monkeytigers(2,2,2))
# 3
# = len(['MMSSTT', 'MSMSTT', 'MMSTST'])
Note that the dictionary multinomial_coefficients(3, n) contains all triplets of nonnegative numbers summing to n, including those where the middle-element empty_bins is equal to n, and the other two elements are 0. But we want at least one bin with monkeys, and at least one bin with tigers; hence I called the triplet (mb_minus1, eb, tb_minus1) rather than (mb, eb, tb), and accordingly I used n_snakes-1 rather than n_snakes+1 as the sum of the triplet.
Before writing code directly , Just solve the question on paper upto the factorial notations , then you can easily find factorial in Code
At first , fix 1 monkey at front and 1 tiger at end .
Then try to fix remaining tigers , then fix snakes in adjancent of tigers , Atleast one snake must be in adjacent of a tiger and then fix monkeys in adjacent of snakes
I have two symmetric matrices A, B and a vector X. The dimension of A is n by n, the dimension of B is n by n, the dimension of X is n by 1. Let the element at ith row and jth column of matrix A denoted by A[i,j].
Since A is symmetric, only each column of the upper triangular matrix of A is saved. The matrix A is saved as an array:
Vector_A = [A[1,1],
A[1,2], A[2,2],
A[1,3], A[2,3], A[3,3],
A[1,4], A[2,4], A[3,4], A[4,4],
...,
A[1,n], A[2,n], ..., A[n,n]]
The matrix B is saved in the same format as matrix A. Now I would like to calculate ABA without transforming Vector_A, Vector_B back to matrix A, B. Since ABA is also symmetric, I would like to save the ABA in the same way as an array. How can I do it in Julia?
I would also like to calculate X'AX without transforming Vector_A back to matrix A where X' denotes transpose(X). How can I do it in Julia?
You need to implement your own data structures that inherit from the the AbstractMatrix type.
For example this could be done as:
struct SymmetricM{T} <: AbstractMatrix{T}
data::Vector{T}
end
So we have a symmetric matrix that is using only a vector for its data storage.
Now you need to implement functions so it actually behaves like a matrix so you can let the Julia magic work.
We start by providing the size of our new matrix datatype.
function Base.size(m::SymmetricM)
n = ((8*length(m.data)+1)^0.5-1)/2
nr = round(Int, n)
#assert n ≈ nr "The vector length must match the number of triang matrix elements"
(nr,nr)
end
In this code nr will be calculate every time to checkbounds is done on matrix. Perhaps in your production implementation you might want to move it to be a field of SymmetricM. You would scarify some elasticity and store 8 bytes more but would gain on the speed.
Now the next function we need is to calculate position of the vector on the base of matrix indices. Here is one possible implementation.
function getix(idx)::Int
n = size(m)[1]
row, col = idx
#assume left/lower triangular
if col > row
row = col
col = idx[1]
end
(row-1)*row/2 + col
end
Having that now we can implement getindex and setindex functions:
#inline function Base.getindex(m::SymmetricM, idx::Vararg{Int,2})
#boundscheck checkbounds(m, idx...)
m.data[getix(idx)]
end
#inline function Base.getindex(m::SymmetricM{T}, v::T, idx::Vararg{Int,2}) where T
#boundscheck checkbounds(m, idx...)
m.data[getix(idx)] = v
end
Now let us test this thing:
julia> m = SymmetricM(collect(1:10))
4×4 SymmetricM{Int64}:
1 2 4 7
2 3 5 8
4 5 6 9
7 8 9 10
You can see that we have provide elements of only one triangle (be it the lower or upper - they are the same) - and we got the full matrix!
This is indeed a fully valid Julia matrix so all matrix algebra should work on it:
julia> m * SymmetricM(collect(10:10:100))
4×4 Array{Int64,2}:
700 840 1010 1290
840 1020 1250 1630
1010 1250 1580 2120
1290 1630 2120 2940
Note that the result of multiplication is a Matrix rather than SymmetricM - to get a SymmetricM you need to overload the * operator to accept 2 SymmetricM arguments. For illustrative purposes let us show a custom operator overloading with the minus sign -:
import Base.-
-(m1::SymmetricM, m2::SymmetricM) = SymmetricM(m1.data .- m2.data)
And now you will see that substraction of SymmetricM is going to return another SymmetricM:
julia> m-m
4×4 SymmetricM{Int64}:
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
In this way you can build a full triangular matrix algebra system in Julia.
Note that however the getix function has an if statement so access to SymmetricM elements without using the data field will be much slower than those of a regular matrix so perhaps you should try to overload as many operators as is required for your project.
Below is a table which has a recursive relation as current cell value is the sum of the upper and left cell.
I want to find the odd positions for any given row denoted by v(x) as represented in the first column.
Currently, I am maintaining two one arrays which I update with new sum values and literally checking if each positions value is odd or even.
Is there a closed form that exists which would allow me to directly say what are the odd positions available (say, for the 4th row, in which case it should tell me that p1 and p4 are the odd places).
Since it is following a particular pattern I feel very certain that a closed form should exist which would mathematically tell me the positions rather than calculating each value and checking it.
The numbers that you're looking at are the numbers in Pascal's triangle, just rotated ninety degrees. You more typically see it written out like this:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
...
You're cutting Pascal's triangle along diagonal stripes going down the left (or right, depending on your perspective) strips, and the question you're asking is how to find the positions of the odd numbers in each stripe.
There's a mathematical result called Lucas's theorem which is useful for determining whether a given entry in Pascal's triangle is even or odd. The entry in row m, column n of Pascal's triangle is given by (m choose n), and Lucas's theorem says that (m choose n) mod 2 (1 if the number is odd, 0 otherwise) can be found by comparing the bits of m and n. If n has a bit that's set in a position where m doesn't have that bit set, then (m choose n) is even. Otherwise, (m choose n) is odd.
As an example, let's try (5 choose 3). The bits in 5 are 101. The bits in 3 are 011. Since the 2's bit of 3 is set and the 2's bit of 5 is not set, the quantity (5 choose 3) should be even. And since (5 choose 3) = 10, we see that this is indeed the case!
In pseudocode using relational operators, you essentially want the following:
if ((~m & n) != 0) {
// Row m, entry n is even
} else {
// Row m, entry n is odd.
}
I am solving a constrained optimization problem in R iteratively where the problem if of the following form:
min f(x)
s.t. g(x) < 0
I am doing the optimization iteratively and so I have a variable called f that holds the current value of the function f and vector g of 1's and 0's that tells me if the constraint was met for the ith iteration. To help, here is an example
#Imagine there are 6 time points
f = c(7,10,6,3,-1,-9)
g = c(1,1,0,1,1,0)
And so I want to keep track of the best minimum value found at the ith iteration such that the constraint was satisfied. Thus I want to be able to calculate a vector like
h = c(7,7,7,3,-1,-1)
Where h records the minimum value found in time such that the constraint was met. Is there an easy way to do this in R either in loops or not?
Given your f and g, I would do it like this:
cummin(zoo::na.locf(ifelse(g == 1, f, NA)))
# [1] 7 7 7 3 -1 -1
Or, perhaps more simply:
cummin((ifelse(g == 1, f, Inf)))
# [1] 7 7 7 3 -1 -1
I have a vector of 874! elements, which I want to turn into a triangular matrix (i.e. the top right hand corner of a square matrix).
Example Input:
1
2
3
4
5
6
7
8
9
10
Example Output:
1 2 4 7
3 5 8
6 9
10
Blanks could be filled with NAs. I'd prefer if the matrix were this way around.
I don't know which programming language do you want to use neither do I understand which order do you want your numbers to be stored in.
You should consider that having N elements, if you want to generate an square matrix its dimensions (n rows and columns) are given by:
N = (n*(n+1))/2
So a first approach (you should consider if your input vector has x^2/2 elements) in Python could be:
from math import sqrt
x = range(1,25+1) # This is your input vector
N = len(x)
#N = (n*(n+1))/2 # Number of elements being stored in a triangular matrix.
n = (-1.0+sqrt(1.0+8.0*N))/2.0 # Solve the equation given by the previous relation.
n = int(round(n)) # Making it integer...
while (n*(n+1))/2 < N: # ... losing precission so we should use the first n being able ...
if (n*(n+1))/2 < N: # ... to store your vector is used.
n += 1
res = [[0]*n for i in xrange(n)] # Here, we create a n*n matrix filled with zeros.
x = x[::-1] #Reverse the input so it can be consumed using pop (O(1) each extraction)
for j in xrange(n): # Fill the empty matrix following the triangular pattern and using...
if not x:
break
for i in xrange(j+1):
if not x:
break
res[i][j] = x.pop() # The elements from your input vector.
for row in res: # Let's print the result!
print(row)
The idea is to consume x filling the square matrix (res) with is values in the right order. This can easily done once you now your target matrix dimesions.