what is the algorithm for iterating over all possible variations of an array? [duplicate] - algorithm

This question already has answers here:
Generating permutations of an int array using java -- error
(9 answers)
Closed 3 days ago.
for example there is an array [1, 3, 5, 7], the algorithm should give all its variations. Array can be any size. I thought to implement this using recursive permutations, but nothing adequate came to my mind.
[1, 3, 7, 5], [1, 5, 3, 7], [1, 5, 7, 3], [1, 7, 3, 5], [1, 7, 5, 3] and so on

just loop over all values, just exclude ones already used, like this:
function* generatePermutations(a) {
function* recPermutations(a, r) {
for (const e of a) {
if (!r.includes(e)) {
r.push(e);
if (r.length == a.length)
yield r;
else
yield * recPermutations(a, r);
r.pop();
}
}
}
yield * recPermutations(a, []);
}
const it = generatePermutations([1,3,5,7]);
for (const i of it)
console.log(i.toString());

Related

What is the time complexity of a function that generates combinations of length r from n elements without repetitions or permutations?

The following function takes in a list of elements src as well as a combination length r. It prints out all possible combinations of length r, without repetition of an element inside a combination or repetition of a combination in a different order (permutation).
void fn(List<dynamic> src, int r, List<dynamic> tmp) {
for (var i = 0; i < src.length; i++) {
tmp.add(src.removeAt(i));
if (tmp.length == r) print(tmp.toString());
else if (i < src.length) fn(src.sublist(i), r, tmp);
src.insert(i, tmp.removeLast());
}
}
So, given n = [1,2,3,4,5] and r = 3, it would print out
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[1, 3, 4]
[1, 3, 5]
[1, 4, 5]
[2, 3, 4]
[2, 3, 5]
[2, 4, 5]
[3, 4, 5]
How would you describe the time complexity of this function in Big O notation? Clearly both the length of src as well as r have to be taken into account. If I am not mistaken, the time complexity of a similar function printing out all combinations with repetitions and permutations would be O(n^r). But what is it in this case?
According to Stef's comment, the time complexity seems to be O(r(n choose r)).

Find all combination size n from n groups

I am having a programming problem
Given n-groups of people.
From each group, pick a person to form a new set.
How to find all possible combinations to from a set.
For example: If I have 2 groups
Group 1: Person A, B
Group 2: Person X Y Z
possible sets will be (A,X) (A,Y) (A,Z) (B,X) (B,Y) (B,Z)
Thank you for any help and suggestion.
Bests.
You are looking for the "product" of the n groups. You can implement this recursively:
for each element in the first group
for each product of the remaining groups
combine the element with the product and add it to the result
Example-implementation in Python:
def product(lists, pos=0):
if pos < len(lists):
for x in lists[pos]:
for p in product(lists, pos+1):
yield [x] + p
else:
yield []
>>> list(product([[1,2,3], [4,5], [6,7,8]]))
[[1, 4, 6], [1, 4, 7], [1, 4, 8], [1, 5, 6], [1, 5, 7], [1, 5, 8],
[2, 4, 6], [2, 4, 7], [2, 4, 8], [2, 5, 6], [2, 5, 7], [2, 5, 8],
[3, 4, 6], [3, 4, 7], [3, 4, 8], [3, 5, 6], [3, 5, 7], [3, 5, 8]]
Because no language constraint is given in the question so I am sharing the code in java. Also the code calculates the cross product of two sets.
import java.util.*;
import java.lang.*;
import java.io.*;
class Combinations
{
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
System.out.println(prod(Arrays.asList(Arrays.asList("A", "B"), Arrays.asList("X", "Y", "Z"))));
}
static <String> List<List<String>> prod(List<List<String>> sets) {
List<List<String>> res = new ArrayList<List<String>>();
if (sets.size() == 0) {
res.add(new ArrayList<String>());
return res;
} else {
List<String> set1 = sets.get(0);
List<List<String>> adLst = prod(sets.subList(1, sets.size()));
for (String item : set1) {
for (List<String> lst : adLst) {
ArrayList<String> result = new ArrayList<String>();
result.add(item);
result.addAll(lst);
res.add(result);
}
}
}
return res;
}
}
Output
[[A, X], [A, Y], [A, Z], [B, X], [B, Y], [B, Z]]

Ruby code to merge two arrays not working

nums1 = Array[1, 2, 3, 4, 5]
nums2 = Array[5, 6, 7, 8, 9]
def mergeArrays (ar1, ar2)
result = (ar1 << ar2).flatten!
require 'pp'
pp %w(result)
end
As simple as this. I am trying to merge these two arrays and display the result. I am also brand-brand new to Ruby. This is the first function I am writing in this language. Trying to learn here. Also how can I remove the duplicates?
It would help if you give example inputs and outputs so we know exactly what you want. When you use the word "merge", I think you actually just want to add the arrays together:
ar1 = [1, 2, 3]
ar2 = [3, 4, 5]
ar3 = ar1 + ar2 # => [1, 2, 3, 3, 4, 5]
Now if you want to remove duplicates, use Array#uniq:
ar4 = ar3.uniq # => [1, 2, 3, 4, 5]
There is no need to write a method to do any of this since the Ruby Array class already supports it. You should skim through the documentation of the Array class to learn more things you can do with arrays.
What do you mean 'not working'?
Similar questions have been asked here:
Array Merge (Union)
You have two options: the pipe operator (a1 | a2) or concatenate-and-uniq ((a1 + a2).uniq).
Also be careful about using <<, this will modify the original variable, concatenating ar2 onto the end of the original ar1.
nums1 = Array[1, 2, 3, 4, 5]
nums2 = Array[5, 6, 7, 8, 9]
result = (nums1<< nums2).flatten!
nums1
=> [1, 2, 3, 4, 5, 5, 6, 7, 8, 9]
nums2
=> [5, 6, 7, 8, 9]
result
=> [1, 2, 3, 4, 5, 5, 6, 7, 8, 9]
Additionally- just another Ruby tip, you do not need the destructive flatten! with ! versus the regular flatten. The regular flatten method will return a new Array, which you assign to result in your case. flatten! will flatten self in place, altering whatever Array it's called upon, rather than returning a new array.
You can merge Arrays using '+' operator and you can ignore the duplicated values using .uniq
>> nums1 = Array[1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]
>> nums2 = Array[5, 6, 7, 8, 9]
=> [5, 6, 7, 8, 9]
>> def mergeArrays (nums1, nums2)
>> result = (nums1 + nums2).uniq
>> end
=> :mergeArrays
>> mergeArrays(nums1,nums2)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
nums1 = Array[1, 2, 3, 4, 5]
nums2 = Array[5, 6, 7, 8, 9]
p nums1.concat(nums2).uniq

What is [....] in Ruby? [duplicate]

This question already has answers here:
Methods in Ruby: objects or not?
(6 answers)
What are recursive arrays good for?
(2 answers)
Closed 10 years ago.
I ended up accidentally doing the equivalent of this in Ruby the other night:
a = *1..5 # => [1, 2, 3, 4, 5]
a << a
a # => [1, 2, 3, 4, 5, [...]]
a.last # => [1, 2, 3, 4, 5, [...]]
What is [...] and what can I do with it?
It's just the way Array.inspect displays recursive arrays. The last Element of a is a itself. If a where displayed after 5, inspect would end up in an endless loop:
[1, 2, 3, 4, 5, [1, 2, 3, 4, 5, [1, 2, 3, 4, 5, [1, 2, 3, 4, 5, [...]]]]]

How to sort an array using minimum number of writes?

My friend was asked a question in his interview:
The interviewer gave him an array of unsorted numbers and asked him to sort. The restriction is that the number of writes should be minimized while there is no limitation on the number of reads.
Selection sort is not the right algorithm here. Selection sort will swap values, making up to two writes per selection, giving a maximum of 2n writes per sort.
An algorithm that's twice as good as selection sort is "cycle" sort, which does not swap. Cycle sort will give a maximum of n writes per sort. The number of writes is absolutely minimized. It will only write a number once to its final destination, and only then if it's not already there.
It is based on the idea that all permutations are products of cycles and you can simply cycle through each cycle and write each element to its proper place once.
import java.util.Random;
import java.util.Collections;
import java.util.Arrays;
public class CycleSort {
public static final <T extends Comparable<T>> int cycleSort(final T[] array) {
int writes = 0;
// Loop through the array to find cycles to rotate.
for (int cycleStart = 0; cycleStart < array.length - 1; cycleStart++) {
T item = array[cycleStart];
// Find where to put the item.
int pos = cycleStart;
for (int i = cycleStart + 1; i < array.length; i++)
if (array[i].compareTo(item) < 0) pos++;
// If the item is already there, this is not a cycle.
if (pos == cycleStart) continue;
// Otherwise, put the item there or right after any duplicates.
while (item.equals(array[pos])) pos++;
{
final T temp = array[pos];
array[pos] = item;
item = temp;
}
writes++;
// Rotate the rest of the cycle.
while (pos != cycleStart) {
// Find where to put the item.
pos = cycleStart;
for (int i = cycleStart + 1; i < array.length; i++)
if (array[i].compareTo(item) < 0) pos++;
// Put the item there or right after any duplicates.
while (item.equals(array[pos])) pos++;
{
final T temp = array[pos];
array[pos] = item;
item = temp;
}
writes++;
}
}
return writes;
}
public static final void main(String[] args) {
final Random rand = new Random();
final Integer[] array = new Integer[8];
for (int i = 0; i < array.length; i++) { array[i] = rand.nextInt(8); }
for (int iteration = 0; iteration < 10; iteration++) {
System.out.printf("array: %s ", Arrays.toString(array));
final int writes = cycleSort(array);
System.out.printf("sorted: %s writes: %d\n", Arrays.toString(array), writes);
Collections.shuffle(Arrays.asList(array));
}
}
}
A few example runs :
array: [3, 2, 6, 1, 3, 1, 4, 4] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 6
array: [1, 3, 4, 1, 3, 2, 4, 6] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 4
array: [3, 3, 1, 1, 4, 4, 2, 6] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 6
array: [1, 1, 3, 2, 4, 3, 6, 4] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 6
array: [3, 2, 3, 4, 6, 4, 1, 1] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 7
array: [6, 2, 4, 3, 1, 3, 4, 1] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 6
array: [6, 3, 2, 4, 3, 1, 4, 1] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 5
array: [4, 2, 6, 1, 1, 4, 3, 3] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 7
array: [4, 3, 3, 1, 2, 4, 6, 1] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 7
array: [1, 6, 4, 2, 4, 1, 3, 3] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 7
array: [5, 1, 2, 3, 4, 3, 7, 0] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 5
array: [5, 1, 7, 3, 2, 3, 4, 0] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 6
array: [4, 0, 3, 1, 5, 2, 7, 3] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 8
array: [4, 0, 7, 3, 5, 1, 3, 2] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 7
array: [3, 4, 2, 7, 5, 3, 1, 0] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 7
array: [0, 5, 3, 2, 3, 7, 1, 4] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 6
array: [1, 4, 3, 7, 2, 3, 5, 0] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 7
array: [1, 5, 0, 7, 3, 3, 4, 2] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 7
array: [0, 5, 7, 3, 3, 4, 2, 1] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 4
array: [7, 3, 1, 0, 3, 5, 4, 2] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 7
If the array is shorter (ie less than about 100 elements) a Selection sort is often the best choice if you also want to reduce the number of writes.
From wikipedia:
Another key difference is that
selection sort always performs Θ(n)
swaps, while insertion sort performs
Θ(n2) swaps in the average and worst
cases. Because swaps require writing
to the array, selection sort is
preferable if writing to memory is
significantly more expensive than
reading. This is generally the case if
the items are huge but the keys are
small. Another example where writing
times are crucial is an array stored
in EEPROM or Flash. There is no other
algorithm with less data movement.
For larger arrays/lists Quicksort and friends will provide better performance, but may still likely need more writes than a selection sort.
If you're interested this is a fantastic sort visualization site that allows you to watch specific sort algorithms do their job and also "race" different sort algorithms against each other.
You can use a very naive algorithm that satisfies what you need.
The algorithm should look like this:
i = 0
do
search for the minimum in range [i..n)
swap a[i] with a[minPos]
i = i + 1
repeat until i = n.
The search for the minimum can cost you almost nothing, the swap costs you 3 writes, the i++ costs you 1..
This is named selection sort as stated by ash. (Sorry, I didn't knew it was selection sort :( )
One option for large arrays is as follows (assuming n elements):
Initialize an array with n elements numbered 0..n-1
Sort the array using any sorting algorithm. As the comparison function, compare the elements in the input set with the corresponding numbers (eg, to compare 2 and 4, compare the 2nd and 4th elements in the input set). This turns the array from step 1 into a permutation that represents the sorted order of the input set.
Iterate through the elements in the permutation, writing out the blocks in the order specified by the array. This requires exactly n writes, the minimum.
To sort in-place, in step 3 you should instead identify the cycles in the permutation, and 'rotate' them as necessary to result in sorted order.
The ordering I meant in O(n) is like the selection sort(the previous post) useful when you have a small range of keys (or you are ordering numbers between 2 ranges)
If you have a number array where numbers will be between -10 and 100, then you can create an array of 110 and be sure that all numbers will fit in there, if you consider repeated numbers the idea is the same, but you will have lists instead of numbers in the sorted array
the pseudo-idea is like this
N: max value of your array
tosort //array to be sorted
sorted = int[N]
for i = 0 to length(tosort)
do
sorted[tosort[i]]++;
end
finalarray = int[length(tosort)]
k = 0
for i = 0 to N
do
if ( sorted[i] > 0 )
finalarray[k] = i
k++;
endif
end
finalarray will have the final sorted array and you will have o(N) write operations, where N is the range of the array. Once again, this is useful when using keys inside a specific range, but perhaps its your case.
Best regards and good luck!

Resources