what is the way to find if array contain Arithmetic progression (sequence) - arrays

i have sorted array of numbers like
1, 4, 5 , 6, 8
what is the way to find out if this array contain Arithmetic progression (sequence) ?
like in this example
4,6,8
or
4,5,6
remark : the minimum numbers in sequence is 3

You can solve this recursively, by breaking it into smaller problems, which are:
Identify the pairs {1,4},{1,5}...{6,8}
For each pair, look for sequences with the same interval
First create the scaffolding to run the problems:
Dim number(7) As Integer
Dim result() As Integer
Dim numbers As Integer
Sub FindThem()
number(1) = 1
number(2) = 4
number(3) = 5
number(4) = 6
number(5) = 8
number(6) = 10
number(7) = 15
numbers = UBound(number)
ReDim result(numbers)
Dim i As Integer
For i = 1 To numbers - 2
FindPairs i
Next
End Sub
Now iterate over the pairs
Sub FindPairs(start As Integer)
Dim delta As Integer
Dim j As Integer
result(1) = number(start)
For j = start + 1 To numbers
result(2) = number(j)
delta = result(2) - result(1)
FindMore j, 2, delta
Next
End Sub
Finding sequences as you go
Sub FindMore(start As Integer, count As Integer, delta As Integer)
Dim k As Integer
For k = start + 1 To numbers
step = number(k) - result(count)
result(count + 1) = number(k) ' should be after the if statement
' but here makes debugging easier
If step = delta Then
PrintSeq "Found ", count + 1
FindMore k, count + 1, delta
ElseIf step > delta Then ' Pointless to search further
Exit Sub
End If
Next
End Sub
This is just to show the results
Sub PrintSeq(text As String, count As Integer)
ans = ""
For t = 1 To count
ans = ans & "," & result(t)
Next
ans = text & " " & Mid(ans, 2)
Debug.Print ans
End Sub
Results
findthem
Found 1,8,15
Found 4,5,6
Found 4,6,8
Found 4,6,8,10
Found 5,10,15
Found 6,8,10
Edit: Oh, and of course, the array MUST be sorted!
HTH

First, I will assume that you only want arithmetic sequences of three terms or more.
I would suggest checking each number a[i] as the start of an arithmetic sequence, and a[i+n] as the next one.
Now that you have the first two terms in your series, you can find the next. In general, if x is your first term and y is your second, your terms will be x + i*(y-x), with the first term at i = 0. The next term will be x + 2*(y-x). Search your array for that value. If that value is in your array, you have an arithmetic sequence of three items or more!
You can continue with i=3, i=4, etc. until you reach one that is not found in your array.
If l is the size of your array, do this for all i from 0 to l-2, and all n from 0 to l-i-1
The only major caveat is that, in the example, this will find both sequences 4,6,8 as well as 6,8. Technically, both of them are arithmetic sequences in your series. You will have to more specifically define what you want there. In your case, it might be trivial to just check and eliminate all progressions that are totally contained inside others.

The general idea is to pick an element as your a_1, then any element after that one as your a_2, compute the difference and then see if any other elements afterwards that match that difference. As long as there are at least 3 elements with the same difference, we consider it a progression.
progression (A, n)
for i = 1 ... n - 2
a_1 = A[i]
for j = i + 1 ... n - 1
a_2 = A[j]
d = a_2 - a_1
S = [ i, j ]
for k = j + 1 ... n
if ( d == ( a[k] - a[S.last] ) )
/* Append the element index to the sequence so far. */
S += k
if ( |s| > 2 )
/* We define a progression to have at least 3 numbers. */
return true
return false
You can modify the algorithm to store each set S before it is lost, to compute all the progressions for the given array A. The algorithm runs in O(n^3) assuming appending to and getting the last element of the set S are in constant time.
Although I feel like there might be a more efficient solution...

Certainly not the optimal way to solve your problem, but you can do the following:
Iterate through all pairs of numbers in your array - each 2 numbers fully define arithmetic sequence if we assume that they're 1st and 2nd progression members. So knowing those 2 numbers you can construct further progression elements and check if they're in your array.
If you want just find 3 numbers forming arithmetic progression then you can iterate through all pairs of non-adjacent numbers a[i] and a[j], j > i+1 and check if their arithmetic mean belongs to array - you can do that using binary search on interval ]i,j[.

Here's the code in Swift 4:
extension Array where Element == Int {
var isArithmeticSequence: Bool {
let difference = self[1] - self[0]
for (index, _) in self.enumerated() {
if index < self.count-1 {
if self[index + 1] - self[index] != difference {
return false
}
}
}
return true
}
var arithmeticSlices: [[Int]] {
var arithmeticSlices = [[Int]]()
var sliceSize = 3
while sliceSize < self.count+1 {
for (index, _) in self.enumerated() {
if (index + sliceSize-1) <= self.count - 1 {
let currentSlice = Array(self[index...index + sliceSize-1])
if currentSlice.isArithmeticSequence {
arithmeticSlices.append(currentSlice)
}
}
}
sliceSize+=1
}
return arithmeticSlices
}
}
let A = [23, 24, 98, 1, 2, 5]
print(A.arithmeticSlices) // []
let B = [4, 7, 10, 4,5]
print(B.arithmeticSlices) //[[1, 2, 3], [2, 3, 4], [3, 4, 5], [1, 2, 3, 4], [2, 3, 4, 5], [1, 2, 3, 4, 5]]
let C = [4, 7, 10, 23, 11, 12, 13]
print(C.arithmeticSlices) // [[4, 7, 10], [11, 12, 13]]

Related

What is the difference between enumerate and range(len(list)) in python?

Can someone tell me why the two code below give me different results? I was under the impression that the enumerate and range(len(list)) both are iterable.
Code: Trying to find the equilibrium index of an array
def equisum (arr):
tsum = sum(arr)
lsum = 0
num = len(arr)
for i in range(num):
tsum -= num
if lsum == tsum:
return i
lsum += num
return -1
arr = [-7, 1, 5, 2, -4, 3, 0]
print (equisum (arr))
Result : -1
def equisum (arr):
tsum = sum(arr)
lsum = 0
for i, num in enumerate(arr):
tsum -= num
if lsum == tsum:
return i
lsum += num
return -1
arr = [-7, 1, 5, 2, -4, 3, 0]
print (equisum (arr))
Result : 3 (the correct answer)
range(num) will give the values 0, 1, 2....
enumerate(arr) will give the values (0, -7), (1, 1), (2, 5)... where the first value is the index and the second value is value of arr at that index.
Your second function should give the correct answer because it subtracts the value of arr[i] rather than just i.
range() is used for getting the sequence of numbers. For example if you give range(10), it will give numbers from 0 to 9.
Here, as you are using range, you are calculating the numbers wrong and finally the default -1 is being returned.
While in enumerate(), it returns both index and actual element from the list.
by the way, if you are using VS Code for programming, make use of the debug feature. It will help to identify such issues much faster.

Find an algorithm to sort an array given its status after sorting

Let A be an array with n elements. A is not sorted, nonetheless, after sorting the array, the difference between any two adjacent elements would be either k1, k2 or k3.
It should be noted that k1, k2 and k3 are not given, and all of them are natural!
For example, given the array:
A = { 25, 7, 5, 9, 32, 23, 14, 21}
After sorting the array, we would get -
A = { 5, 7, 9, 14, 21, 23, 25, 32}
The difference between the first pair (5, 7) is 2; so k1=2, the difference between the third pair (9,14) is 5, so k2=5, whereas the difference between the fourth pair (14, 21) is 7, so k3=7. The difference between other adjacent pairs is also 2, 5 and 7.
The algorithm for sorting the array should be as best as possible (obviously below O(nlogn)).
I managed to answer a similar question where the difference between any two adjacent elements was either k, 2k or 3k, where k is real. But I couldn't find an appropriate algorithm following a similar method, by finding k, dividing by it and doing bucket sort.
By finding the minimum and second minimum we can find one of the k's. But k could be n2 — so finding the maximum does not help either... I am really lost!
Disclaimer: This question has been asked before, but no answer was given to the problem, and the question was not easy to understand.
Here is a O(n) that only doesn't look efficient.
The idea is simple. Given the minimum element and a list of values for k, you construct the biggest sorted set with the values of k that you already have found, find the smallest missing thing not in the set, and find a new value of k. If there are K values of k, this operation is O((1+K) * n).
Repeating this K times is therefore O((1+K)^2 * n).
In our case K is constant, so we get O(n).
Here it is in Python.
def special_sort (array):
# special cases first.
if 0 == len(array):
return array
elif 1 == len(array):
return array
elif 2 == len(array):
return [min(array), max(array)]
min_value = min(array)
values_of_k = []
leftovers = array
while len(leftovers):
values_of_k = sorted(values_of_k)
values = set(array)
sorted_array = [min_value]
values.remove(min_value)
found = True
while found:
found = False
for k in values_of_k:
if sorted_array[-1] + k in values:
found = True
sorted_array.append(sorted_array[-1] + k)
values.remove(sorted_array[-1])
break
leftovers = list(values)
if 0 == len(leftovers):
return sorted_array
else:
first_missing = min(leftovers)
# Find the first element of the array less than that.
i = -1
while i+1 < len(sorted_array) and sorted_array[i+1] < first_missing:
i = i+1
values_of_k.append(first_missing - sorted_array[i])
print(special_sort([25, 7, 5, 9, 32, 23, 14, 21]))

What is the smallest jump I can make to move through a range, when all jumps are the same length and some positions cannot be landed on?

Working through CodeFights. This is problem 4 on level 5 https://codefights.com/arcade/intro/level-5/XC9Q2DhRRKQrfLhb5 :
You are given an array of integers representing coordinates of
obstacles situated on a straight line.
Assume that you are jumping from the point with coordinate 0 to the
right. You are allowed only to make jumps of the same length
represented by some integer.
Find the minimal length of the jump enough to avoid all the obstacles.
Example
For inputArray = [5, 3, 6, 7, 9], the output should be
avoidObstacles(inputArray) = 4.
Check out the image below for better understanding:
Input/Output
[time limit] 4000ms (rb) [input] array.integer inputArray
Non-empty array of positive integers.
Constraints: 2 ≤ inputArray.length ≤ 10, 1 ≤ inputArray[i] ≤ 40.
[output] integer
The desired length.
The natural method for making this happen seems like it would be step. Here is my code:
def avoidObstacles(arr)
jumps = (arr.min..arr.max+1).to_a - arr
full_map = (0..arr.max+1)
jumps.each do |j|
return j if (full_map.step(j).to_a & arr).empty?
end
end
A clearer way to write this:
def avoidObstacles(arr)
jumps = (arr.min..arr.max+1).reject{|n| arr.include?(n)}
full_map = (0..arr.max+1)
jumps.each do |j|
return j if full_map.step(j).none?{|n|arr.include?(n)}
end
end
I pass all of the visible tests given on the website:
Input: inputArray: [5, 3, 6, 7, 9] Expected Output: 4
Input: inputArray: [2, 3] Expected Output: 4
Input: inputArray: [1, 4, 10, 6, 2] Expected Output: 7
But I get tripped up on one of the hidden tests. I borrowed a solution from another user, which works in all cases:
def avoidObstacles a
obs = a.each_with_object(Hash.new(false)){|v, h| h[v]=true}
m = a.max
(1..m+1).each do |j|
return j if (0...m/j+1).all?{ |i| obs[i*j] == false }
end
m
end
I'm not quite sure where this borrowed solution succeeds and mine fails.
Thanks ahead of time for the help. I'm still quite new to coding and appreciate your time.
avoidObstacles [3,5,7] #=> 4
but it should be 2. You want
def avoid_obstacles(arr)
return nil if arr.empty? or arr.max == 1
jumps = (2..arr.max+1).to_a - arr
full_map = (0..arr.max+1)
jumps.each do |j|
return j if (full_map.step(j).to_a & arr).empty?
end
end
avoid_obstacles [3,5,7]
#=> 2
I changed the name of the method because the Ruby convention is to use snake-case for the names of methods and variables.
The other person's solution works because it starts the search at j = 1. (It could have started at j=2 because j = 1 will always fail.
I tried this in Java using the input constraints given (so did not use input validation)
int avoidObstacles(int[] inputArray) {
Arrays.sort(inputArray);
//start from 2 because jump length 1 will always fail
int minJump=2;
while(validateJumpValue(inputArray, minJump)){
minJump++;
}
return minJump;
}
//check if all the successive jumps can avoid touching obstacles
boolean validateJumpValue(int[] arr, int jump){
int successiveJump=jump;
while(Arrays.binarySearch(arr, successiveJump)<0 && successiveJump <= arr[arr.length-1]) {
successiveJump+=jump;
}
return successiveJump<=arr[arr.length-1];
}
Try this:
def avoidObstacles(inputArray):
obs = sorted(inputArray)
jump_dist = 1
obstacle_hit = True
while(obstacle_hit):
obstacle_hit = False
jump_dist += 1
for i in range(0, len(obs)):
#### 3%4 and 5%4 and 6%4 and 7%4 and 9%4 =! 0
if obs[i] % jump_dist == 0:
obstacle_hit = True
break
return jump_dist

How do I combine the coordinate pairs of an array into a single index?

I have an array
A = [3, 4; 5, 6; 4, 1];
Is there a way I could convert all coordinate pairs of the array into linear indices such that:
A = [1, 2, 3]'
whereby (3,4), (5,6), and (4,1) are represented by 1, 2, and 3, respectively.
Many thanks!
The reason I need is because I need to loop through array A such that I could make use of each coordinate pairs (3,4), (5,6), and (4,1) at the same time. This is because I will need to feed each of these pairs into a function so as to make another computation. See pseudo code below:
for ii = 1: length(A);
[x, y] = function_obtain_coord_pairs(A);
B = function_obtain_fit(x, y, I);
end
whereby, at ii = 1, x=3 and y=4. The next iteration takes the pair x=5, y=6, etc.
Basically what will happen is that my kx2 array will be converted to a kx1 array. Thanks for your help.
Adapting your code, what you want was suggested by #Ander in the comments...
Your code
for ii = 1:length(A);
[x, y] = function_obtain_coord_pairs(A);
B = function_obtain_fit(x, y, I);
end
Adapted code
for ii = 1:size(A,1);
x = A(ii, 1);
y = A(ii, 2);
B = function_obtain_fit(x, y, I); % is I here supposed to be ii? I not defined...
end
Your unfamiliarly with indexing makes me think your function_obtain_fit function could probably be vectorised to accept the entire matrix A, but that's a matter for another day!
For instance, you really don't need to define x or y at all...
Better code
for ii = 1:size(A,1);
B = function_obtain_fit(A(ii, 1), A(ii, 2), I);
end
Here is a corrected version for your code:
A = [3, 4; 5, 6; 4, 1];
for k = A.'
B = function_obtain_fit(k(1),k(2),I)
end
By iterating directly on A you iterate over the columns of A. Because you want to iterate over the rows we need to take A.'. So if we just display k it is:
for k = A.'
k
end
the output is:
k =
3
4
k =
5
6
k =
4
1

Given two arrays A and B, how to get B values which are the closest to A

Suppose I have two arrays ordered in an ascending order, i.e.:
A = [1 5 7], B = [1 2 3 6 9 10]
I would like to create from B a new vector B', which contains only the closest values to A values (one for each).
I also need the indexes. So, in my example I would like to get:
B' = [1 6 9], Idx = [1 4 5]
Note that the third value is 9. Indeed 6 is closer to 7 but it is already 'taken' since it is close to 4.
Any idea for a suitable code?
Note: my true arrays are much larger and contain real (not int) values
Also, it is given that B is longer then A
Thanks!
Assuming you want to minimize the overall discrepancies between elements of A and matched elements in B, the problem can be written as an assignment problem of assigning to every row (element of A) a column (element of B) given a cost matrix C. The Hungarian (or Munkres') algorithm solves the assignment problem.
I assume that you want to minimize cumulative squared distance between A and matched elements in B, and use the function [assignment,cost] = munkres(costMat) by Yi Cao from https://www.mathworks.com/matlabcentral/fileexchange/20652-hungarian-algorithm-for-linear-assignment-problems--v2-3-:
A = [1 5 7];
B = [1 2 3 6 9 10];
[Bprime,matches] = matching(A,B)
function [Bprime,matches] = matching(A,B)
C = (repmat(A',1,length(B)) - repmat(B,length(A),1)).^2;
[matches,~] = munkres(C);
Bprime = B(matches);
end
Assuming instead you want to find matches recursively, as suggested by your question, you could either walk through A, for each element in A find the closest remaining element in B and discard it (sortedmatching below); or you could iteratively form and discard the distance-minimizing match between remaining elements in A and B until all elements in A are matched (greedymatching):
A = [1 5 7];
B = [1 2 3 6 9 10];
[~,~,Bprime,matches] = sortedmatching(A,B,[],[])
[~,~,Bprime,matches] = greedymatching(A,B,[],[])
function [A,B,Bprime,matches] = sortedmatching(A,B,Bprime,matches)
[~,ix] = min((A(1) - B).^2);
matches = [matches ix];
Bprime = [Bprime B(ix)];
A = A(2:end);
B(ix) = Inf;
if(not(isempty(A)))
[A,B,Bprime,matches] = sortedmatching(A,B,Bprime,matches);
end
end
function [A,B,Bprime,matches] = greedymatching(A,B,Bprime,matches)
C = (repmat(A',1,length(B)) - repmat(B,length(A),1)).^2;
[minrows,ixrows] = min(C);
[~,ixcol] = min(minrows);
ixrow = ixrows(ixcol);
matches(ixrow) = ixcol;
Bprime(ixrow) = B(ixcol);
A(ixrow) = -Inf;
B(ixcol) = Inf;
if(max(A) > -Inf)
[A,B,Bprime,matches] = greedymatching(A,B,Bprime,matches);
end
end
While producing the same results in your example, all three methods potentially give different answers on the same data.
Normally I would run screaming from for and while loops in Matlab, but in this case I cannot see how the solution could be vectorized. At least it is O(N) (or near enough, depending on how many equally-close matches to each A(i) there are in B). It would be pretty simple to code the following in C and compile it into a mex file, to make it run at optimal speed, but here's a pure-Matlab solution:
function [out, ind] = greedy_nearest(A, B)
if nargin < 1, A = [1 5 7]; end
if nargin < 2, B = [1 2 3 6 9 10]; end
ind = A * 0;
walk = 1;
for i = 1:numel(A)
match = 0;
lastDelta = inf;
while walk < numel(B)
delta = abs(B(walk) - A(i));
if delta < lastDelta, match = walk; end
if delta > lastDelta, break, end
lastDelta = delta;
walk = walk + 1;
end
ind(i) = match;
walk = match + 1;
end
out = B(ind);
You could first get the absolute distance from each value in A to each value in B, sort them and then get the first unique value to a sequence when looking down in each column.
% Get distance from each value in A to each value in B
[~, minIdx] = sort(abs(bsxfun(#minus, A,B.')));
% Get first unique sequence looking down each column
idx = zeros(size(A));
for iCol = 1:numel(A)
for iRow = 1:iCol
if ~ismember(idx, minIdx(iRow,iCol))
idx(iCol) = minIdx(iRow,iCol);
break
end
end
end
The result when applying idx to B
>> idx
1 4 5
>> B(idx)
1 6 9

Resources