Recovering an array [duplicate] - algorithm

This question already has answers here:
Recover original array from all subsets
(3 answers)
Closed 3 years ago.
I recently came acrosss this question in an hiring challenge :
Given array S of 2^N integers(1 <= N <= 20, 0 <= Si <= 10^9) representing subset sums of an array A, we need to recover array A in sorted order.
e.g. S = {2, 1, 0, 3} => A = {1, 2} as subset sums of A are {0, 1, 2, 1+2}
The order of number in array S may be random.
How can I approach this problem ? Thanks in advance.

You can sort the array containing the subset sums
When u sort the subset sum array
Ai = S[2^i] -- should give you the values of array A in sorted order.
You can make a truth table to get subset sum and trace back
Assuming S is a valid input
eg: S = { 0, 5, 3, 8, 1, 6, 4, 9 }
Sorted S = {0, 1, 3, 4, 5, 6, 8, 9}
A = [A0, A1, A2] ---
A0,A1,A2 -- (Binary, part of subset = 1 not part = 0 )
Index | A0,A1,A2 | Sorted Sum
0 0 0 0 0
1 1 0 0 1
2 0 1 0 3
3 1 1 0 4
4 0 0 1 5
5 1 0 1 6
6 0 1 1 8
7 1 1 1 9
From her we can reverse and find that A0 = S[2^0], A1 = S[2^1], A2 = S[2^2]

Related

Print sequences with prime sum

Given an integer n, I want to find two permutations of the numbers 1 to n (inclusive) such that the sum of numbers from the two permutations at any given index is always prime.
For example:
n = 5
1 2 3 4 5
1 5 4 3 2
n = 8
1 2 3 4 5 6 7 8
2 1 4 3 8 7 6 5
Construct a bipartite graph on {0,1} x {1...n} such that (0, i) and (1, j) are connected if and only if i+j is prime.
Find a perfect matching using any standard technique, and then produce the sequences so that the matching numbers are at the same index.
Find the smallest number k>=1 such that n+k is prime.
Form pairs: (n,k), (n-1, k+1), ..., (k,n).
If k>1, repeat on the range [1,k].
E.g., n=5: 5+2=7, so we have:
5, 4, 3, 2
2, 3, 4, 5
Then we repeat for 1.
E.g. n=8: 8+3 = 11, so we have:
8, 7, 6, 5, 4, 3
3, 4, 5, 6, 7, 8
Leaving us with 2:
1, 2
2, 1
By Bertrand's postulate aka Chebyshev's theorem, for any n>1 there is a prime p s.t. n < p < 2n, and for n=1 we have 1+1=2, so we will always be able to do this.

How to compute all unique permutations and keep the same positive adjacent elements always adjacent?

I have a list or a vector V of n nonnegative integers. There are some positive integers that are equal and adjacent, say V=[2, 3, 3, 0, 0]. (I do not care about the zero integer.)
I would like to find all unique permutations of V such that all the same and positive integers remain adjacent. How to write an algorithm for this? (For an implementation, you can choose Python or Matlab or any other language.)
Under Matlab and for the example of V=[2, 3, 3, 0, 0], I get all the unique permuations as follows:
V = [2, 3, 3, 0, 0];
unique(perms([2, 3, 3, 0, 0]), 'rows')
and I get:
0 0 2 3 3
0 0 3 2 3
0 0 3 3 2
0 2 0 3 3
0 2 3 0 3
0 2 3 3 0
0 3 0 2 3
0 3 0 3 2
0 3 2 0 3
0 3 2 3 0
0 3 3 0 2
0 3 3 2 0
2 0 0 3 3
2 0 3 0 3
2 0 3 3 0
2 3 0 0 3
2 3 0 3 0
2 3 3 0 0
3 0 0 2 3
3 0 0 3 2
3 0 2 0 3
3 0 2 3 0
3 0 3 0 2
3 0 3 2 0
3 2 0 0 3
3 2 0 3 0
3 2 3 0 0
3 3 0 0 2
3 3 0 2 0
3 3 2 0 0
As you may know, I get 30 such permutations. Among these 30, there are 18 that do not respect the constraint of adjacency. For example, [3, 2, 3, 0, 0] can not be in the final result because 3 is no longer adjacent to 3. Finally, all unique permutations can be given by:
0 0 2 3 3
0 0 3 3 2
0 2 0 3 3
0 2 3 3 0
0 3 3 0 2
0 3 3 2 0
2 0 0 3 3
2 0 3 3 0
2 3 3 0 0
3 3 0 0 2
3 3 0 2 0
3 3 2 0 0
The first idea (and the simplest) that came to my mind is to generate all unique permutations like so and then, for each one, verify the constraint. But is there any other efficient algorithm?
We can first compress the given array so that there is just one entry for every positive number, while keeping a count of how many times each number occurred (the zeroes should be left as is).
Generate the permutations of the compressed array.
Decompress each of the permutation and retain only the unique ones.
To Compress
def compress(arr):
counts = {}
compressed = []
curr_ele = arr[0]
count_ele = 0
for ele in arr:
if ele != curr_ele or ele == 0:
counts[curr_ele] = count_ele
compressed.append(curr_ele)
count_ele = 1
curr_ele = ele
else:
count_ele += 1
counts[curr_ele] = count_ele
compressed.append(curr_ele)
return compressed, counts
To Uncompress
def uncompress(arr, counts):
res = []
for ele in arr:
if ele == 0:
res.append(0)
continue
num_reps = counts[ele]
for _ in range(num_reps):
res.append(ele)
return res
Putting it together: Compress, Permute, Uncompress and Retain Unique
import itertools
ip = [2, 3, 3, 0, 0]
ip_compressed, counts = compress(ip)
set([tuple(uncompress(perm, counts)) for perm in itertools.permutations(ip_compressed)])
Result:
{(0, 0, 2, 3, 3),
(0, 0, 3, 3, 2),
(0, 2, 0, 3, 3),
(0, 2, 3, 3, 0),
(0, 3, 3, 0, 2),
(0, 3, 3, 2, 0),
(2, 0, 0, 3, 3),
(2, 0, 3, 3, 0),
(2, 3, 3, 0, 0),
(3, 3, 0, 0, 2),
(3, 3, 0, 2, 0),
(3, 3, 2, 0, 0)}
A simple algorithm is:
1.traverse the initial table and make another table with two rows like:
input: V = [2, 3, 3, 0, 0];
new array: V2 = |2,3,0|
|1,2,2|
As you can see V2 comes from V keeping one time the elements and in second row counting how many times we have seen them.
Now generate all permutations of columns
And for every result e.g:
V2 = |3,2,0|
|2,1,2|
you have kept how many times the elements appear.

Find the number of 5 digit numbers using 1, 2, 3, 4, 5 - in which first k digits are not only o to k

The question is to find the number of 5 digits numbers possible using 1, 2, 3, 4, and 5 as digits, in which the set of first k numbers (k is natural number, and k < 5) is not equal to set of numbers from 1 to k.
Clarification - Order of elements of set does not matter. {1, 2} is same as {2, 1} ie {1, 2} = {2, 1}.
For example, in 54213 is a correct number and it will be counted - as
k = 1, we get {5}, and {5} != {1}
k = 2, {5, 4} != {1, 2}
k = 3, {5, 4, 2} != {1, 2, 3}
k = 4, {5, 4, 2, 1} != {1, 2, 3, 4}
Also, the number 13245 is not valid, as for k = 1, {1} = {1}.
Bonus question, find the number of 6 digit possible numbers with same criteria and digits 1, 2, 3, 4, 5, & 6.
Edit - I am sorry for not having followed this up with my method. I have added my solution below.
Number of 5 digit numbers possible with the given digits = 5! = 120
Let's consider the digits that are NOT to be formed.
1 _ _ _ _ = 4! = 24 (As clearly, k = 1 {1} = {1})
2 1 _ _ _ = 3! = 6 (As clearly, k = 2 {2, 1} = {1, 2}, also we will not consider 1 2 _ _ _ as it has already been included in 1)
2 3 1 _ _ = 2! = 2
3 1 2 _ _ = 2! = 2
3 2 1 _ _ = 2! = 2
2 3 4 1 _ = 1
2 4 1 3 _ = 1
2 4 3 1 _ = 1
3 1 4 2 _ = 1
3 2 4 1 _ = 1
3 4 2 1 _ = 1
3 4 1 2 _ = 1
4 - - - _ = 3! x 1 = 6 (Where dashes can be filled by 1, 2, 3)
Total number = 49
But there are the NOT cases. Now, the cases required = 120 - 49 = 71.
For 6, I used recursion, as clearly in case of 5, the series (for the numbers that are NOT to be formed) is
1 x 4! + 1 x 3! + 3 x 2! + 13 x 1! (where 1, 1, 3, and 13 is the solution for the given condition for 1 digit, 2, digit, 3 digit and 4 digit respectively)
{ie, for 1 digit number using only 1, where k < 1, k is natural, number of possible digits - 1 (1). For 2 digit number using only 1, 2, where k < 2, the number of possible digits - 1 (21). For 3, it is 321, 231, 312 and so on)
Hence, for 6, the series becomes
1 x 5! + 1 x 4! + 3 x 3! + 13 x 2! + 71 (where 71 is the solution for given condition of 5 digits)
= 259
ie. for 6, the solutions = 6! - 259 = 461

How to find the index of a k-permutation from n elements?

I know that, for a k-permutation p of size k, built from n elements, there are:
P(n, k) = n! / (n - k)!
possible k-permutations. For example:
k = 2
n = 4
l = [1, 2, 3, 4]
P(n, k) = 4! / (4 - 2)! = 12
1 2 | 2 1 | 3 1 | 4 1
1 3 | 2 3 | 3 2 | 4 2
1 4 | 2 4 | 3 4 | 4 3
And yet another example:
k = 3
n = 4
l = [1, 2, 3, 4]
P(n, k) = 4! / (4 - 3)! = 24
1 2 3 | 2 1 3 | 3 1 2 | 4 1 2
1 2 4 | 2 1 4 | 3 1 4 | 4 1 3
1 3 2 | 2 3 1 | 3 2 1 | 4 2 1
1 3 4 | 2 3 4 | 3 2 4 | 4 2 3
1 4 2 | 2 4 1 | 3 4 1 | 4 3 1
1 4 3 | 2 4 3 | 3 4 2 | 4 3 2
So, how do I find the index of the k-permutation p? Consider the permutations
to be generated lexicographically.
Edit:
I could start by finding in which "block" p is, addressing the block by the first element of p. For example, for p = [3, 2, 4], the index for p should be at least 12 (counting from 0 to P(n, k) - 1).
But then, to find the second element inside that "block", I'd have to see what are the remaining items to be found, and in which position they will be. I mean, I'd be eventually addressing the list [1, 4], and 4 would be at position 2, so simply using the element as key would require some extra manipulation.
I could use a hash to look up the elements and update their positions, but it'd give me a O(n^2) time complexity. Is it possible to do any better?
The number of permutations for a given digit in a given position is given by a formula
(n-digit position)! / (n-k)! where digit position starts on the left with 1.
To get the number of preceding permutations for a given permutation (that is, its index), multiply the formula for each digit by the number of preceding digits not already used, and add them up.
Example 1, k = 2, n = 4, p = [3,4]
First digit, 3:
(4-1)! / (4-2)! * (number of unused preceding digits, 2) = 6
There are six permutations preceding the first that has 3 in position 1.
Second digit, 4:
(4-2)! / (4-2)! * (number of unused preceding digits, 2) = 2
There are two permutations preceding the first that has 4 in position 2.
Zero based index: 6 + 2 = 8.
Example 2, k = 3, n = 4, p = [3,2,4]
First digit, 3:
(4-1)! / (4-3)! * (number of unused preceding digits, 2) = 12
There are 12 permutations preceding the first that has 3 in position 1.
Second digit, 2:
(4-2)! / (4-3)! * (number of unused preceding digits, 1) = 2
There are two permutations preceding the first that has 2 in position 2.
Third digit, 4:
(4-3)! / (4-3)! * (number of unused preceding digits, 1) = 1
There is one permutation preceding the first that has 4 in position 3.
Zero based index: 12 + 2 + 1 = 15.
TXR language:
$ txr -p "(pos '(1 4 3) (perm '(1 2 3 4) 3))"
5
It is brute force, however; of course pos knows nothing about the structure of permutations.
Use binary search tree (BST). Store all you numbers in it before you start and delete them after you use one. To find x-th element maintain .subtreeSize for every vertex and just descend the tree to find the number you need. Pseudocode:
def findXth(x):
curVertex = BST.root
while:
curPosition = curVertex.leftChild.subtreeSize
if curPosition == x: return curVertex.value
elif curPosition > x: curVertex = curVertex.leftChild
elif curPosition < x: curVertex = curVertex.rightChild
Don't forget to check for vertices existence and to delete the vertex you find.
Overall complexity is going to be O(n log n).
you can reference below function
/**
* list all k or <=k size permutation of a given list with n unique elements.
* n can be bigger than 64. this function will take O(K^N) time, Bad.
*
* #param uniqueList
* #param permutationSize
* #param permutation
* #param only Only show the permutation of permutationSize,
* else show all permutation of less than or equal to permutationSize.
*/
public static void my_permutationOf(List<Integer> uniqueList, int permutationSize, List<Integer> permutation, boolean only) {
if (permutation == null) {
assert 0 < permutationSize && permutationSize <= uniqueList.size();
permutation = new ArrayList<>(permutationSize);
if (!only) {
System.out.println(Arrays.toString(permutation.toArray()));
}
}
for (int i : uniqueList) {
if (permutation.contains(i)) {
continue;
}
permutation.add(i);
if (!only) {
System.out.println(Arrays.toString(permutation.toArray()));
} else if (permutation.size() == permutationSize) {
System.out.println(Arrays.toString(permutation.toArray()));
}
if (permutation.size() < permutationSize) {
my_permutationOf(uniqueList, permutationSize, permutation, only);
}
permutation.remove(permutation.size() - 1);
}
}
E.g. you can think the element is the index
public static void main(String[] args) throws Exception {
my_permutationOf(new ArrayList<Integer>() {
{
add(0);
add(1);
add(2);
add(3);
}
}, 3, null, true);
}
the result is
[0, 1, 2]
[0, 1, 3]
[0, 2, 1]
[0, 2, 3]
[0, 3, 1]
[0, 3, 2]
[1, 0, 2]
[1, 0, 3]
[1, 2, 0]
[1, 2, 3]
[1, 3, 0]
[1, 3, 2]
[2, 0, 1]
[2, 0, 3]
[2, 1, 0]
[2, 1, 3]
[2, 3, 0]
[2, 3, 1]
[3, 0, 1]
[3, 0, 2]
[3, 1, 0]
[3, 1, 2]
[3, 2, 0]
[3, 2, 1]

Balanced layout of n items in a grid

I have a list of n logos to display in a grid, with a maximum of 3 per row.
What's an algorithm to decide how many to display per row such that the number of logos per row is as balanced as possible without using more than the minimum possible number of rows?
For example:
n -> number in each row
1 -> 1
2 -> 2
3 -> 3
4 -> 2, 2
5 -> 3, 2
6 -> 3, 3
7 -> 3, 2, 2
8 -> 3, 3, 2
9 -> 3, 3, 3
10 -> 3, 3, 2, 2
For N <= 3 just use N.
If N is exactly divisible by 3 then use: 3 3 ... 3
If N when divided by 3 has remainder 1 then use: 3 3 ... 2 2
If N when divided by 3 has remainder 2 then use: 3 3 ... 3 2
AS confusing as your question is, I think what you need to do is first determine:
number_of_rows = ceil(number_of_logos / 3.0)
Then add a logo to each row, one at a time.
Python:
import math
def partition_logos(count, lsize):
num_lines = int(math.ceil(count / float(lsize)))
partition = [0] * num_lines
for i in xrange(count):
partition[i%num_lines] += 1
return partition
>>> for i in xrange(1,11):
... print partition_logos(i, 3)
[1]
[2]
[3]
[2, 2]
[3, 2]
[3, 3]
[3, 2, 2]
[3, 3, 2]
[3, 3, 3]
[3, 3, 2, 2]
A recursive solution, in Python:
def logos_by_row(N, rows):
width = 0
if N > 4 or N == 3:
width = 3
elif N == 4 or N == 2:
width = 2
elif N == 1:
width = 1
if width != 0:
rows.append(width)
logos_by_row(N - width, rows)
answer = []
for i in range(10):
logos_by_row(i+1, answer)
print answer
just use n/3 to calculate the row and n%3 to calculate the column
edit: ok i saw you edited your question.... i din't saw that you want to display 2 in each row if the are 4 logos. but then you can use n mod 3 to calculate if their is a reminder as others already suggested
if n%3 = 0 then just put 3 logos in each row
if n%3 = 1 then put the last 4 logos in two rows
if n%3 = 2 then put 3 logos in n row and the last 2 logos in a separate row

Resources