Find the same numbers between [a,b] intervals - c++

Suppose I have 3 array of consecutive numbers
a = [1, 2, 3]
b = [2, 3, 4]
c = [3, 4]
Then the same number that appears in all 3 arrays is 3.
My algorithm is to use two for loops in each other to check for the same array and push it in another array (let's call it d). Then
d = [2, 3] (d = a overlap b)
And use it again to check for array d and c => The final result is 1, cause there are only 1 numbers that appears in all 3 arrays.
e = [3] (e = c overlap d) => e.length = 1
Other than that, if there exists only 1 array, then the algo should return the length of the array, as all of its numbers appear in itself. But I think my said algo above would take too long because the numbers of array can go up to 10^5. So, any idea of a better algorithm?

But I think my said algo above would take too long because the numbers of array can go up to 105. So, any idea of a better algorithm?
Yes, since these are ranges, you basically want to calculate the intersection of the ranges. This means that you can calculate the maximum m of all the first elements of the lists, and the minimum n of all the last elements of the list. All the numbers between m and n (both inclusive) are then members of all lists. If m>n, then there are no numbers in these lists.
You do not need to calculate the overlap by enumerating over the first list, and check if these are members of the last list. Since these are consecutive numbers, we can easily find out what the overlap is.
In short, the overlap of [a, ..., b] and [c, ..., d] is [ max(a,c), ..., min(b,d) ], there is no need to check the elements in between.

Related

Combination of elements of lists that meet some condition?

Given:
a = [5, 2, 8, 3, 9]
b = [3, 5, 7, 6, 8]
c = [8, 5, 7, 4, 9].
What is needed:
d = [(9, 8), (8, 7), ..., (5, 5, 5), (5, 6, 5), (5, 6, 7), ..., (8, 7, 7), (9, 8, 9), ...].
Description:
(1) In the above example, there are three lists a, b, c having integer elements and the output is another list d of tuples.
(2) The tuples in d have elements belonging to (a and b and c) or (a and b) or (b and c) such that difference between elements within any tuple is not greater than 1.
(3) Problem: How to find the complete list d where we take any element from any input list and find the difference less than or equal to 1. Generalize to more than just three input list: a, b, c, d, e, ... and each one is having ~ 1000 elements. I also need to retrieve the indices relative to the input lists/ arrays that form the tuples.
(4) Clarification: (a) All such tuples which contain entries not differing by more than 1 are allowed.
(b) Tuples must have elements that are close to at least one other element by not more than 1.
(c) Entries within a tuple must belong to different input arrays/ lists.
Let me know if there are further clarifications needed!
You can use sorting to find results faster than a naive brute-force. That being said, this assumes the number of output tuple is reasonably small. Otherwise, there is no way to find a solution in a reasonable time (eg. several months). As #mosway pointed out in the comments, the number of combinations can be insanely huge since the complexity is O(N ** M) (ie. exponential) where N is the number of list and M is the length of the lists.
The idea is to use np.unique on all lists so to get many sorted arrays with unique items. Then, you can iterate over the first array, and for each number (in the first array), find the range of values in the second one fitting in [n-1;n+1] using a np.searchsorted. You can then iterate over the filtered values of the second array and recursively do that on other array.
Note that regarding which array is chosen first, the method can be significantly faster. Thus, a good heuristic could be to select an array containing values very distant from others. Computing a distance matrix with all the values of all array and selecting the one having the biggest average distance should help.
Note also that using Numba should significantly speed up the recursive calls.

Determine all square sub matrices of a given NxN matrix in C++

GIven an NxN square matrix, I would like to determine all possible square sub matrices by removing equal number of rows and columns.
In order to determine all possible 2x2 matrices I need to loop 4 times. Similarly for 3x3 matrices I need to loop 6 times and so on. Is there a way to generate code in C++ so that the code for the loops is generated dynamically? I have checked some answers related to code generation in C++, but most of them use python in it. I have no idea regarding python. So, is it possible to write code to generate code in C++?
If I get what you are saying, you mean you require M loops to choose M rows, and M loops for M columns for an M x M sub matrix, 1 <= M <= N
You don't need 2*M loops to do this. No need to dynamically generate code with an ever-increasing number of loops!
Essentially, you need to "combine" all possible combinations of i_{1}, i_{2}, ..., i_{M} and j_{1}, j_{2}, ..., j_{M} such that 1 <= i_{1} < i_{2} < ... < i_{M} <= N (and similarly for j)
If you have all possible combinations of all such i_{1}, ..., i_{M} you are essentially done.
Say for example you are working with a 10 x 10 matrix and you require 4 x 4 sub matrices.
Suppose you selected rows {1, 2, 3, 4} and columns {1, 2, 3, 4} initially. Next select column {1, 2, 3, 5}. Next {1, 2, 3, 6} and so on till {1, 2, 3, 10}. Next select {1, 2, 4, 5}, next {1, 2, 4, 6} and so on till you reach {7, 8, 9, 10}. This is one way you could generate all ("10 choose 4") combinations in a sequence.
Go ahead, write a function that generates this sequence and you are done. It can take as input M, N, current combination (as an array of M values) and return the next combination.
You need to call this sequence to select the next row and the next column.
I have put this a little loosely. If something is not clear I can edit to update my answer.
Edit:
I will be assuming loop index starts from 0 (the C++ way!). To elaborate the algorithm further, given one combination as input the next combination can be generated by treating the combination as a "counter" of sorts (except that no digit repeats).
Disclaimer : I have not run or tested the below snippet of code. But the idea is there for you to see. Also, I don't use C++ anymore. Bear with me for any mistakes.
// Requires M <= N as input, (N as in N x N matrix)
void nextCombination( int *currentCombination, int M, int N ) {
int *arr = currentCombination;
for( int i = M - 1; i >= 0; i-- ) {
if( arr[i] < N - M + i ) {
arr[i]++;
for( i = i + 1, i < M; i++ ) {
arr[i] = arr[i - 1] + 1;
}
break;
}
}
}
// Write code for Initialization: arr = [0, 1, 2, 3]
nextCombination( arr, 4, 10 );
// arr = [0, 1, 2, 4]
// You can check if the last combination has been reached by checking if arr[0] == N - M + 1. Please incorporate that into the function if you wish.
Edit:
Actually I want to check singularity of all possible sub matrices. My approach is to compute all submatrices and then find their determinants. How ever after computing the determinant of 2x2 matrices , I'll store them and use while computing determinants of 3x3 matrices. And so on. Can you suggest me a better approach. I have no space and time constraints. – vineel
A straight-forward approach using what you suggest is to index the determinants based on the the rows-columns combination that makes a sub matrix. At first store determinants for 1 x 1 sub matrices in a hash map (basically the entries themselves).
So the hash map would look like this for the 10 x 10 case
{
"0-0" : arr_{0, 0},
"0-1" : arr_{0, 1},
.
.
.
"1-0" : arr_{1, 0},
"1-1" : arr_{1, 1},
.
.
.
"9-9" : arr_{9, 9}
}
When M = 2, you can calculate determinant using the usual formula (the determinants for 1 x 1 sub matrices having been initialized) and then add to the hash map. The hash string for a 2 x 2 sub matrix would look something like 1:3-2:8 where the row indices in the original 10 x 10 matrix are 1,3 and the column indices are 2, 8. In general, for m x m sub matrix, the determinant can be determined by looking up all necessary (already) computed (m - 1) x (m - 1) determinants - this is a simple hash map lookup. Again, add the determinant to hash map once calculated.
Of course, you may need to slightly modify the nextCombination() function - it currently assumes row and column indices run from 0 to N - 1.
On another note, since all sub matrices are to be processed starting from 1 x 1, you don't need something like a nextCombination() function. Given a 2 x 2 matrix, you just need to select one more row and column to form a 3 x 3 matrix. So you need to select one row-index (that's not part of the row indices that make the 2 x 2 sub matrix) and similarly one column-index. But doing this for every 2 x 2 matrix will generate duplicate 3 x 3 matrices - you need to think of some way to eliminate duplicates. One way to avoid duplicates is by choosing only such row/column whose index is greater than the highest row/column index in the sub matrix.
Again I have loosely defined the idea. You can build upon it.

Mathematica collecting elements in a list

Given the 256 tuples generated from:
Tuples[{a,b,c,d},4] = {{a,a,a,a},{a,a,a,b}...,{d,d,d,d}}
I would like to filter all of the tuples that have exactly 3 of a kind. For example, I want to keep {c,b,c,c} & {a,a,d,a} etc.. but not {d,d,d,d} or {a,b,b,c}.
I know there are:
Binomial[4,3]*4*3 = 48
such tuples from simple maths. But I am looking for a programmatic way of counting these.
My final goal is from the tuples:
Tuples[{1,2,3,...,n},k]
I would like to know how many of those tuples have exactly one subset with m of a kind, with all other subgroups of a kind having size less than m.
In case you are interested, this problem spawned from asking: What is the average number of rounds played before there is a winner in the game "Cards Against Humanity"? Assuming we have n players and the first person with x cards wins.
This will find your 48 tuples
Select[Tuples[{a, b, c, d}, 4],
MatchQ[Sort[#], {a_, a_, a_, b_} | {b_, a_, a_, a_}] &&
Length[Union[#]] != 1 &]
This will show you the tuples of four items over 1,...,6 with m identical items and all other items appearing less than m times.
m = 2;
f[v_] := Module[{runlens},
runlens = Sort[Map[Length, Split[Sort[v]]]];
runlens[[-1]] == m && If[Length[runlens] == 1, True, runlens[[-2]] < m]]
];
Select[Tuples[Range[6], 4], f]
Use Count on that result and you know how many you have.
Another approach:
Select[ Tuples[{a, b, c, d}, 4] ,
((Count[#, 3] == 1 && Max[#] == 3) &#Tally[#][[All, 2]] ) & ]
Of course if the set size is greater than half the list length it is redundant to check both Max and Count

How to find closest exceeding number between two lists?

I have two lists of numbers list A and list B
I want to map every number in list A to a number in list B. That number is the closest number that list A exceeds in list B.
So for example, if i have the number 5 in list A and there are the numbers 3 and 6 in list B, then I want the number 5 to map to 3.
I realize I could do this by taking the difference between each number in list A with each number in list B then indexing and such but my list A and list B are extremely long and was wondering if there was a more efficient way to go about this.
Thanks!
You say you are looking for something faster than getting the difference. If you look at this answer, which computes the closest value for a single item in O(n), your list would only take O(n^2), which is really quick. Your solution would look like this:
>>> A = [100, 7, 9]
>>> B = [2, 5, 6, 8, 123, 12]
>>> [min(A, key=lambda x: 2**16 if x > y else abs(x-y)) for y in B]
[12, 6, 8]
The 2**16 is slightly dirty, but gets the job done.

haskell, counting how many prime numbers are there in a list

i m a newbie to haskell, currently i need a function 'f' which, given two integers, returns the number of prime numbers in between them (i.e., greater than the first integer but smaller than the second).
Main> f 2 4
1
Main> f 2 10
3
here is my code so far, but it dosent work. any suggestions? thanks..
f :: Int -> Int -> Int
f x y
| x < y = length [ n | n <- [x..y], y 'mod' n == 0]
| otherwise = 0
Judging from your example, you want the number of primes in the open interval (x,y), which in Haskell is denoted [x+1 .. y-1].
Your primality testing is flawed; you're testing for factors of y.
To use a function name as an infix operator, use backticks (`), not single quotes (').
Try this instead:
-- note: no need for the otherwise, since [x..y] == [] if x>y
nPrimes a b = length $ filter isPrime [a+1 .. b-1]
Exercise for the reader: implement isPrime. Note that it only takes one argument.
Look at what your list comprehension does.
n <- [x..y]
Draw n from a list ranging from x to y.
y `mod` n == 0
Only select those n which evenly divide y.
length (...)
Find how many such n there are.
What your code currently does is find out how many of the numbers between x and y (inclusive) are factors of y. So if you do f 2 4, the list will be [2, 4] (the numbers that evenly divide 4), and the length of that is 2. If you do f 2 10, the list will be `[2, 5, 10] (the numbers that evenly divide 10), and the length of that is 3.
It is important to try to understand for yourself why your code doesn't work. In this case, it's simply the wrong algorithm. For algorithms that find whether a number is prime, among many other sources, you can check the wikipedia article: Primality test.
I you want to work with large intervals, then it might be a better idea to compute a list of primes once (instead of doing a isPrime test for every number):
primes = -- A list with all prime numbers
candidates = [a+1 .. b-1]
myprimes = intersectSortedLists candidates primes
nPrimes = length $ myprimes