Arranging array into all possible pairs - c

I am working on a problem (in C) that requires me to list all possible connections between an even number of points, so that every point is connected to only one other point. For example, say I have points 1, 2, 3, and 4:
1 - 2, 3 - 4
1 - 3, 2 - 4
1 - 4, 2 - 3
The order of the points doesn't matter (1 - 2 is same as 2 - 1), and the order of connections doesn't too (1 - 2, 3 - 4 same as 3 - 4, 1 - 2).
I am currently trying to simply order the array such as {1, 2, 3, 4} into all possible orderings and check to see if it is already generated. However this can be very expensive and also the ordering of the points and pairs needs to be disregarded.
What would be a better way to arrange an array into all possible pairs? A basic outline of an algorithm would be appreciated!
Edit: in the example above with {1, 2, 3, 4}, if pairings are represented as two adjacent elements in the array, all possible outcomes would be:
{1, 2, 3, 4}: 1 - 2, 3 - 4
{1, 3, 2, 4}: 1 - 3, 2 - 4
{1, 4, 2, 3}: 1 - 4, 2 - 3
I would need the entire arranged array to perform calculations based on all the connections.

This can be accomplished by nondeterministically pairing the rightmost unpaired element and recursing. In C:
void enum_matchings(int n, int a[static n]) {
if (n < 2) {
// do something with the matching
return;
}
for (int i = 0; i < n-1; i++) {
int t = a[i];
a[i] = a[n-2];
a[n-2] = t;
enum_matchings(n-2, a);
a[n-2] = a[i];
a[i] = t;
}
}

Related

Rearrange an array A so that A wins maximum number of comparisons with array B when comparison is done one-on-one

Let's say I have an array A = [3, 6, 7, 5, 3, 5, 6, 2, 9, 1] and B = [2, 7, 0, 9, 3, 6, 0, 6, 2, 6]
Rearrange elements of array A so that when we do comparison element-wise like 3 with 2 and 6 with 7 and so on, we have maximum wins (combinations where A[i] > B[i] are maximum (0<=i<len(A))).
I tried below approach:
def optimal_reorder(A,B,N):
tagged_A = [('d',i) for i in A]
tagged_B = [('a',i) for i in B]
merged = tagged_A + tagged_B
merged = sorted(merged,key=lambda x: x[1])
max_wins = 0
for i in range(len(merged)-1):
print (i)
if set((merged[i][0],merged[i+1][0])) == {'a','d'}:
if (merged[i][0] == 'a') and (merged[i+1][0] == 'd'):
if (merged[i][1] < merged[i+1][1]):
print (merged[i][1],merged[i+1][1])
max_wins += 1
return max_wins
as referenced from
here
but this approach doesn't seem to give correct answer for given A and B i,e if A = [3, 6, 7, 5, 3, 5, 6, 2, 9, 1] and B = [2, 7, 0, 9, 3, 6, 0, 6, 2, 6] then maximum wins is 7 but my algorithm is giving 5.
is there something I am missing here.
revised solution as suggested by #chqrlie
def optimal_reorder2(A,B):
arrA = A.copy()
C = [None] * len(B)
for i in range(len(B)):
k = i + 1
all_ele = []
while (k < len(arrA)):
if arrA[k] > B[i]:
all_ele.append(arrA[k])
k += 1
if all_ele:
e = min(all_ele)
else:
e = min(arrA)
C[i] = e
arrA.remove(e)
return C
How about this algorithm:
start with an empty array C.
for each index i in range(len(B)).
if at least one of the remaining elements of A is larger than B[i], choose e as the smallest of these elements, otherwise choose e as the smallest element of A.
set C[i] = e and remove e from A.
C should be a reordering of A that maximises the number of true comparisons C[i] > B[i].
There’s probably a much better algorithm than this, but you can think of this as a maximum bipartite matching problem. Think of the arrays as the two groups of nodes in the bipartite graph, then add an edge from A[i] to B[j] if A[i] > B[j]. Then any matching tells you how to pair elements of A with elements of B such that the A element “wins” against the B element, and a maximum matching tells you how to do this to maximize the number of wins.
I’m sure there’s a better way to do this, and I’m excited to see what other folks come up with. But this at least shows you can solve this in polynomial time.

Algorithm for array permutation

We have an integer array A[] of size N (1 ≤ N ≤ 10^4), which originally is a sorted array with entries 1...N. For any permutation P of size N, the array is shuffled so that i-th entry from the left before the shuffle is at the Ai-th position after the shuffle. You would keep repeating this shuffle until the array is sorted again.
For example, for A[] = {1, 2, 3, 4}, if P = {1, 2, 3, 4}, it would only take one move for the array to be sorted (the entries would move to their original positions). If P = {4, 3, 1, 2}, then it would take 4 moves for the array to be sorted again:
Move 0 | [1, 2, 3, 4]
Move 1 | [3, 4, 2, 1]
Move 2 | [2, 1, 4, 3]
Move 3 | [4, 3, 1, 2]
Move 4 | [1, 2, 3, 4]
The problem is to find the sum of all positive integers J for which you can generate a permutation that requires J moves to get the array sorted again.
Example:
For A[] = {1, 2, 3, 4}, you can generate permutations that require 1, 2, 3, and 4 steps:
Requires 1 move: P = {1, 2, 3, 4}
Requires 2 moves: P = {1, 3, 2, 4}
Requires 3 moves: P = {1, 4, 2, 3}
Requires 4 moves: P = {4, 3, 1, 2}
So you would output 1 + 2 + 3 + 4 = 10.
Some observations I have made is that you can always generate a permutation that requires J moves for (1 ≤ J < N). This is because in the permutation, you would simply shift by 1 all the entries in the range of size J. However, for permutations that requires J moves where J ≥ N, you would need another algorithm.
The brute-force solution would be checking every permutation, or N! permutations which definitely wouldn't fit in run time. I'm looking for an algorithm with run time at most O(N^2).
EDIT 1: A permutation that requires N moves will always be guaranteed as well, as you can create a permutation where every entry is misplaced, and not just swapped with another entry. The question becomes how to find permutations where J > N.
EDIT 2: #ljeabmreosn made the observation that there exists a permutation that takes J steps if and only if there are natural numbers a_1 + ... + a_k = N and LCM(a_1, ..., a_k) = J. So using that observation, the problem comes down to finding all partitions of the array, or partitions of the integer N. However, this won't be a quadratic algorithm - how can I find them efficiently?
Sum of distinct orders of degree-n permutations.
https://oeis.org/A060179
This is the number you are looking for, with a formula, and some maple code.
As often when trying to compute an integer sequence, compute the first few values (here 1, 1, 3, 6, 10, 21) and look for it in the great "On-line Encyclopedia of Integer Sequences".
Here is some python code inspired by it, I think it fits your complexity goals.
def primes_upto(limit):
is_prime = [False] * 2 + [True] * (limit - 1)
for n in range(int(limit**0.5 + 1.5)):
if is_prime[n]:
for i in range(n*n, limit+1, n):
is_prime[i] = False
return [i for i, prime in enumerate(is_prime) if prime]
def sum_of_distinct_order_of_Sn(N):
primes = primes_upto(N)
res = [1]*(N+1)
for p in primes:
for n in range(N,p-1,-1):
pj = p
while pj <= n:
res[n] += res[n-pj] * pj
pj *= p
return res[N]
on my machine:
>%time sum_of_distinct_order_of_Sn(10000)
CPU times: user 2.2 s, sys: 7.54 ms, total: 2.21 s
Wall time: 2.21 s
51341741532026057701809813988399192987996798390239678614311608467285998981748581403905219380703280665170264840434783302693471342230109536512960230

How to get the minimum addition result from 2 arrays within k swaps?

I ran into an interesting algorithm(maybe :/) question, and as I am just starting out with algorithms and data structure, it's a little bit hard for me to resolve. Could you please have a look and maybe give me some advice :)
Here is the question:
There are two integer arrays with same length - n, one switch number k which allows at most k times swap between 2 arrays, how to find the minimum addition result after k swaps?
Something important is:
Between 2 swaps, the elements should come form same array!
It may be a little confusing........ here is the example:
ex:
{1, 5, 3, 2, 4} Array A
{3, 4, 1, 6, 2} Array B
k - 2 Max swap chance
the minimum result should be 1-A[0] + 4-B[1] + 1-B[2] + 2-A[3] + 4-A[4] = 12
first swap second swap
A -> B B -> A
There is path like :
1 2 4
4 1
Please note that:
If we choose A[0] (because A[0] < B[0] ), then Array A have to be the base array.
And the swap here: 1 A[1] -> 4 B[1] is the first swap
after above swap, the next number have to be 1 (B[2]) if we do not do another swap from B to A
1 A[3] -> 2 B[3] is the second swap
In my example:
We choose 1 in Array A, then the first swap(replace) happens between A[1] and B[1],
and after second swap happens at A[3], we could not do more swap now because k has reached to 2 (k should <= 2)
In the following case:
{1 5 3 7 1 1 3}
{3 1 4 1 3 9 2}
^ ^
if we only have at most 2 chance to swap, they should happen at '^' because
1 1 3
1 4 1 3
could result in minimum addition result
Lets make it more general:
{1, 5, ... , 3, ... , 2, 4} Array A
{3, 4, ... , 1, ... , 6, 2} Array B
k - n Max swap chance
The key point here is: how could I decide whether the first swap should still
happen between A[1] and B[1] or there may be another better chance to do a swap
between A[i-th] and B[i-th] .
And we only have at most k times swap chance, so when and where should the
k swaps happen need to be considered carefully..
I am trying to make the question more clear, if there is still something confusing, please tell me.
Any ideas of how to decide where to swap and how many times to swap and finally get the minimum calculation result? Thanks a lot!
Well, if I've understood you right you have 2 possibilities:
swap items of each pair of i-th items to make A array contain min items
swap items of each pair of i-th items to make B array contain min items
In your case:
Let's make A have min items:
{1, 5, 3, 2, 2} Array A
{3, 4, 1, 6, 4} Array B
---------------
{1 4 1 2 2} Min (based on A, 2 swaps)
^ ^
swap (we take items from B)
Let's make B have min items:
{1, 5, 3, 2, 2} Array A
{3, 4, 1, 6, 4} Array B
---------------
{1 4 1 2 2} Min (based on B, 3 swaps)
^ ^ ^
swap (we take items from A)
Here 2 < 3 so we should make A contain minimum items and we can do it in 2 swaps
So far, so good in general case you can
Count swaps (let it be swapsA) required to make A contain min items of each pair.
Count swaps (let it be swapsB) required to make B contain min items of each pair.
Return Min(swapsA, swapsB)
Possible C# code
int[] A = ...
int[] B = ...
int swapsA = 0;
int swapsB = 0;
int sum = 0;
for (int i = 0; i < A.Length; ++i) {
sum += Math.Min(A[i], B[i]);
if (A[i] > B[i])
swapsA += 1;
else if (A[i] < B[i])
swapsB += 1;
}
int swaps = Math.Min(swapsA, swapsB);
Console.Write($"We have to make at least {swaps} swaps; the min sum is {sum}");
Edit: the only diffiuclty is when items are equal, e.g.
{1, 5, 1, 2, 4} Array A # note that 3d and 4th pairs have equal items
{3, 4, 1, 2, 2} Array B
---------------
{1 4 1 2 2} Min (based on A, 1 swap)
^ ^
swap (we take items from B)
Let's make B have min items:
{1, 5, 1, 2, 4} Array A
{3, 4, 1, 2, 2} Array B
---------------
{1 4 1 2 4} Min (based on B, 2 swaps)
^
swap (we take items from A)
note, that in general case swapsA + swapsB <= A.Length
Edit 2: If you have up to K swaps to perform you can order them and take K the most promising (with maximum A[i] - B[i] difference):
Let's swap and sum A
{1 5 3 7 1 1 3} A
{3 1 4 1 3 9 2} B
^ ^ ^
reasonable swaps - 3 - more than allowed 2
{5, 1} drops sum by 5 - 1 == 4 # most promising (a best sum drop)
{7, 1} drops sum by 7 - 1 == 6 # most promising (a best sum drop)
{3, 2} drops sum by 3 - 2 == 1
the most promising swaps are {7, 1} and {5, 1}. So we have 1 + 1 + 3 + 1 + 1 + 1 + 3.
Let's swap and sum A
{1 5 3 7 1 1 3} A
{3 1 4 1 3 9 2} B
^ ^ ^ ^
reasonable swaps - 4 - more than allowed 2
{1, 3} drops sum by 3 - 1 == 2 # most promising (a best sum drop)
{3, 4} drops sum by 4 - 3 == 1
{1, 3} drops sum by 3 - 1 == 2
{1, 9} drops sum by 9 - 1 == 8 # most promising (a best sum drop)
So we have {1, 3} and {1, 9} swaps more promising and the sum is 1 + 1 + 4 + 1 + 3 + 1 + 2.
Finally you should compare both possibnbilities (if you make minimum sum from A or from B)

Finding (multiset) difference between two arrays

Given arrays (say row vectors) A and B, how do I find an array C such that merging B and C will give A?
For example, given
A = [2, 4, 6, 4, 3, 3, 1, 5, 5, 5];
B = [2, 3, 5, 5];
then
C = multiset_diff(A, B) % Should be [4, 6, 4, 3, 1, 5]
(the order of the result does not matter here).
For the same A, if B = [2, 4, 5], then the result should be [6, 4, 3, 3, 1, 5, 5].
(Since there were two 4s in A and one 4 in B, the result C should have 2 - 1 = 1 4 in it. Similarly for the other values.)
PS: Note that setdiff would remove all instances of 2, 3, and 5, whereas here they need to be removed just however many times they appear in B.
Performance: I ran some quick-n-dirty benchmarks locally, here are the results for future reference:
#heigele's nested loop method performs best for small lengths of A (say upto N = 50 or so elements). It does 3x better for small (N=20) As, and 1.5x better for medium-sized (N=50) As, compared to the next best method - which is:
#obchardon's histc-based method. This is the one performs the best when A's size N starts to be 100 and above. For eg., this does 3x better than the above nested loop method when N = 200.
#matt's for+find method does comparably to the histc method for small N, but quickly degrades in performance for larger N (which makes sense since the entire C == B(x) comparison is run every iteration).
(The other methods are either several times slower or invalid at the time of writing.)
Still another approach using the histc function:
A = [2, 4, 6, 4, 3, 3, 1, 5, 5, 5];
B = [2, 3, 5, 5];
uA = unique(A);
hca = histc(A,uA);
hcb = histc(B,uA);
res = repelem(uA,hca-hcb)
We simply calculate the number of repeated elements for each vectors according to the unique value of vector A, then we use repelem to create the result.
This solution do not preserve the initial order but it don't seems to be a problem for you.
I use histc for Octave compatibility, but this function is deprecated so you can also use histcounts
Here's a vectorized way. Memory-inefficient, mostly for fun:
tA = sum(triu(bsxfun(#eq, A, A.')), 1);
tB = sum(triu(bsxfun(#eq, B, B.')), 1);
result = setdiff([A; tA].', [B; tB].', 'rows', 'stable');
result = result(:,1).';
The idea is to make each entry unique by tagging it with an occurrence number. The vectors become 2-column matrices, setdiff is applied with the 'rows' option, and then the tags are removed from the result.
You can use the second output of ismember to find the indexes where elements of B are in A, and diff to remove duplicates:
This answer assumes that B is already sorted. If that is not the case, B has to be sorted before executing above solution.
For the first example:
A = [2, 4, 6, 4, 3, 3, 1, 5, 5, 5];
B = [2, 3, 5, 5];
%B = sort(B); Sort if B is not sorted.
[~,col] = ismember(B,A);
indx = find(diff(col)==0);
col(indx+1) = col(indx)+1;
A(col) = [];
C = A;
>>C
4 6 4 3 1 5
For the second example:
A = [2, 4, 6, 4, 3, 3, 1, 5, 5, 5];
B = [2, 4, 5, 5];
%B = sort(B); Sort if B is not sorted.
[~,col] = ismember(B,A);
indx = find(diff(col)==0);
col(indx+1) = col(indx)+1;
A(col) = [];
C = A;
>>C
6 4 3 3 1 5
I'm not a fan of loops, but for random perturbations of A this was the best I came up with.
C = A;
for x = 1:numel(B)
C(find(C == B(x), 1, 'first')) = [];
end
I was curious about looking at the affect of different orders of A on a solution approach so I setup a test like this:
Ctruth = [1 3 3 4 5 5 6];
for testNumber = 1:100
Atest = A(randperm(numel(A)));
C = myFunction(Atest,B);
C = sort(C);
assert(all(C==Ctruth));
end
Strongly inspired by Matt, but on my machine 40% faster:
function A = multiDiff(A,B)
for j = 1:numel(B)
for i = 1:numel(A)
if A(i) == B(j)
A(i) = [];
break;
end
end
end
end

How Can I Creat Method do This Job?

I want create method that return an array which contains exactly the same numbers as the given array, but rearranged so that every 3 is immediately followed by a 4.
Do not move the 3's, but every other number may move. The array contains the same number of 3's and 4's, every 3 has a number after it that is not a 3 or 4, and a 3 appears in the array before any 4.
Example:
problem({1, 3, 1, 4, 4, 3, 1}) → {1, 3, 4, 1, 1, 3, 4}
problem({3, 2, 2, 4}) → {3, 4, 2, 2}
thanks .
Set i = 0, j = 0. Then you repeat the following:
Find the first 3 at an index ≥ i which is not followed by a 4. If none are found, you succeeded. If the 3 is the last number in the array or followed by a 3, you failed. Now find the first 4 at an index ≥ j which is not preceded by a 3. If none are found, you fail. Otherwise set i = location of the 3, j = location of the 4, exchange the objects at positions i+1 and j, set i = i + 2 and j = j + 1, and repeat.
I don't like writing code that depends on promises about the data that I don't verify myself, so this will work whatever is in the array.

Resources