count number of permutations in a cycle - algorithm

I have a permutation of numbers 1 to n. in each turn a permutation function is used to map the current permutation to a new one.
The function is defined by F(i) = p[i] which maps each element of the current permutation to a position in the new permutation. Since this function is injective and surjective, it can be proved that we always get to the first permutation again. (It's actually a cycle in the permutations graph)
for example [2,3,1] -> [3,1,2] -> [1,2,3] -> [2,3,1] so the cycle length is 3 since the first and last permutations are the same and we're stuck in a loop.
As input I have a special kind of permutation like this:
[2,1,
4,5,3,
7,8,9,10,6,
17,11,12,13,14,15,16,
18,19,20,
29,21,22,23,24,25,26,27,28,
40,30,31,32,33,34,35,36,37,38,39,
53,41,42,43,44,45,46,47,48,49,50,51,52]
It's made of some sub-permutations (each line has a set of numbers which belong to the set of their indexes)
My question is what's the minimum number of moves needed to get to the first permutation again.
As a practice problem in prolog I want to calculate the number of moves for each sub-permutation and get their lcm but I'm not sure how to implement this (how to count the number of moves for each sub-permutation)
Any help would be appreciated

A permutation p can be seen as a bijective function from the set {1,2,...,n} onto itself. Now what you seem to ask for is the minimal number of concatenations of this permutation with itself p o p o ... o p (where o is the concatenation operator with (f o g)(i) := f(g(i))) s.t. you get the identity permutation p0 with p0(i) = i.
You have a permutation that can be easily decomposed into cycles 1->2->1, 3->4->5->3, 6->7->8->9->10->6, ...
Each cycle needs as many concatenations with itself as it has members to get the identity. Since you have cycles of lengths 2, 3, 5, 7, 3, 9, 11, 13 it takes 2*9*5*7*11*13 (the least common multiple) concatenations until all cycles are run through at the same time for the first time.

Related

Find only two numbers in array that evenly divide each other

Find the only two numbers in an array where one evenly divides the other - that is, where the result of the division operation is a whole number
Input Arrays Output
5 9 2 8 8/2 = 4
9 4 7 3 9/3 = 3
3 8 6 5 6/3 = 2
The brute force approach of having nested loops has time complexity of O(n^2). Is there any better way with less time complexity?
This question is part of advent of code.
Given an array of numbers A, you can identify the denominator by multiplying all the numbers together to give E, then testing each ith element by dividing E by Ai2. If this is a whole number, you have found the denominator, as no other factors can be introduced by multiplication.
Once you have the denominator, it's a simple task to do a second, independent loop searching for the paired numerator.
This eliminates the n2 comparisons.
Why does this work? First, we have an n-2 collection of non-divisors: abcde..
To complete the array, we also have numerator x and denominator y.
However, we know that x and only x has a factor of y, so it can be expressed as yz (z being a whole remainder from the division of x by y)
When we multiply out all the numbers, we end up with xyabcde.., but as x = yz, we can also say y2zabcde..
When we loop through dividing by the squared i'th element from the array, for most of the elements we create a fraction, e.g. for a:
y2zabcde.. / a2 = y2zbcde.. / a
However, for y and y only:
y2zabcde.. / y^2 = zabcde..
Why doesn't this work? The same is true of the other numbers. There's no guarantee that a and b can't produce another common factor when multiplied. Take the example of [9, 8, 6, 4], 9 and 8 multiplied equals 72, but as they both include prime factors 2 and 3, 72 has a factor of 6, also in the array. When we multiply it all out to 1728, those combine with the original 6 so that it can divide soundly by 36.
How might this be fixed? More accurately, if y is a factor of x, then y's prime factors will uniquely be a subset of x's prime factors, so maybe things can be refined along those lines. Obtaining a prime factorization should not scale according to the size of the array, but comparing subsets would, so it's not clear to me if this is at all useful.
I think that O(n^2) is the best time complexity you can get without any assumptions on the data.
If you can't tell anything about the numbers, knowing that x and y do not divide each other tells you nothing about x and z or y and z for any x, y, z. Therefore, in the worst case you must check all pairs of numbers - equal to n Choose 2 = n*(n-1)/2 = O(n^2).
Clearly, we can get O(n * sqrt(m)), where m is the absolute value range, by listing the pairs of divisors of each element against a hash of unique values in the array. This can be more efficient than O(n^2) depending on the input.
5 9 2 8
list divisor pairs (at most sqrt m iterations per element m)
5 (1,5)
9 (1,9), (3,3)
2 (1,2)
8 (1,8), (2,4) BINGO!
If you prime factorise all the numbers in the array progressively into a tree, when we discover a completely factored number leaf while factoring another number, we know we've found the divisor.
However, given we don't know which number is the divisor, we do need to test all primes up to divisor's largest factor. The largest factor for any m-digit number is, at most, sqrt(m), while the average number of primes below any m-digit number is m / ln(m). This means we will make at most n (sqrt(m) / ln(sqrt(m)) operations with very basic factorization and no optimization.
To be a little more specific, the algorithm should keep track of four things: a common tree of explored prime factors, the original number from the array, its current partial factorization, and its position in the tree.
For each prime number, we should test all numbers in the array (repeatedly to account for repeated factors). If the number divides evenly, we a) update the partial factorization, b) add/navigate to the corresponding child to the tree, c) if the partial factorization is 1, we have found the last factor and can indicate a leaf by adding the terminating '1' child, and d) if not, we can check for other numbers having left a child '1' to indicate they are completely factored.
When we find a child '1', we can identify the other number by multiplying out the partial factorization (e.g. all the parents up the tree) and exit.
For further optimization, we can cache the factorization (both partial and full) of numbers. We can also stop checking further factors of numbers that have a unique factor, narrowing the field of candidates over time.

Constructing dodge ball team

A coach is trying to construct a dodge ball team. Each player is assigned a student ID, and if one player's ID divides by other player's ID, they fight. So the couch wants to make a team so that no one fights in the team. Given the number N (ID is assigned 1 to N), find out the minimum number K
where the couch is unable to make a team in which no one fights.
input (N): 3
output (K): 2
For example, N = 3,
K = 3, {1,2,3} --> Player 1 and 2 has a fight.
K = 2, {2,3} --> No one fights.
input (N): 4
output (K): 2
N = 4,
K = 4, {1,2,3,4} -> more than a pair of players (1,2), (1,3), etc, fights.
K = 3, {1,2,4}, {2,3,4}, {1,3,4} --> players fights in all teams.
K = 2, {2,3} --> No one fights.
So basically, given N, find out the minimum K that a couch can't make any combination of K players so that no one fights. (This is also the maximum number K'+1 where a couch can find at least one team of K' where no one fights.)
A greedy solution I and my friend came up with is try finding the maximum set from the given N. The optimal set must contain the big numbers because since if we start putting small numbers, 2, 3, ..., all the multipliers of these numbers can't be included. So we can start putting N to N/2 in a set as long as the new number is not a divisor of some number already included in the set. We are not entirely sure if this solution would be correct, so we would love to discuss the correctness of our solution and hear other people's ideas.
I was asked to solve this coding problem during an online coding test but couldn't figure it out how to solve.
The way I answered this was return the number of primes in n + 1.
The k is the minimum number that makes it impossible to have pairs that don't fight, as in, at least one pair of a number that divides the other evenly, yes? Based on that, the "safest" bet is prime numbers (since they can't divide each other). Once you add non-prime numbers, you'll be certain to have a "fighting" pair.
Case 1: all prime numbers in n and the number 1 (trivial).
Case 2: all prime numbers in n and any even number in n (the even number can be divided by 2, which eliminates this option).
Case 3: all prime numbers and an odd number (any composite -non prime - odd number can be divided by an odd prime number).
I'm not 100% sure on case 3 regarding mathematical proof, but it seems to be the case.
Disclaimer: I haven't yet received feedback from the interview, this could be totally wrong.

Correctness proof of Algorithm

Our teacher asked us a question which goes like this.
Given a list of n distinct integers and a sequence of n boxes with preset
inequality signs inserted between them, design an algorithm that places
the numbers into the boxes to satisfy those inequalities. For example, the
numbers 2, 5, 1, and 0 can be placed in the four boxes as shown below
The from looking at the question we can say the numbers be sorted and if less than symbol appears next we have to insert the least number, if greater than symbol appears we have to insert max number and proceed as so.
How can I say this algorithm works for every case?
Traversing in
one direction i found one solution and in reverse order i found
another. What is the efficient method to find all solutions to this
problem?
To answer question 1, I'd say that should be done by induction over the number of distinct numbers involved.
Say n is the number of numbers.
for n = 1 there's nothing left to prove.
for n = 2, you have either a greater than or a less than operator. Since the numbers are distinct and the set of natural (or real) numbers is well ordered, your algorithm will trivially yield a solution.
n -> n+1:
case 1: the first operator is a less than sign. According to your algorithm you pick the smallest number and put it into the first box. Then you solve the problem for the last n boxes. This is possible by induction. Since the number in the first box is the smallest, it is also smaller than the number in the second box. Therefor you have a solution.
Case 2: the first operator is a greater than sign. This also works analogue to case 1.
QED
Now for the second part of the question. My thoughts came up with the algorithm described below. Happy with the fact I solved the question (of getting all solutions) in the first place, I can't guarantee that it's the fastest solution.
As already noted in a comment, if there are no operator changes, there will be only one solution. So we assume there are operator changes (but the algorithm will produce this solution too).
for all operator changes of the form >< or nil < (first operator is a <):
place the smallest element between them
now divide the remaining set of numbers into two.
if there are n numbers and there are k operators to the left of
the placed number, that will give you k over (n - 1) possibilities.
do this recursively with the two remaining parts.
If no operator changes of the form >< or nil < are left,
do the same with the mirrored operator changes <> and nil >,
but choose the highest element of the set.
If no operator changes are left, fill in the elements according to the
remaining operator in ascending or descending order.
OK, this is not program code, but I think that will be comparatively easy (the choose k out of n - 1 is the hard part). I hope my explanation of the algorithm is understandable. And beware, the number of solutions grows fast (exponentially, probably worse).
Answering part two of the question in part, finding one single solution:
First, the input can be sorted, which can be done in O( n log n ) time. Then, the algorithm described can be applied; the minimum and maximum element are at the beginning and the end of the list, which can be accessed in constant time. This means that, once the input is sorted, the output can be generated in O( n ) time. This yields a runtime bound of O( n log n ) in total.
Here's a proof that there is an assignment of numbers to boxes:
The diagram defines a partial order on the empty boxes (box A <= box B
if either A=B, or A is the left of B and there's only < between them,
or A is to the right of B and there's only > between them). It's easy
to check that <= satisfies the properties of a partial order.
Any finite partially ordered set can be totally ordered (for example
by using a topological sort).
So sort the boxes with respect to the total order, and assign numbers
based on the position in the resulting list.
This yields an answer to part (2) of your question, which is to enumerate all possible solutions. A solution is exactly a total order that's compatible with the partial order defined in the proof, and you can generate all possible total orders by choosing which minimal element you pick at each stage in the topological sort algorithm.
That is, you can generate all solutions like this:
topo_sort(boxes):
if boxes = [] then return [[]]
let result = []
for each x in minimal(boxes)
for each y in topo_sort(boxes - x)
append ([x] + y) to result
return result
minimal(boxes):
return [all x in boxes such that there's no y != x in boxes with y lesseq x]
Here "lesseq" is constructed as in the proof.
If you squint hard enough, you can see that your algorithm can also be viewed as a topological sorting algorithm, using the observation that if the next symbol is a > then the first element is maximal in the remaining list, and if the next symbol is a < then the first element is minimal in the remaining list. That observation gives you a proof that your algorithm is also correct.
Here's an inefficient Python 2.7 implementation:
def less(syms, i, j):
if i == j: return False
s = '<' if i < j else '>'
return all(c == s for c in syms[min(i,j):max(i,j)])
def order(boxes, syms):
if not boxes:
yield []
return
for x in [b for b in boxes if not any(less(syms, a, b) for a in boxes)]:
for y in order(boxes - set([x]), syms):
yield [x] + y
def solutions(syms):
for idxes in order(set(range(len(syms)+1)), syms):
yield [idxes.index(i) for i in xrange(len(syms)+1)]
print list(solutions('<><'))
Which gives as output all 5 solutions:
[[0, 2, 1, 3], [0, 3, 1, 2], [1, 2, 0, 3], [1, 3, 0, 2], [2, 3, 0, 1]]

Generate a sequence of numbers (powers) in order

I'm looking for an algorithm (or better yet, code!) for a the generation of powers, specifically numbers with an odd exponent greater than 1: third powers, fifth powers, seventh powers, and so forth. My desired output is then
8, 27, 32, 125, 128, 216, 243, 343, 512, 1000
and so forth up to a specified limit.
I don't want to store the powers in a list and sort them, because I'm making too many to fit in memory -- hopefully the limit be 1030 or so, corresponding to a memory requirement of ≈ 1 TB.
My basic idea is to have an array holding the current number (starting at 2) for each exponent, starting with 3 and going up to the binary log of the limit. At each step I loop through the exponent array, finding the one which yields the smallest power (finding either pow(base, exponent) or more likely exponent * log(base), probably memoizing these values). At that point call the 'output' function, which will actually do calculations with the number but of course you don't need to worry about that.
Of course because of the range of the numbers involved, bignums must be used -- built into the language, in a library, or self-rolled. Relevant code or code snippets would be appreciated: I feel that this task is similar to some classic problems (e.g., Hamming's problem of generating numbers that are of the form 2x3y5z) and can be solved efficiently. I'm fairly language-agnostic here: all I'll need for my 'output' function are arrays, subtraction, bignum-word comparison, and a bignum integer square root function.
Your example is missing 64=4^3, and 729=9^3.
You want the set of all { n^m } traversed in numerical order, m odd, n integral and n > 1. We know that (for n > 1) that increasing either n or m will increase this value, but short of calculation we can't compare much else.
There are two obvious "dual" ways to do this: keep track of the highest base n you consider, and for all bases less than that, the next exponent m to consider. Then pick the smallest one, and compare it to n^3. Or, the other way around -- keep track of the highest exponent m, and for each exponent smaller than that, keep track of the highest base used, and find the smallest one, and compare it to adding 2^m.
To make keeping track of these numbers efficiently, you'll want to keep them in a priority queue. Now, you still want to minimize the number of entries in the priority queue at a time, so we'll want to figure out which of these two methods does better job of this. It turns out that much higher n values are required to make it to a given point. At number k, the largest value of m seen will be log_2 of k, whereas the largest value of n seen will be k^(1/3).
So, we have a priority queue with elements (v, n, m), where the value v=n^m.
add_priority_queue(2^3, 2, 3)
for m in 5, 7, ....
v = 2^m
while value(peek(queue)) <= v:
(v1, n1, m1) = pop(queue)
if v1 != v print v1
add_priority_queue((n1+1)^m1, n1+1, m1)
add_priority_queue(2^m, 2, m)
Note that we need to check for v1 = v: we can have 2^9 = 512 = 8^3, and only one should be printed out, right?
A Haskell implementation, with a random priority queue grabbed off of hackage.
import Data.MeldableHeap
dropMin q = maybe empty snd (extractMin q)
numbers = generate_values (insert (2^3, 2, 3) empty) 5
generate_values q m = case findMin q of
Nothing -> []
Just (v1, n1, m1) -> case compare v1 (2^m) of
EQ -> generate_values (insert ((n1+1)^m1, n1+1, m1) (dropMin q)) m
LT -> v1 : generate_values (insert ((n1+1)^m1, n1+1, m1) (dropMin q)) m
GT -> 2^m : generate_values (insert (3^m, 3, m) q) (m + 2)
main = sequence_ (map print numbers)
I have a run currently at 177403008736354688547625 (that's 23 digits) and 1.3 GB plaintext output, after 8 minutes
deque numbers // stores a list of tuples - base number, and current odd power value - sorted by the current odd power value
for i = 2 .. infinity
numbers.push_back (i,i^3) // has to be the highest possible number so far
while numbers.peek_front[1] == i // front always has the lowest next value
print i
node = numbers.pop_front
node[1]=node[1]*(node[0]^2)
// put the node back into the numbers deque sorted by the second value in it - will end up being somewhere in the middle
at 2, numbers will be [2,8]
at 3, numbers will be [2,9], [3, 27]
...
at 8, numbers will be [2,8], [3,27].....[8,8^3]
You'll take off the first node, print it out, then put it back in the middle of numbers with the values [2,32]
I think this will work and has a reasonable memory usage.
There's a special case for 1, since 1^N never changes. This will also print out duplicate values for numbers - 256 for instance - and there are fairly simple ways to slightly alter the algorithm to remove those.
This solution is constant time for checking each number, but requires quite a bit of ram.
Consider k lists for numbers 2 .. k+1 numbers. Each list i represents the powers of number i+1. Since each list is a sorted use k-way merging with min heap to achieve what you need.
Min-heap is constructed with first indices of lists as key and after minimum is extracted we remove first element making second element as key and rearrange the heap to get next minimum.
This procedure is repeated till we get all numbers.

equal k subsets algorithm

does anyone know a good and efficient algorithm for equal k subsets algorithm ? preferably c or c++ which could handle a 100 element vector maybe with a complexity and time estimation
ex. 9 element vector
x = {2,4,5,6,8,9,11,13,14}
i need to generate all k=3 disjoint subsets with sum = 24
the algorithm should check if there are k disjoint subsets each with sum of elements 24, and list them in ascending order(in subset and between subsets) or to see if the solution doesn't exists
Solutions
solution 1: {2 8 14} {4 9 11} {5 6 13}
solution 2: {2 9 13} {4 6 14} {5 8 11}
Thanks
Unfortunately the constrained k-subset problem is a hard problem ... and if you want to generate all such k-subsets, you have no choice but to evaluate many possible candidates.
There are a couple of optimizations you can perform to reduce the search space.
Given a domain x constaining integer values,
Given a positive integer target M,
Given a positive integer k size for the subset,
When x only contains positive integers, and given a upper bound M, remove all items from x larger than or equal to M. These can't possibly be part of the subset.
Similarly, for k > 1, a given M, and x containing positive integers, remove all items from x which are larger than M + min0 + min1 ... minK. Essentially, remove all of the large values which can't possibly be part of the subset since even when selecting small values they will results in a sum in excess of M.
You can also use the even/odd exclusion principle to pare down your search space. For instance, of k is odd and M is even, you know that the sum will either contain three even numbers or two odd and one even. You can use this information to reduce the search space by eliminating candidate values from x that could be part of the sum.
Sort the vector x - this allows you to rapidly exclude values that can't possibly be included in the sum.
Many of these optimizations (other than the even/odd exclusion) are no longer useful/valid when the vector x contains negative values. In this case, you pretty much have to do an exhaustive search.
As Jilles De Wit points out, if X contains negative numbers you could add the absolute value of the smallest value in X to each member of X. This would shift all values back into positive range - making some of the optimizations I describe above possible again. This requires, however, that you are able to accurately represent positive values in the enlarged range. One way to achieve this would be to internally use a wider type (say long instead of int) to perform the subset selection search. If you do this, however, remember to scale the results subsets back down by this same offset when you return your results.

Resources