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.
Related
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?
I have been given this assignment for school:
You have been given a puzzle consisting of a row of squares each containing an integer, like this:
6, 4, 1, 3, 3, 1, 4, 1, 1, 0
The bold number on the initial square is a marker that can move to other squares along the row.
At each step in the puzzle, you may move the marker the number of squares indicated by the integer in the square it currently occupies.
The marker may move either left or right along the row but may not move past either end.
The goal of the puzzle is to move the marker to the 0 at the far end of the row.
The program checks the index you are currently on, and moves either left or right a number of squares based on the integer at that index in the array. It decides this based on the bounds of the array, if it can't move the required number of squares to the left it will move to the right, and vice versa.
In this program, the first move has to be 6 to the right, since it cannot move 6 spaces left without going out of bounds. Then, it has to move 4 left since it cant move 4 right, and it goes on like that.
I have got this working, and printing the process is worth extra credit. I have it printing the process, but it is out of order.
here is my code:
def self.solvable(start, board)
return false if start>= board.length || start<0
return false if ##infinite[start] == -1
return true if board[start] == 0
##infinite[start] = -1
if solvable(board[start] + start, board)
puts "Shifted right " + board[start].to_s + " spaces, from index " + start.to_s + " to index " + (board[start] + start).to_s
return true
else
puts "Shifted left " + board[start].to_s + " spaces, from index " + start.to_s + " to index " + (start - board[start]).to_s
end
return solvable(start - board[start], board)
end
print "Enter an array of numbers: "
input = gets.chomp!
board = input.each_char.map(&:to_i)
##infinite = input.each_char.map(&:to_i)
puts solvable(0, board)
I do not understand how to make the code output in a more logical order, printing 6 spaces right, 4 spaces left, etc... instead of the current output, which is:
Shifted left 4 spaces, from index 6 to index 2
Shifted left 3 spaces, from index 3 to index 0
Shifted left 1 spaces, from index 2 to index 1
Shifted left 1 spaces, from index 5 to index 4
Shifted right 1 spaces, from index 8 to index 9
Shifted right 1 spaces, from index 7 to index 8
Shifted right 3 spaces, from index 4 to index 7
Shifted right 4 spaces, from index 1 to index 5
Shifted right 6 spaces, from index 0 to index 6
Assumption
I assume the game begins at position 0. Each move increases or decreases the position by an integal amount. The objective is to get back to position 0 after the first move has been made.
We are given an array, arr, of integers and a mapping from positions to indices of the array. For position p the index of arr is given by p % arr.size.
If we are at position p we obtain the value may move to position p + n or p - n, where
n = arr[p % arr.size]
For the example given:
arr = [6, 4, 1, 3, 3, 1, 4, 1, 1, 0]
(arr.size #=> 10) and p initially zero,
n = arr[0 % 10]
#=> arr[0] => 6
so we may move to position +6 or -6. If we move to +6, we calculate
n = arr[6 % 10]
#=> 4
so we may move to position 6+4 #=> 10 or 6-4 #=> 2. If we move to -6, we calculate
n = arr[-6 % 10]
#=> 3
so we may move to position -6-3 #=> -9 or -6+3 #=> -3.
Note that arr[9] #=> 0 can be regarding as an absorbing state.
Code
The method I've chosen to use is recursive.
def onward_to_zero(arr, pos=0)
n = arr[pos % arr.size]
return [] if n.zero?
return [-n] if (pos-n).zero?
return [n] if (pos+n).zero?
if rand < 0.5
rv = onward_to_zero(arr, pos-n)
return [-n] + rv unless rv.empty?
rv = onward_to_zero(arr, pos+n)
return [n] + rv unless rv.empty?
else
rv = onward_to_zero(arr, pos+n)
return [n] + rv unless rv.empty?
rv = onward_to_zero(arr, pos-n)
return [-n] + rv unless rv.empty?
end
[]
end
I believe it can be proven that there is always a path back to zero, but I have not given thought to a proof.
Examples
arr = [6, 4, 1, 3, 3, 1, 4, 1, 1, 0]
onward_to_zero(arr)
#=> [-6, 3, 1, -1, 1, -1, -1, 4]
# pos % 10 0 4 7 8 7 8 7 6
# pos-> 0 -6 -3 -2 -3 -2 -3 -4 0
arr = [3, 2, 4, 1, 3, 6, 2]
onward_to_zero(arr)
#=> [3, -1, 4, 2, 2, 1, -3, 2, -1, -4, -6, -2, 3]
# pos-> 3 2 6 8 10 11 8 10 9 5 -1 -3 0
arr = [3, 3]
onward_to_zero(arr)
#=> [-3, 3]
# pos-> -3 0
arr = [7, 26, 33, 18, 7, 13]
onward_to_zero(arr)
#=> [-7, -13, 7, 13]
# pos-> -7 -20 -13 0
Discussion
Notice that if rand < 0.5 causes me to consider a reduction in the position before an increase in the position roughly half the time. If I were always to consider a reduction before an increase, or vice-versa, I could easily get a stack level too deep error.
Even with that probability mechanism, however, the method gives quite varied results and could still result in a stack level too deep error. Here are the results I obtained by running the first example 10 times.
[6, -4, 1, -3]
[-6, 3, 1, -1, -1, 4]
[6, 4, 6, 4, 6, 4, 6, 4, 6,..., -1, -1, 4] (824 elements)
[6, 4, -6, -3, 4, 1, -4, -1,..., -4, 1, -3] (386 elements)
[-6, 3, 1, -1, -1, 4]
[-6, -3, 4, 1, 4]
[-6, 3, 1, -1, 1, -1, -1, 4]
[-6, -3, -4, -1, -4, 1, -3, 6, 4, 6, 4]
[-6, -3, -4, 1, -1, -1, -4, -1, 4, 1, 4, 6, 4]
[-6, 3, -1, 4]
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]
I created this basic class right here:
class TimePeriod
MONTHS_PER_QUARTER = 3
QUARTER_RANGE = {
0 => [1,3],
1 => [4,6],
2 => [7,9],
3 => [10,12]
}
def self.quarter(month_num)
(month_num - 1) / MONTHS_PER_QUARTER
end
def self.quarter_range(month_num)
quarter = quarter month_num
t1,t2 = QUARTER_RANGE[quarter]
[Time.parse(Date::MONTHNAMES[t1]).beginning_of_month, Time.parse(Date::MONTHNAMES[t2]).end_of_month]
end
end
It gives me a time range for a quarter, given a month provided as an integer:
> TimeUtils.quarter_range(Time.now.month)
=> [2015-04-01 00:00:00 -0400, 2015-06-30 23:59:59 -0400]
So it works. However, I have cheated. I had difficulty finding the start and end, given, let's say, the month 6. So I hardcoded the values in the QUARTER_RANGE constant. I want to be able to remove that QUARTER_RANGE constant and find the beginning and end (e.g. [4,6]) without it.
So for example, if the input 3 (March),6 (June),9(September),12(December) is passed, I will know its the end of the quarter, using modulus arithmetic:
3 % 3
=> 0
6 % 3
=> 0
9 % 3
=> 0
12 % 3
=> 0
But the tricky part is given let's say 5 (May), how can I return [4,6]?
You can get the start of the quarter like this:
def qtr_start(mon)
mon - (mon - 1) % MONTHS_PER_QUARTER
end
qtr_start(9) # => 7
The end of the quarter is just that plus two:
def qtr_end(mon)
qtr_start(mon) + 2
end
qtr_end(9) # => 9
Put them together:
def qtr_start_end(mon)
start = mon - (mon - 1) % MONTHS_PER_QUARTER
[ start, start + 2 ]
end
(1..12).each do |mon|
start_end = qtr_start_end(mon)
puts "Month #{mon} is in quarter #{start_end.inspect}"
end
# => Month 1 is in quarter [1, 3]
# Month 2 is in quarter [1, 3]
# Month 3 is in quarter [1, 3]
# Month 4 is in quarter [4, 6]
# Month 5 is in quarter [4, 6]
# Month 6 is in quarter [4, 6]
# Month 7 is in quarter [7, 9]
# Month 8 is in quarter [7, 9]
# Month 9 is in quarter [7, 9]
# Month 10 is in quarter [10, 12]
# Month 11 is in quarter [10, 12]
# Month 12 is in quarter [10, 12]
(1..12).each do |m|
low = 3*((m-1)/3) + 1
p m, [low, low+2]
end
result:
1
[1, 3]
2
[1, 3]
3
[1, 3]
4
[4, 6]
5
[4, 6]
6
...
Well, I'm not sure why you want it but if you want to use modulo this should work out how you want:
month = some_num
quarter_range = []
if month%3 == 0
# end of quarter
quarter_range = [month-2, month]
elsif month%3 == 1
# beginning of quarter
quarter_range = [month, month+2]
else
# middle of quarter
quarter_range = [month-1, month+1]
end
return quarter_range
You could do the following:
MONTHS_PER_PERIOD = 3
PERIODS = (1..12).step(MONTHS_PER_PERIOD).map do |m|
m..(m+MONTHS_PER_PERIOD-1)
end
#=> [1..3, 4..6, 7..9, 10..12]
def month_to_period(m)
PERIODS.find { |p| p.cover?(m) }
end
(1..12).each { |m| puts month_to_period(m) }
1..3
1..3
1..3
4..6
4..6
4..6
7..9
7..9
7..9
10..12
10..12
10..12
MONTHS_PER_PERIOD = 2
PERIODS = (1..12).step(MONTHS_PER_PERIOD).map do |m|
m..(m+MONTHS_PER_PERIOD-1)
end
#=> [1..2, 3..4, 5..6, 7..8, 9..10, 11..12]
(1..12).each { |m| puts month_to_period(m) }
1..2
1..2
3..4
3..4
5..6
5..6
7..8
7..8
9..10
9..10
11..12
11..12
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