How to group consecutive integers in a scala array? - arrays

Let’s say I have an array like the following:
1 2 3 4 5 6 7 8 9 1 2 3 4 5 1 2 3 4
I want many sub-arrays of contiguous numbers whose sum of every contiguous pair is less than 10
1 2 3 4 5, 6, 7, 8, 9, 1 2 3 4 5 1 2 3 4
How do I code it in scala in a functional idiomatic way?
// example no. 1
>Array(1, 2, 3, 4, 5, 6)...???
res0: List(Array(1, 2, 3, 4, 5), Array(6))
// example no. 2
>Array(3, 8, 1, 9, 1, 3)...???
res1: List(Array(3), Array(8, 1), Array(9), Array(1, 3))

Doing a foldRight makes it easier to use head and tail to build the resulting List.
val grouped = Array(3,8,1,9,1,3).foldRight(List.empty[Array[Int]]){case (n,acc) =>
if (acc.isEmpty) List(Array(n))
else if (acc.head.head + n < 10) n +: acc.head :: acc.tail
else Array(n) :: acc
} // List(Array(3), Array(8, 1), Array(9), Array(1, 3))

This should work (although it's a very inefficient way):
def group(threshold: Int)(seq: Seq[Int]): Seq[Seq[Int]] =
seq.reverse.tails.find(_.sum < threshold) match {
case None => Nil
case Some(Nil) => Nil
case Some(subSeq) =>
subSeq.reverse +: group(threshold)(seq.drop(subSeq.size))
}
group(10)(Array(3, 8, 1, 9, 1, 3))
List(Array(3), Array(8, 1), Array(9), Array(1, 3))

Related

Need help filtering an array?

I am trying to remove odd numbers from an array.
arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
def remove_odd_nums(arr)
for x in arr
if x % 2 == 0
arr.delete(x)
end
end
end
print remove_odd_nums(arr)
# [1, 3, 5, 7, 10]
I can't seem to make this program work. The method works on the numbers except for the last one. What am I doing wrong?
You want to delete odd numbers but your program is deleting even numbers (x % 2 == 0 checks if x is an even number)
METHOD 1:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
arr.delete_if &:odd?
print arr
delete_if iterates by incrementing the index for arr, and deletes an element immediately after evaluating the block &:odd? with respect to the element. In other words, it is going through each element in array, and deleting the element if &:odd? is true.
&:odd?: a lambda function passing in an object to the odd? method, which returns true if the object is an odd number. Further explanations can be found what is the functionality of "&: " operator in ruby?
Note that method 1 actually MODIFIES the original array. For a way to create a new array of non-odd numbers, there is...
METHOD 2:
non_odds = arr.select{|i| not i.odd?}
TL;DR: don't modify an array while iterating it.
Let's see what's happening by printing the current value of x and arr inside the loop:
def remove_odd_nums(arr)
for x in arr
p x: x, arr: arr # <- debug output
if x % 2 == 0
arr.delete(x)
end
end
end
remove_odd_nums([1, 2, 3, 4, 5, 6, 7, 8, 10])
Output:
{:x=>1, :arr=>[1, 2, 3, 4, 5, 6, 7, 8, 10]}
{:x=>2, :arr=>[1, 2, 3, 4, 5, 6, 7, 8, 10]}
{:x=>4, :arr=>[1, 3, 4, 5, 6, 7, 8, 10]}
{:x=>6, :arr=>[1, 3, 5, 6, 7, 8, 10]}
{:x=>8, :arr=>[1, 3, 5, 7, 8, 10]}
The first two x values are as expected: 1 and 2. But then it moves on to 4, skipping 3. It also skips 5, 7, and 10. But why?
It's because you are modifying the array while iterating it. Think of the for loop as someone pointing to an element at a specific position. Initially it looks like this:
1 2 3 4 5 6 7 8 10 <- array
^ <- element
for then moves on to the next element:
1 2 3 4 5 6 7 8 10
^
at this point x % 2 == 0 becomes true and 2 is deleted from the array:
1 3 4 5 6 7 8 10
^
for isn't aware of this change and simply moves on to the next element:
1 3 4 5 6 7 8 10
^
which is why we have unintentionally skipped 3. The same happens for 5 and 7.
When for finally reaches 8:
1 3 5 7 8 10
^
it is being deleted:
1 3 5 7 10
^
and for stops looping because it seems to have reached the array's end.
Hello Practical1 just to clarify why do you want to destroy objects and array?
In case you on want to filter array and only select even numbers , you can try a combination of Array#select and Integer#even? method helpers
arr = arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# select all even numbers in an array
arr.select(&:even?) # shorthand for arr.select {|number| number.even? }
will return even numbers
[0] 2,
[1] 4,
[2] 6,
[3] 8,
[4] 10
source:
Array#select https://apidock.com/ruby/Array/select
Integer#even? https://ruby-doc.org/core-1.8.7/Integer.html
Ruby has fabulous methods to modify arrays in place based on the logic in a block.
To arrive at an array with only odd numbers, you can either remove the elements that don't meet a test or keep the number that do meet a test. You can either return a new array or use one of the in place modification methods.
To remove undesired values, use either .reject for a new array or .reject! to modify an existing array in place.
Since we are removing, we would use {|e| e%2!=0} inside the block for odd numbers:
> [1,2,3,4,5,6,7,8,9,10].reject {|e| e%2!=0}
=> [2, 4, 6, 8, 10] # new array
> arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
> arr.reject! {|e| e%2!=0}
=> [2, 4, 6, 8, 10] # arr modified in place
Rather than a block, you can also use the odd? logical test for the same result:
> [1,2,3,4,5,6,7,8,9,10].reject &:odd?
=> [2, 4, 6, 8, 10]
Or, you can keep the values desired and other values will not be kept. You would use {|e| e%2==0} inside the block for even values. Or you can use &:even? instead of the block.
You can use .keep_if to return a new array:
> arr
=> [1, 2, 3, 4, 5, 6, 7, 8, 10]
> [1,2,3,4,5,6,7,8,9,10].keep_if {|e| e%2==0}
=> [2, 4, 6, 8, 10] # new array.
Or use .select! to modify in place:
> arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
=> [1, 2, 3, 4, 5, 6, 7, 8, 10]
> arr.select! {|e| e%2==0}
=> [2, 4, 6, 8, 10]
> arr
=> [2, 4, 6, 8, 10] # arr modified in place

Separating a matrix into sub-matrices in Fortran

Suppose I have a 2-D array such that the first column is composed of only two integers 1 and 2:
1 5 1 7 0.5
2 4 5 6 0.1
1 9 3 4 0.6
2 8 7 2 0.2
I want to separate two matrices out of this, such that the first column of each contains the same integer (so the first column of first matrix contains only integer 1, same goes for 2 in the second matrix).
So it would become:
1 5 1 7 0.5
1 9 3 4 0.6
and
2 4 5 6 0.1
2 8 7 2 0.2
I don't know exactly how to start. I was thinking of using the count at the beginning (well, because I have a way larger matrix with 10 different integers in the first column), then according to the counted number of each integer I construct the dimension of each [sub]matrix. After that, the only thing I could think of is the count(mask), and if the value is true it's then added to the matrix by if statement.
You can't have mixed types (integer and real) in the same array in Fortran, so I will suppose all data are real in the 2-dim array:
program split
implicit none
real, allocatable :: a(:, :), b(:, :)
integer :: i, ids = 10
integer, allocatable :: id(:), seq(:)
a = reshape([real :: 1, 5, 1, 7, 0.5, &
& 2, 4, 5, 6, 0.1, &
& 1, 9, 3, 4, 0.6, &
& 2, 8, 7, 2, 0.2], [5, 4])
seq = [(i, i = 1, size(a, 2))]
do i = 1, ids
print*, "i = ", i
! here we are creating a vector with all the line indices that start with i
! e.g. for i = 1 we get id = [1, 3], for i = 2 we get [2, 4], for i = 3 we get [], ...
id = pack(seq, a(1,:) == i)
! here we use a Fortran feature named vector-subscript
b = a(:, id)
print*, b
end do
end
If you want the first column(or any column) to be integer, you can declare it as a separated array, and use the same vector subscripts to gather the desired lines.

How to split single line input in ruby and store it as different variable and different datatype (i.e Integer/String/Array)

How to split single line input into multiple variable of different data type.
Example
3 2 3 1
Sample Output
n = 3 #Integer/FixNum
a = [2,3,1] #Array
To be more specific, I need
To get 3(n) times the a(input) dynamically
like,
ip -> 5 1 3 4 5 6
op -> n = 5 and a = [1,3,4,5,6]
ip -> 7 1 2 3 4 5 6 7
op -> n = 7 and a = [1,2,3,4,5,6,7]
What I tried
a,b = gets.split(" ").map(&:to_i) #it didn't not work
op -> a = 1, b = 2
You can use splat operator:
array = gets.split.map(&:to_i)
#=> [7, 1, 2, 3, 4, 5, 6, 7]
a, *b = array # <===== magic happens here
a #=> 7
b #=> [1, 2, 3, 4, 5, 6, 7]
b = gets.chomp.split(" ").map(&:to_i)
# => [7, 1, 2, 3, 4, 5, 6, 7]
a = b.shift
# => 7
b
# => [1, 2, 3, 4, 5, 6, 7]

Given an unsorted array, Find the maximum subtraction between two elements in the array

I've got this question from an Interview in Microsoft: Given an unsorted array, Find the maximum subtraction between two elements in the array is a way that:
(Index1, Index2) = arr[Index2] - arr[Index1]. Index1<Index2.
Example:
given the array: [1, 5, 3, 2, 7, 9, 4, 3] -> Output: (1,9)=8.
given the array: [4, 9, 2, 3, 6, 3, 8, 1] -> Output: (2,8)=6.
The naive solution works in O(n^2) times: Scan the first index for subtraction with all other indexes and save the max value, Continue to the next index and so on.
Is there any way to optimize this?
Fairly simple when you write it down. Rephrasing the problem, you want to find the largest element to the right of each element. Now given the first example, this is:
[1, 5, 3, 2, 7, 9, 4, 3]
=>
[9, 9, 9, 9, 9, 4, 3]
Now, notice the maximums array is just the cumulative maximums from the right. Given this property it is easy to construct an O(n) time algorithm.
Implementation in python:
def find_max(xs):
ys = []
cur_max = float('-inf')
for x in reversed(xs):
cur_max = max(x, cur_max)
ys.append(cur_max)
ys = ys[::-1][1:]
return max(y - x for x, y in zip(xs, ys))
We can also construct the maximums array lazily, doing so gives us O(1) memory, which is the best possible:
def find_max(xs):
cur_max = float('-inf')
cum_max = xs[-1]
for i in range(len(xs) - 2, -1, -1):
cur_max = max(cur_max, cum_max - xs[i])
cum_max = max(cum_max, xs[i])
return cur_max
I think this is correct and O(nlogn): Split in the middle and select from right the max, from left the min value. Also split the the other 2 quarters, if one of them gives bigger result continue on that branch recursively.
Second example:
4, 9, 2, 3| 6, 3, 8, 1 -> 2 and 8
4, 9| 2, 3, 6, 3, 8, 1 -> 4 and 8
4, 9, 2, 3, 6, 3| 8, 1 -> 2 and 8
So working on the right split:
4, 9, 2, 3, 6, 3, 8| 1 -> 2 and 1
Selecting the 2 and 8 option. It also works for the first example.

Best way to find a number in an array that's "out of order"?

I have an array of length 10 filled with numbers 0-9.
The numbers are (for the most part) in sequential order. However the number at the starting index can be any number, and whether the numbers are in ascending or descending order is unknown (the numbers wrap around once they hit the min/max number - 0 once it reaches 9, and vice-versa).
Exactly one of these numbers are not in order (as if it's been plucked out and randomly inserted back into the array).
Example:
[4, 3, 1, 0, 9, 8, 7, 2, 6, 5]
The number 2 at index 7 is out of order. The "gap" in numbers between indexes 1 and 2 is okay, and neither the number 3 or 1 is considered out of order.
What's the best way to pinpoint the index of the out-of-order number?
More examples - out of place numbers are marked with *:
[2, 3, *0, 4, 5, 6, 7, 8, 9, 1]
[5, 6, 7, 9, *8, 0, 1, 2, 3, 4]
[7, 6, 5, 4, 3, *8, 2, 1, 0, 9]
[0, *5, 1, 2, 3, 4, 6, 7, 8, 9]
[4, 3, *0, 2, 1, 9, 8, 7, 6, 5]
To find the number that is out-of-order you have look at every element in the array. So, you have to iterate over the entire array with complexity O(n).
When you loop through the array, you should
calculate the absolute value of the difference between the previous number and the current number.
calculate the absolute value of the difference between the current number and next number
If both the above differences are greater than 1 and not equal to n-1 (when the difference is n-1, that is the point where your array flips), then that is number that is out of order.
Look at every other element, and compute the differences.
If most differences are positive, the order is ascending. If most are negative, it's descending; it can be decided exactly like the other case and i will not examine it further.
Of course you need to wrap around and compute the diff between (N-1)th and 0th element, or whatever.
From now on look at the diffs modulo N.
If the diff is 2, this is the regular case of no extra or missing elements; ignore it.
If the diff is 3, an element was yanked from somewhere around here. But we are not looking for its old place, we are looking for its new place; ignore this too.
If the diff is 1, then the out of order element is between these numbers.
If you have any other diff, then you must have two of them next to each other. The out of order element is the one that produces both of these diffs.
In the case of two consecutive numbers swapped, either one can be considered out of order. The diffs produced will be either (1,3) or (3,1) next to each other. This method picks one of the two possible answers.
For the arrays in question:
array -> 2 3 0 4 5 6 7 8 9 1(2)
\ / \ / \ / \ / \ /
diffs -> -2 5 2 2 -7(=3 mod 10)
*
In further examples I will not state equality mod 10 to save space.
array -> 5 6 7 9 8 0 1 2 3 4(5)
\ / \ / \ / \ / \ /
diffs -> 2 1 3 2 2
*
array -> 7 6 5 4 3 8 2 1 0 9(7)
\ / \ / \ / \ / \ /
diffs -> -2 -2 -1 -2 -3
*
array -> 0 5 1 2 3 4 6 7 8 9(0)
\ / \ / \ / \ / \ /
diffs -> 1 2 3 2 2
*
array -> 4 3 0 2 1 9 8 7 6 5(4)
\ / \ / \ / \ / \ /
diffs -> -4 -9 -3 -2 -2
*
More examples:
array -> 0 2 1 3 4 5 6 7 8 9(0) swapped adjacent elements, case 1
\ / \ / \ / \ / \ /
diffs -> 1 3 2 2 2
*
array -> 0 1 3 2 4 5 6 7 8 9(0) swapped adjacent elements, case 2
\ / \ / \ / \ / \ /
diffs -> 3 1 2 2 2
*
array -> 0 2 3 4 5 6 7 1 8 9(0) element removed and inserted at odd pos
\ / \ / \ / \ / \ /
diffs -> 3 2 2 1 2
*
array -> 0 2 3 4 5 6 1 7 8 9(0) element removed and inserted at even pos
\ / \ / \ / \ / \ /
diffs -> 3 2 6 7 2
*
array -> 0 7 1 2 3 4 5 6 8 9(0) element removed and inserted at odd pos
\ / \ / \ / \ / \ /
diffs -> 1 2 2 3 2
*
array -> 0 1 7 2 3 4 5 6 8 9(0) element removed and inserted at even pos
\ / \ / \ / \ / \ /
diffs -> 7 6 2 3 2
*
The following contrived examples do not have a unique solution. You need to decide what happens in these cases:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9 // first item move to end
2, 1, 3, 4, 5, 6, 7, 8, 9, 0 // adjacent items swapped
For all other cases, luckily the telling trait is that the "out-of-order" item will be more than 1 away from both its neighbors (because #2 above).
for (i = 0; i < arr.length; i++) {
int priorIndex = (i-1) % arr.length;
int nextIndex = (i+1) % arr.length;
int diffToPriorValue = abs(arr[i] - arr[priorIndex]);
int diffToNextValue = abs(arr[i] - arr[nextIndex]);
if (diffToPriorValue > arr.length/2)
diffToPriorValue = arr.length - diffToPriorValue; // wrap-around
if (diffToNextValue > arr.length/2)
diffToNextValue = arr.length - diffToNextValue; // wrap-around
if (diffToPriorValue != 1 && diffToNextValue != 1)
return i;
return -1;
First I'll start with defining what is “out of order”:
Suppose we have a list of numbers A
If there exist A[i] in A,
Such that A[i-1] <= A[i] <= A[i+1], then A[i] is "in order"
Otherwise, A[i] is "out of order"
ALGORITHM:
FOR i: 1..SIZE(A) DO
PRINT " "
PRINT A[i]
IF A[i-1] <= A[i] <= A[i+1]
THEN
CONTINUE
ELSE
PRINT "*"
REMOVE A[i]
END-IF
END-FOR
TEST:
INPUT: { 2, 3, 0, 1, 2, 3, 5, 6, 7, 8, 9, 1 }
OUTPUT: { 2, 3, 3, 5, 6, 7, 8, 9 }
CONSOLE: 2 3 0* 1* 2* 3 5 6 7 8 9 1*
Here's a solution similar to Khalid's.
Two elements are considered adjacent if they can appear next to each other ignorant of wrapping. So, 9 and 0 are considered adjacent elements.
The algorithm cycles through each set of three consecutive elements, and checks if the first one and the third one are adjacent or not. If they are adjacent, then the middle value must be out of order.
I join the given list to itself, thus creating an array of size 20. This takes care of a special case where the number was moved to the beginning or the end of the list.
# checks if two given numbers are adjacent or not, independent of wrapping
def adjacent?(a, b)
(a - b).abs == 1 || [a, b].sort == [0, 9]
end
# finds the misplaced number in a list
def misplaced_number(list)
middle_index = 1
(list + list).each_cons(3).find { |first, second, third|
adjacent?(first, third)
}[middle_index]
end
Checked with the following tests. The second and last test failed because of ambiguity.
test([2, 3, 0, 4, 5, 6, 7, 8, 9, 1], 0)
test([5, 6, 7, 9, 8, 0, 1, 2, 3, 4], 8) # [FAIL: result = 9]
test([7, 6, 5, 4, 3, 8, 2, 1, 0, 9], 8)
test([0, 5, 1, 2, 3, 4, 6, 7, 8, 9], 5)
test([4, 3, 0, 2, 1, 9, 8, 7, 6, 5], 0)
test([2, 4, 5, 6, 7, 8, 9, 0, 1, 3], 2) # [FAIL: result = 3]
def test(list, expected)
result = misplaced_number(list)
assert result == expected_value, "Got #{result} but expected #{expected} from list #{list}"
end
So combining srikanta and n.m.'s in Haskell:
import Data.List (findIndex)
f s = maybe (-1) (+1) . findIndex (==1)
$ zipWith (\a b -> abs (a - b)) s (drop 2 s ++ take 2 s)
*Main> f [2,3,0,4,5,6,7,8,9,1]
2
*Main> f [5,6,7,9,8,0,1,2,3,4]
3
...
#include <stdio.h>
int main(void)
{
int array[10] = { 4, 3, 1, 0, 9, 8, 7, 2, 6, 5};
size_t idx;
int diff, state,this,next;
#define COUNT (sizeof array/sizeof array[0])
#define FOLD(n,i) ((i)%(n))
#define FETCH(a,i) a[FOLD(COUNT,(i))]
this = FETCH(array,COUNT-1);
next = FETCH(array,0);
diff = next - this;
state = (diff < -1 || diff >1) ? 1: 0;
for (idx = 0; idx < COUNT; idx++) {
this = next;
next = FETCH(array,idx+1);
diff = next - this;
state = (state<<1) & 3;
state |= (diff < -1 || diff >1) ? 1: 0;
if (state==3) putc('*', stdout);
printf("%d ", this );
}
putc('\n', stdout);
return 0;
}
Output:
4 3 1 0 9 8 7 *2 6 5
int element, backdiff, forwarddiff;
boolean elementFound = false;
if(abs(a[0] - a[1]) == 2 )
return "Out of Order Element is # position" + (a[0] - a[1] > 0 ? 0 : 1);
for (i=1;i<n;i++){
if(!elementFound){
backdiff = abs(a[i-1] - a[i]);
forwarddiff = abs(a[i+1] - a[i]);
if( (backdiff == 1 && forwarddiff == 1) ||
(backdiff == n-1 && forwarddiff == 1) ||
(backdiff == 1 && forwarddiff == n-1) )
continue;
if(forwarddiff == 2 || backdiff == 2)
element = abs(a[i]-(a[i-1]+a[i+1]));
elementFound = true;
if(forwarddiff > 2 || backdiff > 2)
return "Out of Order Element is # position" + (forwarddiff > 2 ? (i+1) : i);
} else {
if(a[i] == element)
return "Out of Order Element is # position" + (i);
}
}

Resources