Check if two arrays are cyclic permutations - algorithm

Given two arrays, how do you check if one is a cyclic permutation of the other?
For example, given a = [1, 2, 3, 1, 5], b = [3, 1, 5, 1, 2], and c = [2, 1, 3, 1, 5] we have that a and b are cyclic permutations but c is not a cyclic permutation of either.
Note: the arrays may have duplicate elements.

The standard trick here is to concatenate one of the arrays with itself, and then try to find the 2nd array in the concatenated array.
For example, 'a' concatenated with itself is:
[1, 2, 3, 1, 5, 1, 2, 3, 1, 5]
Since you do see 'b' in this array starting from the 3rd element then a and b are cyclic permutations.

If A and B are cyclic permutations of each other, A will be found in doubled list BB (as will B in AA).

The efficient way to handle large amounts of data, is to transform each of them into a 'canonical' form then compare to see of they're equal. For this problem you can choose as the canonical form of all the rotated permutations the one that 'sorts smallest'.
So the canonical form for 'a' and 'b' is [1, 2, 3, 1, 5] which are equal so they are acyclic permutations.
The canonical form for 'c' is [1, 3, 1, 5, 2] which is different.

Here is simple adhoc approach to findout cyclic permutations with O(n) time complexity.
a = [1, 2, 3, 1, 5], b = [3, 1, 5, 1, 2]
Find index of b[0] in a[], lets say index is 'x'.Then start
navigating in both the array's. a[] starts from index 'x' and b[]
starts from '0'. Such that both of them must have same values. If
not, they are not cyclic.
Here is the sample code.
public class CyclicPermutation {
static char[] arr = { 'A', 'B', 'C', 'D' };
static char[] brr = { 'C', 'D', 'K', 'B' };
boolean dec = false;
public static void main(String[] args) {
boolean avail = true;
int val = getFirstElementIndex(brr[0]);
if(val ==Integer.MIN_VALUE){
avail = false;
return;
}
for (int i = val, j = 0; j <= brr.length-1; ) {
if (i > arr.length-1) {
i = 0;
}
if (arr[i] == brr[j]) {
i++;
j++;
} else {
avail = false;
System.out.println(avail);
return;
}
}
System.out.println(avail);
}
public static int getFirstElementIndex(char c) {
for (int i = 0; i <= arr.length; i++) {
if (arr[i] == c) {
return i;
}
}
return Integer.MIN_VALUE;
}
}

Related

How to generate row-wise permutations of a 2d Array?

I recently got this question (paraphrased below) in a practice interview test and it still stumps me:
Given a 2d array A, generate a list of row-wise 1d array permutations from it.
A = [
[1],
[5, 2],
[6]
]
Answer: [[1, 5, 2, 6], [1, 6, 5, 2], [5, 2, 1, 6], [5, 2, 6, 1], [6, 1, 5, 2], [6, 5, 2, 1]]
Explanation of answer: We are permuting on the rows, so it's like generating permutations for [a,b,c] where each of these elements is a 1d array of potentially varying length.
I'm sure the solution involves backtracking, but anytime I try to implement it I end up with a 5+ parameters. I was hoping one of you folks could kindly provide an elegant solution, pseudocode, or explanation.
You're really just permuting the row order, and then flattening the matrix for each permutation. Python example:
from itertools import chain, permutations
def flatten(matrix):
return list(chain(*matrix))
def permute(matrix):
return [flatten(perm) for perm in permutations(matrix)]
With your example:
>>> M = [[1], [5, 2], [6]]
>>> permute(M)
[[1, 5, 2, 6], [1, 6, 5, 2], [5, 2, 1, 6], [5, 2, 6, 1], [6, 1, 5, 2], [6, 5, 2, 1]]
In another language, you may have to implement your own helper functions to iterate through permutations (possibly using recursion), and list flattening.
In Java you can do it like the following(first get a permutation of all the indexes and then use that to generate the ans):
public class RowWisePermutation {
public static void main(String[] args) {
int[][] A = {
{1},
{5, 2},
{6}
};
generateRowWisePermutation(A);
}
public static List<List<Integer>> generateRowWisePermutation(int[][] matrix) {
List<Integer> temp = new ArrayList<>();
List<List<Integer>> ans = new ArrayList<>();
List<List<Integer>> indexPermutation = new ArrayList<>();
int[] indexArr = new int[matrix.length];
for(int i = 0; i < matrix.length; i++) {
indexArr[i] = i;
}
backtrack(indexArr, temp, indexPermutation);
System.out.println(indexPermutation);
for(int i = 0; i < indexPermutation.size(); i++) {
List<Integer> row = new ArrayList<>();
List<Integer> indices = indexPermutation.get(i);
for(Integer index : indices) {
for(int j = 0; j < matrix[index].length; j++) {
row.add(matrix[index][j]);
}
}
ans.add(row);
}
System.out.println(ans);
return ans;
}
private static void backtrack(int[] arr, List<Integer> temp,
List<List<Integer>> indexPermutation) {
if(temp.size() == arr.length) {
indexPermutation.add(new ArrayList<>(temp));
return;
}
for(int i = 0; i < arr.length; i++) {
if(temp.contains(i)) { continue; }
temp.add(arr[i]);
backtrack(arr, temp, indexPermutation);
temp.remove(temp.size() - 1);
}
}
}

Find all ways to partition a set into given-sized subsets

It isn't really complicated, but I just can't figure out how to do it.
I have one set with objects, let's say they are numbers. I need to check all the possibilities of N groups (we can assume there are 3 groups, 9 objects in set), where order inside group doesn't matter ({1,2,3}, {2,1,3}, {3,2,1}, etc. are the same) and order of groups doesn't matter ([{1,2,3},{4,5,6}] is the same as [{5,4,6},{2,1,3}]).
I'm writing code in C#, but there really isn't anything I could show. The closest idea I had contained a lot of fors and ifs 😞
The solution I've used places the elements in order; this avoids any problems of duplication. It uses recursion and backtracking to find all solutions.
The critical restriction to keep from duplicating a solution is that you may not place an element into the nth partition unless all lower-numbered partitions are non-empty.
Consider your problem, 9 students in 3 partitions. We start with three empty sets
{} {} {}
We now need to place students [1, 2, 3, 4, 5, 6, 7, 8, 9] into this partition set. Call our function
place({ {}, {}, {} }, [1, 2, 3, 4, 5, 6, 7, 8, 9])
We place the students in order. Student 1 has only one place to go: the first partition. Otherwise, we would violate the restriction.
place({ {1}, {}, {} }, [2, 3, 4, 5, 6, 7, 8, 9])
Student 2 can go into either of the first two partitions (i.e. you'll need an iteration loop to cover the legal possibilities). From here, you'll cycle through two recursive calls:
place({ {1, 2}, {}, {} }, [3, 4, 5, 6, 7, 8, 9])
place({ {1}, {2}, {} }, [3, 4, 5, 6, 7, 8, 9])
In the first call, 3 cannot yet go into the 3rd partition; in the second call, it can go anywhere.
Do you see how this works? As the partitions fill up (I infer a limit of 3 students in each group), you'll need to check for a full group, as well. At the end, each time you place the final student, you have a valid, unique arrangement.
Coding is left as an exercise for the reader. :-)
Well I wrote this yesterday. It takes a lot of time to generate all solutions, but it works. I suppose I can make it faster if I use some tree to store elements (now every new group is compared with all existing groups).
Edit: Actualy now when I think about it, I'm not sure if there are possible duplicats. I wrote that when I had for loop through all elements. Maybe I can remove that "if" to make it faster. I'll check that when I'll have access to my laptop.
There were no dups. Now it's fast and result seems to be okay.
public class Group<T> : IComparable<Group<int>>
{
public Group(IEnumerable<T> elements)
{
Elements = elements.OrderBy(n => n).ToArray();
}
public T[] Elements { get; }
public bool Equals(Group<T> other)
{
if (object.ReferenceEquals(this, other))
return true;
//assume number of elements in groups are equal
for (int i = 0; i < Elements.Length; i++)
if (!Elements[i].Equals(other.Elements[i]))
return false;
return true;
}
public int CompareTo(Group<int> other)
{
int[] elements = Elements as int[];
for (int i = 0; i < Elements.Length; i++)
{
if (elements[i] < other.Elements[i])
return -1;
else if (elements[i] > other.Elements[i])
return 1;
}
return 0;
}
public override string ToString()
{
string result = "{";
for (int i = 0; i < Elements.Length; i++)
result += Elements[i] + (i == Elements.Length - 1 ? "" : ", ");
result += "}";
return result;
}
}
class Program
{
static void Main(string[] args)
{
int[] allElements = {1, 2, 3, 4, 5, 6, 7, 8, 9};
List<Group<int>> singleGroupCombinations = new List<Group<int>>();
for (int i = 0; i < allElements.Length; i++)
{
for (int j = i + 1; j < allElements.Length; j++)
{
for (int k = j + 1; k < allElements.Length; k++)
{
Group<int> newGroup = new Group<int>(new[]
{
allElements[i], allElements[j], allElements[k]
});
singleGroupCombinations.Add(newGroup);
}
}
}
List<Group<Group<int>>> groupsCombinations = new List<Group<Group<int>>>();
for (int i = 0; i < singleGroupCombinations.Count; i++)
{
for (int j = i+1; j < singleGroupCombinations.Count; j++)
{
for (int k = j+1; k < singleGroupCombinations.Count; k++)
{
Group<Group<int>> newGroup = new Group<Group<int>>(new[]
{
singleGroupCombinations[i], singleGroupCombinations[j], singleGroupCombinations[k]
});
groupsCombinations.Add(newGroup);
}
}
}
//all groups combinations in groupCombinations variable
}
}

Sort a List in Dart based on how another List was sorted

I am trying to sort a list with reference to another list. Consider this example,
List<String> a = ["a", "b", "c"];
List<int> b = [2, 3, 1];
Now, I want the result to be like this,
a = ["c", "a", "b"];
b = [1, 2, 3];
How can I achieve this result?
You can achieve this by create a Map that holds the mappings for the letters to your numbers, i.e. 2 has a assigned to it, 3 has b etc.
Now you can sort your list normally and after that recreate your other list based on the mappings that you stored before sorting:
main() {
List<String> letters = ["a", "b", "c"];
final List<int> numbers = [2, 3, 1];
final Map<int, String> mappings = {
for (int i = 0; i < numbers.length; i++)
numbers[i]: letters[i]
};
numbers.sort();
letters = [
for (int number in numbers) mappings[number]
];
print(letters); // [c, a, b]
print(numbers); // [1, 2, 3]
}
I used collection for for this example. This syntax for collection literals was introduced in Dart 2.3.
Learn more.
You can easily turn this about and map the numbers to your letters instead. That would look like this:
main() {
final List<String> letters = ["a", "b", "c"];
List<int> numbers = [2, 3, 1];
final Map<String, int> mapping = {
for (int i = 0; i < letters.length; i++)
letters[i]: numbers[i]
};
letters.sort((a, b) => b.compareTo(a));
numbers = [
for (String letter in letters) mapping[letter]
];
print(letters); // [c, b, a]
print(numbers); // [1, 3, 2]
}
Note that I sorted the letters in a descending order here by turning about the compareTo as well (by default a.compareTo(b) is used by List.sort).
If your Lists have duplicate elements, you won't be able to use a Map. I'd instead use package:tuple and then use the same approach of combining the two Lists into a single List<Tuple2>, sorting that, and extracting the values:
import 'package:tuple/tuple.dart';
void main() {
var a = ["a", "b", "c", "d"];
var b = [2, 3, 1, 1];
var combined = <Tuple2<int, String>>[
for (var i = 0; i < b.length; i += 1) Tuple2(b[i], a[i]),
];
combined.sort((tuple1, tuple2) => tuple1.item1.compareTo(tuple2.item1));
for (var i = 0; i < combined.length; i += 1) {
a[i] = combined[i].item2;
b[i] = combined[i].item1;
}
print(a); // Prints: [c, d, a, b]
print(b); // Prints: [1, 1, 2, 3]
}
I use this way to solve the problem:
List<String> strings = ["a", "b", "c", "c"];
List<int> numbers = [2, 3, 1, 0];
List<int> storeNumbers = List.from(numbers);
List<int> storeIndex = [];
//sorting numbers list
numbers.sort((a, b) => a.compareTo(b));
//get the index of numbers list elements before the sorting
for (int i = 0; i < numbers.length; i++) {
for (int j = 0; j < storeNumbers.length; j++) {
if (numbers[i] == storeNumbers[j]) {
storeIndex.add(j);
}
}
}
//generate a new string list based on the indexes we get
strings =
List.generate(strings.length, (index) => strings[storeIndex[index]]);
print(strings);//output:[c, c, a, b]
print(numbers);//output:[0, 1, 2, 3]

Count number of subsets whose sum is greater than or equal to k

Given an array with n elements , one need to count number of subsets whose sum is greater than or equal to k.
Eg arr[] = {1,5,9,2,3}, k =16
1+5+9+2=17
1+5+9+3=18
1+5+9+2+3=20
5+9+2=16
5+9+3=17
5+9+2+3=19
Answer is 6.
One approach what i know is to use dynamic programming using bit masking and check if sum>=k and increment the count.
Problem with this approach is N should be very small since bit masking involves exponential running time.
Is there any other efficient algorithm for the above problem.
Thanks in advance.
Make array Counts[Sum+1] where Sum is sum of all elements
Set Counts[0] = 1, other elements - zero
For ever x=arr[i] scan Counts array from the end and increment those entries, that could be composed from existing so far sums and x
if Counts[j - arr[i]] > 0 then //this check might be omitted
Counts[j] = Counts[j - arr[i]] + Counts[j]
Then sum non-zero Counts entries for j>=k
Complexity is O(Sum * N)
If range of possible sums is large but number of possible sums is not so high (like arr=[1, 2, 3, 100000000, 100000001] array), you can exploit memoization approach and store only really existing variants in the map
Example:
arr=[1,2,3,5]
Counts = [1,0,0,0,0,0,0,0,0,0,0,0]
after arr[0]=1
Counts = [1,1,0,0,0,0,0,0,0,0,0,0]
after arr[1]=2
Counts = [1,1,1,1,0,0,0,0,0,0,0,0]
after arr[2]=3
Counts = [1,1,1,2,1,1,1,0,0,0,0,0]
after arr[3]=5
Counts = [1,1,1,2,1,2,2,1,2,1,1,1]
Counts[8] could be composed from 5 and existing Counts[3] with two variants
1+2+5; 3+5
One approach would be to use recursion to create the subsets and stop the recursion when the sum of the elements omitted from the original set is greater than total-k, where total is the sum of all elements of the array.
Here's some Java code that illustrates the approach:
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
public class SubSet
{
public static void main(String[] args)
{
Integer[] set = { 1, 5, 9, 2, 3 };
List<List<Integer>> subsets = subsetsK(set, 16);
for (List<Integer> subset : subsets)
{
System.out.println(subset);
}
}
static List<List<Integer>> subsetsK(Integer[] arr, int k)
{
int t = 0;
for (int n : arr) t += n;
List<List<Integer>> subsets = new ArrayList<>();
allSubsets(subsets, arr, new BitSet(arr.length), 0, 0, t - k);
return subsets;
}
public static void allSubsets(List<List<Integer>> subsets, Integer[] arr, BitSet off, int pos, int sum, int lim)
{
if(sum > lim) return;
if(pos == arr.length)
{
subsets.add(toSubset(arr, off));
return;
}
off.set(pos);
allSubsets(subsets, arr, off, pos + 1, sum + arr[pos], lim);
off.clear(pos);
allSubsets(subsets, arr, off, pos + 1, sum, lim);
}
static List<Integer> toSubset(Integer[] arr, BitSet off)
{
List<Integer> ss = new ArrayList<>();
for (int i = 0; i < arr.length; i++)
{
if (!off.get(i))
ss.add(arr[i]);
}
return ss;
}
}
Output:
[5, 9, 3]
[5, 9, 2]
[5, 9, 2, 3]
[1, 5, 9, 3]
[1, 5, 9, 2]
[1, 5, 9, 2, 3]
You can run/edit the code here: Ideone

Looking for non-recursive algorithm for visiting all k-combinations of a multiset in lexicographic order

More specifically, I'm looking for an algorithm A that takes as its inputs
a sorted multiset M = {a1, a2, …, an } of non-negative integers;
an integer 0 &leq; k &leq; n = |M |;
a "visitor" callback V (taking a k-combination of M as input);
(optional) a sorted k-combination K of M (DEFAULT: the k-combination {a1, a2, …, ak }).
The algorithm will then visit, in lexicographic order, all the k-combinations of M, starting with K, and apply the callback V to each.
For example, if M = {0, 0, 1, 2}, k = 2, and K = {0, 1}, then executing A(M, k, V, K ) will result in the application of the visitor callback V to each of the k-combinations {0, 1}, {0, 2}, {1, 2}, in this order.
A critical requirement is that the algorithm be non-recursive.
Less critical is the precise ordering in which the k-combinations are visited, so long as the ordering is consistent. For example, colexicographic order would be fine as well. The reason for this requirement is to be able to visit all k-combinations by running the algorithm in batches.
In case there are any ambiguities in my terminology, in the remainder of this post I give some definitions that I hope will clarify matters.
A multiset is like a set, except that repetitions are allowed. For example, M = {0, 0, 1, 2} is a multiset of size 4. For this question I'm interested only in finite multisets. Also, for this question I assume that the elements of the multiset are all non-negative integers.
Define a k-combination of a multiset M as any sub-multiset of M of size k. E.g. the 2-combinations of M = {0, 0, 1, 2} are {0, 0}, {0, 1}, {0, 2}, and {1, 2}.
As with sets, the ordering of a multiset's elements does not matter. (e.g. M can also be represented as {2, 0, 1, 0}, or {1, 2, 0, 0}, etc.) but we can define a canonical representation of the multiset as the one in which the elements (here assumed to be non-negative integers) are in ascending order. In this case, any collection of k-combinations of a multiset can itself be ordered lexicographically by the canonical representations of its members. (The sequence of all 2-combinations of M given earlier exhibits such an ordering.)
UPDATE: below I've translated rici's elegant algorithm from C++ to JavaScript as faithfully as I could, and put a simple wrapper around it to conform to the question's specs and notation.
function A(M, k, V, K) {
if (K === undefined) K = M.slice(0, k);
var less_than = function (a, b) { return a < b; };
function next_comb(first, last,
/* first_value */ _, last_value,
comp) {
if (comp === undefined) comp = less_than;
// 1. Find the rightmost value which could be advanced, if any
var p = last;
while (p != first && ! comp(K[p - 1], M[--last_value])) --p;
if (p == first) return false;
// 2. Find the smallest value which is greater than the selected value
for (--p; comp(K[p], M[last_value - 1]); --last_value) ;
// 3. Overwrite the suffix of the subset with the lexicographically
// smallest sequence starting with the new value
while (p !== last) K[p++] = M[last_value++];
return true;
}
while (true) {
V(K);
if (!next_comb(0, k, 0, M.length)) break;
}
}
Demo:
function print_it (K) { console.log(K); }
A([0, 0, 0, 0, 1, 1, 1, 2, 2, 3], 8, print_it);
// [0, 0, 0, 0, 1, 1, 1, 2]
// [0, 0, 0, 0, 1, 1, 1, 3]
// [0, 0, 0, 0, 1, 1, 2, 2]
// [0, 0, 0, 0, 1, 1, 2, 3]
// [0, 0, 0, 0, 1, 2, 2, 3]
// [0, 0, 0, 1, 1, 1, 2, 2]
// [0, 0, 0, 1, 1, 1, 2, 3]
// [0, 0, 0, 1, 1, 2, 2, 3]
// [0, 0, 1, 1, 1, 2, 2, 3]
A([0, 0, 0, 0, 1, 1, 1, 2, 2, 3], 8, print_it, [0, 0, 0, 0, 1, 2, 2, 3]);
// [0, 0, 0, 0, 1, 2, 2, 3]
// [0, 0, 0, 1, 1, 1, 2, 2]
// [0, 0, 0, 1, 1, 1, 2, 3]
// [0, 0, 0, 1, 1, 2, 2, 3]
// [0, 0, 1, 1, 1, 2, 2, 3]
This, of course, is not production-ready code. In particular, I've omitted all error-checking for the sake of readability. Furthermore, an implementation for production will probably structure things differently. (E.g. the option to specify the comparator used by next_combination's becomes superfluous here.) My main aim was to keep the ideas behind the original algorithm as clear as possible in a piece of functioning code.
I checked the relevant sections of TAoCP, but this problem is at most an exercise there. The basic idea is the same as Algorithm L: try to "increment" the least significant positions first, filling the positions after the successful increment to have their least allowed values.
Here's some Python that might work but is crying out for better data structures.
def increment(M, K):
M = list(M) # copy them
K = list(K)
for x in K: # compute the difference
M.remove(x)
for i in range(len(K) - 1, -1, -1):
candidates = [x for x in M if x > K[i]]
if len(candidates) < len(K) - i:
M.append(K[i])
continue
candidates.sort()
K[i:] = candidates[:len(K) - i]
return K
return None
def demo():
M = [0, 0, 1, 1, 2, 2, 3, 3]
K = [0, 0, 1]
while K is not None:
print(K)
K = increment(M, K)
In iterative programming, to make combinations of K size you would need K for loops. First we remove the repetitions from the sorted input, then we create an array that represents the for..loop indices. While the indices array doesn't overflow we keep generating combinations.
The adder function simulates the pregression of counters in a stacked for loop. There is a little bit of room for improvement in the below implementation.
N = size of the distinct input
K = pick size
i = 0 To K - 1
for(var v_{i0} = i_{0}; v_{i} < N - (K - (i + 1)); v_{i}++) {
...
for(var v_{iK-1} = i_{K-1}; v_{iK-1} < N - (K - (i + 1)); v_{iK-1}++) {
combo = [ array[v_{i0}] ... array[v_{iK-1}] ];
}
...
}
Here's the working source code in JavaScript
function adder(arr, max) {
var k = arr.length;
var n = max;
var carry = false;
var i;
do {
for(i = k - 1; i >= 0; i--) {
arr[i]++;
if(arr[i] < n - (k - (i + 1))) {
break;
}
carry = true;
}
if(carry === true && i < 0) {
return false; // overflow;
}
if(carry === false) {
return true;
}
carry = false;
for(i = i + 1; i < k; i++) {
arr[i] = arr[i - 1] + 1;
if(arr[i] >= n - (k - (i + 1))) {
carry = true;
}
}
} while(carry === true);
return true;
}
function nchoosekUniq(arr, k, cb) {
// make the array a distinct set
var set = new Set();
for(var i=0; i < arr.length; i++) { set.add(arr[i]); }
arr = [];
set.forEach(function(v) { arr.push(v); });
//
var n = arr.length;
// create index array
var iArr = Array(k);
for(var i=0; i < k; i++) { iArr[i] = i; }
// find unique combinations;
do {
var combo = [];
for(var i=0; i < iArr.length; i++) {
combo.push(arr[iArr[i]]);
}
cb(combo);
} while(adder(iArr, n) === true);
}
var arr = [0, 0, 1, 2];
var k = 2;
nchoosekUniq(arr, k, function(set) {
var s="";
set.forEach(function(v) { s+=v; });
console.log(s);
}); // 01, 02, 12

Resources