Sorting permutation efficiently - algorithm

Given an unsorted permutation of [n], I want to collect the numbers by iterating from left to right in order to sort the premutation (1...n).
What is the number of iteration I have to do in order to acheieve this goal?
For example:
Given '3, 7, 4, 2, 10, 8, 9, 1, 6, 5'- the number of iterations is 6.
In the first iteration I will collect the number 1
In the second iteration I will collect the number 2
In the third iteration I will collect the numbers 3,4,5
In the forth iteration I will collect the number 6
In the fifth iteration I will collect the numbers 7,8,9
In the sixth iteration I will collect the number 10
I build a naive code, doing the task with O(n^2), but I need it to be more efficient, so I think there's a trick I'm missing here.
Any suggestions?

Invert the permutation, then count how many times two consecutive numbers are decreasing, plus one.
def iterations(perm):
invperm = [None] * len(perm)
for i in range(len(perm)): # yes, we could use enumerate
invperm[perm[i] - 1] = i
count = 1
for i in range(1, len(perm)):
count += invperm[i - 1] > invperm[i]
return count
Explaination:
Given : 3, 7, 4, 2, 10, 8, 9, 1, 6, 5
x : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Index of x in the given array : |8, |4, |1, 3, 10, |9, |2, 6, 7, |5
If indexes are out of order then you have to start again. So if you count |s then you know number of iterations you need.

Since you already know the result, it's unclear to me in what sense you're "sorting" anything. What result are you looking for -- the information about what numbers are "collected" at each iteration, as you show in your Q? In this case here's a simple Python 2 implementation example:
target = 3, 7, 4, 2, 10, 8, 9, 1, 6, 5
def do_permut(targ):
look_for = 1
iter_num = 1
while look_for != len(targ) + 1:
print 'Iteration', iter_num, ':',
for item in targ:
if item == look_for:
print item,
look_for += 1
print
iter_num += 1
do_permut(target)
However the task is inevitably O(N squared) -- remember big-O stands for worst case! You'll have up to N iterations (worst case realized when targ is reverse sorted to start with) each over N numbers -- thus, N squared. You could slightly optimize each iteration by collecting a set of numbers previously seen during it and breaking when look_for is in that set, but that only (roughly) halves each iteration's work, so it's still O(N squared).
If you can explain better what results and outputs you expect from your work we may be able to help more!
Just for curiosity here's a version with the above "improvement" and also a sanity check to ensure it raises an exception, rather than looping forever, if passed a sequence that's NOT a permutation of [1:n)...:
target = 3, 7, 4, 2, 10, 8, 9, 1, 6, 5
def do_permut(targ):
look_for = 1
iter_num = 1
while look_for != len(targ) + 1:
print 'iteration', iter_num, ':',
seen = set()
found_in_iter = 0
for item in targ:
seen.add(item)
if item == look_for:
print item,
found_in_iter += 1
look_for += 1
if look_for in seen:
break
print
if not found_in_iter:
raise ValueError('missing: %s' % look_for)
iter_num += 1
do_permut(target)

If you know that in assumption is given an array where for sure are present all elements of the permutation of [n] then I think:
Allocate an array y[1..n]
In one loop from 1 to n search initial array x of unsorted elements colecting items in each iteration the following way: y[x[i]] := x[i]
After the loop all in y is a sorted permutation with O (n)
-- edited 20-12-2014 22:54 CET:
The solution above works only for situation, where there is n-elementh table of integers from 1 to n unordered in any given way.
I'd like to explain in details how you can achieve the goal with only one iteration through the inpput array basing on your example.
Let's take the initial array:
x[] = { 3, 7, 4, 2, 10, 8, 9, 1, 6, 5 }
As a result let's take the following array filled at start with zero's:
y[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
Now let each item of the following ordered list be an iteration of the sorting algorithm:
We take x[1] which equals 3 - let's write it under 3rd position in result table y:
y[3] := 3 (which in fact is: y[x[1]] := x[1])
the result table now looks like following
y[] = { 0, 0, 3, 0, 0, 0, 0, 0, 0, 0 }
In second step we take x[2] which equals 7 and we repeat the steps:
y[7] := 7 (which in fact is: y[x[2]] := x[2])
the result table now looks like following
y[] = { 0, 0, 3, 0, 0, 0, 7, 0, 0, 0 }
Third step: x[3] which equals 4:
y[4] := 4 (which in fact is: y[x[3]] := x[3])
result table:
y[] = { 0, 0, 3, 4, 0, 0, 7, 0, 0, 0 }
x[4] which equals 2:
y[2] := 2 (which in fact is: y[x[4]] := x[4])
result table:
y[] = { 0, 2, 3, 4, 0, 0, 7, 0, 0, 0 }
x[5] which equals 10:
y[10] := 10 (which in fact is: y[x[5]] := x[5])
result table:
y[] = { 0, 2, 3, 4, 0, 0, 7, 0, 0, 10 }
x[6] which equals 8:
y[8] := 8 (which in fact is: y[x[6]] := x[6])
result table:
y[] = { 0, 2, 3, 4, 0, 0, 7, 8, 0, 10 }
x[7] which equals 9:
y[9] := 9 (which in fact is: y[x[7]] := x[7])
result table:
y[] = { 0, 2, 3, 4, 0, 0, 7, 8, 9, 10 }
x[8] which equals 1:
y[1] := 1 (which in fact is: y[x[8]] := x[8])
result table:
y[] = { 1, 2, 3, 4, 0, 0, 7, 8, 9, 10 }
x[9] which equals 6:
y[6] := 6 (which in fact is: y[x[9]] := x[9])
result table:
y[] = { 1, 2, 3, 4, 0, 6, 7, 8, 9, 10 }
The last iteration:
x[10] which equals 5:
y[5] := 5 (which in fact is: y[x[10]] := x[10])
result table:
y[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
As we can see table y is a fully sorted version of input table x that was generated with 10 iterations (so O(n) cost level).
No matter how big is n and how much unordered is the given input table, with those particular assumptions taken, the cost is constant and equals n;
I hope I didn't misunderstood your question.

I tried to implement your sample in PERL.
#!/usr/bin/perl
if ($#ARGV < 0) { # with no arguments
#data = (3, 7, 4, 2, 10, 8, 9, 1, 6, 5);
}
else {
#tmp = (1..$ARGV[0]);
while(#tmp) {
push(#data, splice(#tmp, rand($#tmp), 1));
}
}
$key = 1;
while (#data) {
#remove = (); #remain = ();
printf "key = $key\t(#data) --> ";
foreach $i (#data) {
if ($i == $key) { # found
push(#remove, $i);
$key++;
}
else {
push(#remain, $i);
}
}
#data = #remain;
print "(#remove) & (#data)\n";
$count++;
}
print "Iteration = $count\n";
As a result.
$ ./a.pl
key = 1 (3 7 4 2 10 8 9 1 6 5) --> (1) & (3 7 4 2 10 8 9 6 5)
key = 2 (3 7 4 2 10 8 9 6 5) --> (2) & (3 7 4 10 8 9 6 5)
key = 3 (3 7 4 10 8 9 6 5) --> (3 4 5) & (7 10 8 9 6)
key = 6 (7 10 8 9 6) --> (6) & (7 10 8 9)
key = 7 (7 10 8 9) --> (7 8 9) & (10)
key = 10 (10) --> (10) & ()
Iteration = 6
$ ./a.pl 10
key = 1 (2 1 4 8 5 9 3 6 7 10) --> (1) & (2 4 8 5 9 3 6 7 10)
key = 2 (2 4 8 5 9 3 6 7 10) --> (2 3) & (4 8 5 9 6 7 10)
key = 4 (4 8 5 9 6 7 10) --> (4 5 6 7) & (8 9 10)
key = 8 (8 9 10) --> (8 9 10) & ()
Iteration = 4
$ ./a.pl 10
key = 1 (3 1 7 8 6 2 9 5 4 10) --> (1 2) & (3 7 8 6 9 5 4 10)
key = 3 (3 7 8 6 9 5 4 10) --> (3 4) & (7 8 6 9 5 10)
key = 5 (7 8 6 9 5 10) --> (5) & (7 8 6 9 10)
key = 6 (7 8 6 9 10) --> (6) & (7 8 9 10)
key = 7 (7 8 9 10) --> (7 8 9 10) & ()
Iteration = 5

Related

A* Search Algorithm Not Giving the Optimal Path

I am trying to create a MATLAB script for A* Search Algorithm. I created a script. I tried it with a 6-node graph, and computed the correct path. However, this time I tried the script for a different graph (with 12 nodes) and this time I received a wrong answer.
These are the node information nodes.csv file:
Node number, (x, y) coords, heuristic cost
1, -0.5,-0.5, 1.4142
2, -0.09,-0.4, 1.0762
3, -0.285,-0.305, 1.1244
4, 0.0575,-0.225, 0.8494
5, -0.0525,-0.0175, 0.7604
6, -0.37,0.3, 0.8927
7, 0.3525,-0.0525, 0.5719
8, 0.0625,0.255, 0.5014
9, -0.1,0.3725, 0.6134
10, 0.4275,0.195, 0.3135
11, 0.345,0.3525, 0.214
12, 0.5,0.5, 0
These are the edge informations from edges.csv file (edges are undirected):
Node 1, Node 2, Cost
12, 11, 0.214
12, 10, 0.3135
12, 8, 0.5014
11, 10, 0.1778
11, 9, 0.4454
10, 7, 0.2586
9, 8, 0.2005
9, 6, 0.2796
9, 5, 0.5994
8, 4, 0.48
7, 4, 0.3417
5, 2, 0.179
4, 3, 0.3517
4, 2, 0.2289
3, 2, 0.2169
3, 1, 0.2903
2, 1, 0.422
7, 5, 0.4402
5, 4, 0.11
The solution to the graph is: 1 - 3 - 4 - 7 - 10 - 12.
The path my script calculated is: 1 - 3 - 4 - 2 - 5 - 5 - 7 - 10 - 12.
Notice that node 5 is shown twice, which I have no idea about. I tried to debug, but could not find what was the incorrect part.
Here is my code:
clc
clear
%% Constructing the Nodes with their information:
% Assigning the adjacent node information to nodes:
nodes = readmatrix('nodes.csv');
edges = readmatrix('edges.csv');
node(1).successors = [2 3];
node(2).successors = [3 4 5];
node(3).successors = [1 2 4];
node(4).successors = [5 2 3 7 8];
node(5).successors = [4 7 2 9];
node(6).successors = 9;
node(7).successors = [5 4 10];
node(8).successors = [4 9 12];
node(9).successors = [5 6 8 11];
node(10).successors = [7 11 12];
node(11).successors = [9 10 12];
node(12).successors = [8 10 11];
% Assigning heuristic cost values and cost numbers to nodes:
heuristics = nodes(:,4);
for i = 1 : length(nodes)
node(i).heuristic = heuristics(i);
node(i).order = i;
end
% Initializing the pastCost and totalCost of the nodes:
node(1).pastCost = 0;
node(1).totalCost = node(1).pastCost + node(1). heuristic;
for i = 2 : length(nodes)
node(i).pastCost = Inf;
node(i).totalCost = node(i).pastCost + node(i). heuristic;
end
nodeStart = nodes(1, 1);
nodeGoal = nodes(12, 1);
% Node start has no parent node:
node(nodeStart).parent = [];
% Adding the first node to OPEN List
OPEN = {node(1)};
CLOSED = {};
%% Starting the A* Search Algorithm:
% If tthe OPEN list is not empty, iterations are going to start:
while(~isempty(OPEN))
current = OPEN{1};
OPEN(1) = [];
CLOSED{length(CLOSED) + 1} = current;
% If the current node is the goal node, algorithm is finished with
% success, return the path from the CLOSED List:
if (current.order == nodeGoal)
disp('SUCCESS!')
for i = 1 : length(CLOSED)
fprintf(' %d ', CLOSED{i}.order)
end
return
end
% Creating an array which consists of the node numbers of the closed nodes:
for i = 1 : length(CLOSED)
closedNodes(i) = CLOSED{i}.order;
end
% Starting searching through the adjacents/successors of the current node:
for i = 1 : length(current.successors)
% If the current node is not in the CLOSED List / member of the
% closedNodes array, calculations are going to be taking place:
if (~ismember(current.successors(i), closedNodes))
tentativePastCost = current.pastCost + edgeCost(current.order, current.successors(i), edges);
if (tentativePastCost < node(current.successors(i)).pastCost)
node(current.successors(i)).pastCost = tentativePastCost;
node(current.successors(i)).parent = current.order;
node(current.successors(i)).totalCost = node(current.successors(i)).pastCost + node(current.successors(i)).heuristic;
% Adding the current node to the OPEN List and then sorting
% the OPEN List with respect to total cost values:
if(length(OPEN) == 0 || node(current.successors(i)).order ~= OPEN{length(OPEN)}.order)
OPEN{length(OPEN) + 1} = node(current.successors(i));
end
[~,I] = sort(cellfun(#(s) getfield(s,"totalCost"), OPEN));
OPEN = OPEN(I);
end
end
end
end
disp('FAILURE!')
What is the reason my program jumps from node 4 to 2, instead of node 7?

Finding remaining months in a fiscal year

I need to calculate the number of remaining months in a fiscal year from the given month, where a fiscal year starts from the fourth month of the year. I have an array illustrating this:
months = [4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]
Some expected inputs and outputs are:
4 => 11
10 => 5
2 => 1
However, when 3 is given (as well as when 2 is given), I want it to return 1 because the return value is used in a multiplication, and if it is 0, the output becomes 0.
I solved this by doing:
#month == 3 ?
annual_taxable_income += total_monthly_income_present_month :
annual_taxable_income += total_monthly_income_present_month + #basic_salary * fiscal_months_array[#month - 3, 12].size
I used ternary operator to check if there is 3, and if there is, then do not find the remaining months. The solution is working but I need a better way to do this.
def remaining_months(mon)
(3 - mon) % 12
end
(1..12).each { |mon| puts "#{mon} -> #{remaining_months(mon)}" }
1 -> 2
2 -> 1
3 -> 0
4 -> 11
5 -> 10
6 -> 9
7 -> 8
8 -> 7
9 -> 6
10 -> 5
11 -> 4
12 -> 3
You therefore would want [remaining_months(mon), 1].max. It's best not to put this part in the method remaining_months.
Note that the array months is determined by the first element, which is the first month of the fiscal year (4). It therefore should not be surprising that only the first element is needed in calculations.
Do you ever have problems like this where a modulus is involved and finding yourself trying different expressions until you finally find hit on one that works? Here's a way to do that for those in audience who are somewhat lazy by nature.
RESULT = [*(3..11), 0, 1, 2].reverse
a = [*(-12..0), *(1..12)]
a.product([1,-1], (a-[0]), a).
select do |c1,c2,c3,c4|
(1..12).all? { |mon| c1 + c2 * ((c3 * mon + c4) % 12) == RESULT[mon-1] }
end.
map do |c1,c2,c3,c4|
s1 = c1.zero? ? '' : c1.to_s
s2 = case c1.zero?
when true then c2==1 ? '' : '-'
else c2==1 ? ' + ' : ' - '
end
s3 = if c3 > 0
c3==1 ? '' : "#{c3} * "
else
c3==-1 ? '- ' : "- #{c3.abs} * "
end
s4 = case c4 <=> 0
when 0 then ''
when -1 then " - #{c4.abs}"
else " + #{c4}"
end
"#{s1}#{s2}((#{s3}mon#{s4}) % 12"
end
#=> ["((- mon - 9) % 12",
# "((- mon + 3) % 12",
# "(11 * mon - 9) % 12",
# "(11 * mon + 3) % 12",
# "11 - ((- 11 * mon - 4) % 12",
# "11 - ((- 11 * mon + 8) % 12",
# "11 - ((mon - 4) % 12",
# "11 - ((mon + 8) % 12"]
Take your pick!
Here we obtain the following intermediate result.
a.product([1,-1], (a-[0]), a).
select do |c1,c2,c3,c4|
(1..12).all? { |mon| c1 + c2 * ((c3 * mon + c4) % 12) == RESULT[mon-1] }
end
#=> [[0, 1, -1, -9], [0, 1, -1, 3], [0, 1, 11, -9], [0, 1, 11, 3],
# [11, -1, -11, -4], [11, -1, -11, 8], [11, -1, 1, -4], [11, -1, 1, 8]]
you could set the min value of the starting index value with max
fiscal_months = [4,5,6,7,8,9,10,11,12,1,2,3]
index = [#month-3, 1].max
annual_taxable_income += total_monthly_income_present_month + #basic_salary * fiscal_months[index, 12].size
It seems odd that you want a function that returns the same answer (1) for two different inputs (2,3). But, if that is the case you could do it like this. It is brute force but makes clear what you are trying to do:
def num_remaining_months_for (m)
fiscal_months = [4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]
remaining = [11, 10, 9, 8, 7, 6, 5, 4, 3 , 2, 1, 1]
index = fiscal_months.index(m)
remaining[index]
end
(1..12).each do |e|
puts "For month #{e} => #{num_remaining_months_for(e)} remaining"
end
The results are:
For month 1 => 2 remaining
For month 2 => 1 remaining
For month 3 => 1 remaining
For month 4 => 11 remaining
For month 5 => 10 remaining
For month 6 => 9 remaining
For month 7 => 8 remaining
For month 8 => 7 remaining
For month 9 => 6 remaining
For month 10 => 5 remaining
For month 11 => 4 remaining
For month 12 => 3 remaining
I would do it like that. I think it's clearer.
def number_of_remaining_months(month)
fiscal_months_array = [4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]
month = 2 if month == 3
fiscal_months_array.count - 1 - fiscal_months_array.index(month)
end
puts("Number of the month [1-12]:")
month = Integer(gets.chomp)
result = number_of_remaining_months(month)
annual_taxable_income = total_monthly_income_present_month +
#basic_salary * result
I hope it useful for you.

How do I find the smallest combination of 2 numbers to get closest to another number

I have two numbers: 6 & 10
I want to use a combination of these 2 numbers to get as close as possible to another number.
For example, to get to 9 I need 1 six with 3 remaining.
Other examples:
6: [6]
10: [10]
12: [6, 6]
18: [6, 6, 6]
20: [10, 10]
24: [6, 6, 6, 6]
26: [10, 10, 6]
28: [10, 6, 6, 6]
30: [10, 10, 10]
32: [10, 10, 6, 6]
I need an algorithm that can find the smallest number of combinations for any given number, taking preference for a combination with the smallest remainder. ie
38: [10, 10, 10, 6] - 2 remaining
38: [10, 10, 6, 6, 6] - no remainder, so preferred result
I hope I've explained this clearly, let me know if I need to clarify.
UPDATE:
To clarify, this is a real-world problem dealing with physical goods. The numbers 6 & 10 correspond to package cartons that contain multiples of a product in either 6 or 10 quantities. We accept orders for these products in any amount, and want to calculate the smallest number of cartons that can make up the order, and then add the remainder as individual qtys.
A customer may want to order a qty of 39, so I need to know the smallest number of 6/10 qty cartons to make up the order, with the smallest number of remainders being the priority.
A customer may also order qtys of 1,2,3,4,5,6..... up to a max of about 300.
Considering you want the factorization of n in factors of a and b, then you just need to factorize the two possible ways and check which one gives you the minimal remainder.
So, you can something like this:
def factorize(a, b, n):
return n/a, (n%a)/b, (n%a)%b
def factorize_min(a, b, n):
na1, nb1, r1 = factorize(a, b, n)
nb2, na2, r2 = factorize(b, a, n)
return (na1, nb1) if r1 < r2 else (na2, nb2)
def factorize_min_list(a, b, n):
na, nb = factorize_min(a, b, n)
return [a]*na + [b]*nb
And use it like this:
for n in (6,10,12,18,20,24,26,28,30,32):
print factorize_min_list(6, 10, n)
This would give you:
[6]
[10]
[6, 6]
[6, 6, 6]
[10, 10]
[6, 6, 6, 6]
[6, 10, 10]
[6, 10, 10]
[10, 10, 10]
[10, 10, 10]
This is kind of change-making problem that might be effectively solved using dynamic programming. Note that if needed sum cannot be produced exactly (like 9 in your example) - check lower neighbor cells of the DP table.
This is more or less the coin problem. Above the Frobenius number all values can be built. Here we have 6 and 10 which aren't coprime. So we can divide by the greatest common divisor (2) to get 3 and 5 which are coprime. Then we get the Frobenius number 3*5 - 5 - 3 = 7. This means all even values > 14 can be built using 6 and 10 coins. The values are so few, that you could just make a list:
3 (% 3 = 0), coins (1, 0)
5 (% 3 = 2), coins (0, 1)
6 (% 3 = 0), coins (2, 0)
8 (% 3 = 2), coins (1, 1)
9 (% 3 = 0), coins (3, 0)
10 (% 3 = 1), coins (0, 2)
So the algorithm would be as follows:
divide input by 2
if it is smaller than 11 return the closest of the 6 values in the list
otherwise do input % 3, take corresponding configuration (8, 9 or 10), subtract it from input, divide by 3 and add the result to the 3 (i.e. 6) coins
Example for 32 (or 33):
32 / 2 = 16
16 >= 11
16 % 3 = 1, we take 10 (0, 2), (16 - 10) / 3 = 2, add it to 3 coins => (2, 2)
check: 2 * 6 + 2 * 10 = 32
The following is a C version of solving your problem with dynamic programming.
After you compile it you can run it with the total number of items as parameter
It will output the package sizes 10 and 6 separated by tabs
followed by their sum.
I took the algorithm from the german wikipedia page on the knapsack problem
https://de.m.wikipedia.org/wiki/Rucksackproblem
It is quoted in the comment at the beginning:
/*
U = { 10, 6 } n = 2
w = { 10, 6 }
v = { 2, 1 }
Eingabe: U, B, w, v wie oben beschrieben
R := [1…(n+1), 0…B]-Matrix, mit Einträgen 0
FOR i = n … 1
FOR j = 1 … B
IF w(i) <= j
R[i,j] := max( v(i) + R[i+1, j-w(i)], R[i+1,j]\
)
ELSE
R[i,j] := R[i+1,j]
Ausgabe: R[1,B]
*/
#include <stdlib.h>
#include <stdio.h>
int n = 2;
int main(int argc, char** argv) {
int w[3] = { -1, 10, 6 };
int v[3] = { -1, 10, 6 };
int B = atoi(argv[1]);
size_t sz = ((B+1)*3*sizeof(int));
int* R = malloc(sz);
memset(R, 0, sz);
for(int i = n; i > 0; i--) {
for(int j = 1; j <= B; j++) {
int b = R[i+1,j];
if(w[i] <= j) {
// max( v(i) + R[i+1, j-w(i)], R[i+1,j] )
int a = v[i] + R[i+1, j-w[i]];
R[i,j] = a>b?a:b;
} else {
R[i,j] = b;
}
}
}
int k = R[1,B];
while(R[1,k]>0){
int j = R[1,k];;
for(int i = n; i > 0; i--) {
int t = R[1,k-w[i]];
if(t == k - w[i]) {
j = w[i];
}
}
printf("%i\t",j);
k = k-j;
}
printf("\n%i\n", R[1,B]);
return 0;
}

Segregate even and odd places of an array in O(N) time and O(1) space

Given an array a = {1,2,3,4,5,6,7,8}
We should bring all the odd place elements(1,3,5,7) together and even place elements(2,4,6,8) together while preserving the order.
Input : [1,2,3,4,5,6,7,8].
Output : [1,3,5,7,2,4,6,8].
Update:(Example 2)
Example 2 : [3,54,77,86,45,2,25,100]
Output : [3, 77, 45, 25, 54, 86, 2, 100]
Restrictions: O(N) time complexity and O(1) space complexity.
My approach :
1. partitioning it like in (quicksort partition)
Problem : the order is not preserved. ( 1,7,3,5,4,6,2,8) -O(N) time complex
2. Putting the odd element to the rightful position and shifting all the other elements :
Problem : It comes to O(N) for each element and shifting takes another O(N). So the time complexity becomes O(N^2)
Is there a O(N) time complex and O(1) space complex solution possible?
See if you can generalize either of these permutation solutions based on cycles, noting that sorted indices would be I[] = {0,2,4,6,1,3,5,7}, I[1] = 2, I[2] = 4, I[4] = 1 , end of cycle. I[3] = 6, I[6] = 5, I[5] = 3, end of cycle. The issue here is if n is not known in advance, then even though I[i] can be calculated on the fly (I[i] = (2*i < n) ? 2*i : (2*i-n) | 1; ), the issue is keeping track of which cycles have already been processed, which could require O(n) space.
For 8 elements, it's two cycles, 3 elements each:
0 1 2 3 4 5 6 7
I[] = 0 2 4 6 1 3 5 7
t = a[1] 2
a[1] = a[2] 1 3 3 4 5 6 7 8
a[2] = a[4] 1 3 5 4 5 6 7 8
a[4] = t 1 3 5 4 2 6 7 8
t = a[3] 4
a[3] = a[6] 1 3 5 7 2 6 7 8
a[6] = a[5] 1 3 5 7 2 6 6 8
a[5] = t 1 3 5 7 2 4 6 8
for 12 elements, it's just one cycle of 10 elements
0 1 2 3 4 5 6 7 8 9 10 11
I[] = 0 2 4 6 8 10 1 3 5 7 9 11
t = a[ 1] 2
a[ 1] = a[ 2] 1 3 3 4 5 6 7 8 9 10 11 12
a[ 2] = a[ 4] 1 3 5 4 5 6 7 8 9 10 11 12
a[ 4] = a[ 8] 1 3 5 4 9 6 7 8 9 10 11 12
a[ 8] = a[ 5] 1 3 5 4 9 6 7 8 6 10 11 12
a[ 5] = a[10] 1 3 5 4 9 11 7 8 6 10 11 12
a[10] = a[ 9] 1 3 5 4 9 11 7 8 6 10 10 12
a[ 9] = a[ 7] 1 3 5 4 9 11 7 8 6 8 10 12
a[ 7] = a[ 3] 1 3 5 4 9 11 7 4 6 8 10 12
a[ 3] = a[ 6] 1 3 5 7 9 11 7 4 6 8 10 12
a[ 6] = t 1 3 5 7 9 11 2 4 6 8 10 12
For 27 elements, it's 3 cycles, starting at a[1] (19 elements), a[3] (6 elements), and a[9] (2 elements).
This is a partial answer only.
Here's the executable pseudocode for the first half of the array:
def magic_swap(arr):
mid = len(arr) / 2 + (1 if len(arr) % 2 == 1 else 0)
for i in range(1, mid):
arr[i], arr[i*2] = arr[i*2], arr[i]
The second half is the tricky part... I will update this answer if I ever figure out it.
For people who want to figure this out, here's the results for the first few array sizes:
Note that arrays of size n and n+1, when n is odd, always have the same sequence of swaps in this approach.
[1, 2]
[1, 3, 2]
[1, 3, 2, 4]
[1, 3, 5, 4, 2]
[1, 3, 5, 4, 2, 6]
[1, 3, 5, 7, 2, 6, 4]
[1, 3, 5, 7, 2, 6, 4, 8]
[1, 3, 5, 7, 9, 6, 4, 8, 2]
[1, 3, 5, 7, 9, 6, 4, 8, 2, 10]
[1, 3, 5, 7, 9, 11, 4, 8, 2, 10, 6]
[1, 3, 5, 7, 9, 11, 4, 8, 2, 10, 6, 12]
[1, 3, 5, 7, 9, 11, 13, 8, 2, 10, 6, 12, 4]
[1, 3, 5, 7, 9, 11, 13, 8, 2, 10, 6, 12, 4, 14]
[1, 3, 5, 7, 9, 11, 13, 15, 2, 10, 6, 12, 4, 14, 8]
[1, 3, 5, 7, 9, 11, 13, 15, 2, 10, 6, 12, 4, 14, 8, 16]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 10, 6, 12, 4, 14, 8, 16, 2]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 10, 6, 12, 4, 14, 8, 16, 2, 18]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 6, 12, 4, 14, 8, 16, 2, 18, 10]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 6, 12, 4, 14, 8, 16, 2, 18, 10, 20]
The problem seems rather hard with O(1) and O(n) restrictions.
Best match I can find is an article Stable minimum space partitioning
in linear time, where they propose a solution for slightly more general problem. However, their algorithm is complex and (IMHO) not applicable in practice.
Unless it is a theoretical question, I suggest to relax restrictions to O(logN) and O(NlogN) respectively, and use simple 'stable partitioning' algorithm (updated):
#inplace reverse block [begin,end) in list l
#O(|end-begin|)
def reverse(l, begin, end):
p = begin
q = end - 1
while p < q:
l[p], l[q] = l[q], l[p]
p = p + 1
q = q - 1
#inplace swaps blocks [begin, mid) and [mid, end) and
#returns a new pivot (dividing point)
#O(|end-begin|)
def swap(l, begin, mid, end):
reverse(l, begin, mid)
reverse(l, mid, end)
reverse(l, begin, end)
return (end - (mid - begin))
#recursive partitioning: partition block [begin, end) into
#even and odd blocks, returns pivot (dividing point)
##O(|end-begin|*log|end-begin|)
def partition(l, begin, end):
if end - begin > 1:
mid = (begin + end) / 2
p = partition(l, begin, mid)
q = partition(l, mid, end)
mid = swap(l, p, mid, q)
return mid
return begin if l[begin] % 2 == 0 else begin + 1
def sort(l):
partition(l, 0, len(l))
return l
print sort([1,2,3,4,5,6,7,8])
Update. For an updated question, article is a direct match. So unless there is some trick which abuses the numerical nature of elements, we don't have a simple solution to that problem.
Here is a python program that works. No extra space needed, only one pass through the array.
You don't require the numbers to be sorted or to keep the original order; just put them together.
arr = [1,3,2,4,5,6,3,55,66,77,21,4,5]
iFirst = 0
iLast = len(arr)-1
print arr
while (iFirst < iLast):
while ((arr[iFirst] & 1)==1): # find next even at the front
iFirst += 1
while ((arr[iLast] & 1)==0): # find next odd at the back
iLast -= 1
k = arr[iLast] # exchange them
arr[iLast] = arr[iFirst]
arr[iFirst] = k
iFirst += 1
iLast -= 1
print arr
Here is the output.
[1, 3, 2, 4, 5, 6, 3, 55, 66, 77, 21, 4, 5]
[1, 3, 5, 21, 5, 77, 3, 66, 55, 6, 4, 4, 2]

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

Resources