Algorithm Logic, Splitting Arrays - arrays

I'm not looking for a solution just pseudo code or logic that would help me derive an answer.
Given an array:
[1,2,3,4]
I want to split this into two arrays of varying lengths and contents whose sum lengths are equal to the length of the given array. It would be ideal without repetition.
Example output:
[[1],[2, 3, 4]]
[[1, 2], [3, 4]]
[[1, 3], [2, 4]]
[[1, 4],[2, 3]]
[[1, 2, 3], [4]]
[[2], [1, 3, 4]]
[[2, 4], [1, 3]]
[[3], [1, 2, 4]]
More example:
[[1, 3, 4, 6, 8], [2, 5, 7]] //this is a possible combination of 1 through 8
//array
Intuitions:
First attempt involved pushing the starting number array[i] to the result array[0], the second loop moving the index for the third loop to start iterating as is grabbed sublists. Then fill the other list with remaining indices. Was poorly conceived...
Second idea is permutations. Write an algorithm that reorganizes the array into every possible combination. Then, perform the same split operation on those lists at different indexes keeping track of unique lists as strings in a dictionary.
[1,2,3,4,5,6,7,8]
^
split
[1,2,3,4,5,6,7,8]
^
split
[1,3,4,5,6,7,8,2]
^
split
I'm confident that this will produce the lists i'm looking for. However! i'm afraid it may be less efficient than I'd like due to the need for sorting when checking for duplicates and permutations is expensive in the first place.
Please respond with how you would approach this problem, and why.

Pseudocode. The idea is to start with an item in one of the bags, and then to place the next item once in the same bag, once in the other.
function f(A):
// Recursive function to collect arrangements
function g(l, r, i):
// Base case: no more items
if i == length(A):
return [[l, r]]
// Place the item in the left bag
return g(l with A[i], r, i + 1)
// Also return a version where the item
// is placed in the right bag
concatenated with g(l, r with A[i], i + 1)
// Check that we have at least one item
if A is empty:
return []
// Start the recursion with one item placed
return g([A[0]], [], 1)
(PS see revisions for JavaScript code.)

Related

Algorithm to check if a multidimensional array contains another?

Say I have two multidimensional arrays of equal depth, say:
[ [1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]
and
[ [2, 3],
[5, 6] ]
What sort of algorithm can I follow to determine if the latter is a contiguous subarray of the former?
For example, with the above example, it is:
And also with this pair of 3d arrays:
[ [ [4, 6],
[5, 7] ],
[ [2, 8],
[9, 3] ] ]
[ [ [4, 6] ],
[ [2, 8] ] ]
Another way of interpreting this is that by removing the first or last item from a dimension of the first array repeatedly, you will eventually get the target array.
The Rabin-Karp string search algorithm can be extended to multiple dimensions to solve this problem.
Lets say your pattern array is M rows by N columns:
Using any rolling hash function, like a polynomial hash, first replace every column of your pattern array with the hash of the column, reducing it to 1 dimension. Then hash the remaining row. This will be your pattern hash.
Now use the rolling hash in your target array to replace all values in rows >= M by the hash of those values with the M-1 values above them.
Then, similarly replace all remaining values in columns >= N-1 with the hash of those values and the N-1 values to the left.
Finally, find any instances of the pattern hash in the resulting matrix. When you find one, compare with your pattern array to see if it's a real match.
This algorithm extends to as many dimensions as you like and, like simple Rabin-Karp, it takes O(N) expected time if the number of dimensions is constant.
The simple and naive approach would be, to look for first (0,0) match and then to compare the sub array.
Example: (Python)
hay=[ [1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]
needle=[ [2, 3],
[5, 6] ]
def get_sub_array(array,i,j,width,height):
sub_array=[]
for n in range(i,i+height):
sub_array.append(array[n][j:j+width])
return sub_array
def compare(arr1,arr2):
for i in range(len(arr1)):
for j in range(len(arr1[0])):
if arr1[i][j]!=arr2[i][j]:
return False
return True
def is_sub_array(hay,needle):
hay_width=len(hay[0])
hay_height=len(hay)
needle_width=len(needle[0])
needle_height=len(needle)
for i in range(hay_height-needle_height+1):
for j in range(hay_width-needle_width+1):
if hay[i][j]==needle[0][0]:
if compare(
get_sub_array(hay,i,j,needle_width,needle_height),
needle
):
return True
return False
print(is_sub_array(hay,needle))
Output:
True

Find all array with second highest elements in a list

Assuming that I have a list of arrays in Python 3.2, and I want to output an array that contains every array elements, together with their index position in the list, which have the highest second elements. How can I achieve this goal in the most scalable way (i.e., without having to use the nested for-loop )?
Input
a = [[2,3], [1,4,5], [1,4,6,2], [3,3,5], [9,4]]
Expected Output
res = [[[1,4,5], 1], [[1, 4, 6,2], 2], [[9,4], 4]]
Can someone please help assist me on how to do this without using nested for-loop?
You could do:
b = max(a, key=lambda x:x[1])[1]
[[j, i] for i, j in enumerate(a) if j[1]==b]
Out[6]: [[[1, 4, 5], 1], [[1, 4, 6, 2], 2], [[9, 4], 4]]

Quicker way of adding x to every second element in all nested arrays

I have a nested array in ruby, similar to the one below, but with quite a few more nested arrays.
arr=[[1,2,3],[4,5,6],[7,8,9]]
Is there a way to get every second element within the nested array, and add x to that element? I have used the code below, but if there is a quicker way I'd love to know.
x = 5
arr[0][1], arr[1][1], arr[2][1] = arr[0][1]+x, arr[1][1]+x, arr[2][1]+x
I have tried to use arr.map!{|f,l| [f, l + 1]}, but I get the result arr == [[1, 3], [4, 6], [7, 9]]
EDIT:
So the outcome should be arr == [[1,2+x,3],[4,5+x,6],[7,8+x,9]]
Any time you find yourself writing that kind of code over and over, you should look to use a loop! Ruby commonly uses iterators for performing looping. Array#each is an iterator which loops over an Array, and lets you operate on each element one at a time.
Since you know that you want to add x to the second element in each, this is trivially:
arr.each {|e| e[1] += x }
This mutates arr (and arr's subarrays) in place. If you want to return a mutated copy, you would use map, which is like each except the return value is the output of the block, rather than the input to it.
# First we clone each subarray with Array#dup, then we iterate the
# clones, adding x to the second element. Because we're using `map`
# the result will be a new array, rather than the original arr, leaving
# the original unmodified.
new_arr = arr.map(&:dup).each {|e| e[1] += x }
You're close! You can use map to loop through each sub-array and the ruby += operator to add x to the second element of each. The trick with map is that you'll need to return the entire sub-array in each loop, which would look like:
arr.map { |a| a[1] += x; a }
#=> [[1, 7, 3], [4, 10, 6], [7, 13, 9]]
Here's another one:
arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
x = 5
arr.map { |a, b, c| [a, b + x, c] }
#=> [[1, 7, 3], [4, 10, 6], [7, 13, 9]]
Note that map returns a new array. If you want to modify the existing array, there's map!.

Iterating Over a List of Lists in Haskell?

I'm having some difficulties understanding how to iterate through a list in Haskell. I've been trying to work with mapM but for some reason I keep on coming up with parsing errors. I know that this can be done recursively, but the code within the iteration/for loop is only a small part of the whole function so I wouldn't want to recursively call the function. So for example, if I have a list of lists like
[[0, 1, 2], [2, 3, 4], [4, 5, 6]]
how would I go about first iterating through each list to see if the sum of values in each list is > 5 and then within each list, iterating through the individual values to check if there is an integer = 2 in the list (and return True in that case)?
how would I go about first iterating through each list to see if the sum of values in each list is > 5
Lets say your list is
l = [[0, 1, 2], [2, 3, 4], [4, 5, 6]]
You can get the lists whose values sum up more than five, using filter. The first argument of filter is a function (\xs -> sum xs > 5), that given a list xs, decides if the sum of its elements is bigger than 5
> filter (\xs -> sum xs > 5) l
[[2,3,4],[4,5,6]]
and then within each list, iterating through the individual values to check if there is an integer = 2 in the list
Same as before, you use filter, but now you check if number 2 is an element of each list xs
> filter (\xs -> 2 `elem` xs) l
[[0,1,2],[2,3,4]]
It's not 100% clear to me exactly what you want to do, but here are some building blocks that may help:
Find which lists have a sum greater than 5:
Prelude> filter ((>5) . sum) [[0, 1, 2], [2, 3, 4], [4, 5, 6]]
[[2,3,4],[4,5,6]]
Find whether a list contains the number 2:
Prelude> any (==2) [1,2,3]
True
Prelude> any (==2) [4,5,6]
False
Combine the above, to give True / False for each list whose sum is greater than 5:
Prelude> (map (any (==2)) . filter ((>5) . sum)) [[0, 1, 2], [2, 3, 4], [4, 5, 6]]
[True,False]
List comprehensions are iterative. I'm not sure what you want so the following creates a tuple of the sum greater than 5 of each list and the second item of the tuple weather any element of the list is 2. The check for elements equal to 2 is another short list comprehension.
[(a,[True|t<-b,t == 2])|b<-[[0,1,2],[2,3,4,5],[6,7,8]], a<-[sum b], a>5]
[(14,[True]),(21,[])]

How to extract lines in an array, which contain a certain value? (numpy, scipy)

I have an numpy 2D array and I want it to return coloumn c where (r, c-1) (row r, coloumn c) equals a certain value (int n).
I don't want to iterate over the rows writing something like
for r in len(rows):
if array[r, c-1] == 1:
store array[r,c]
, because there are 4000 of them and this 2D array is just one of 20 i have to look trough.
I found "filter" but don't know how to use it (Found no doc).
Is there an function, that provides such a search?
I hope I understood your question correctly. Let's say you have an array a
a = array(range(7)*3).reshape(7, 3)
print a
array([[0, 1, 2],
[3, 4, 5],
[6, 0, 1],
[2, 3, 4],
[5, 6, 0],
[1, 2, 3],
[4, 5, 6]])
and you want to extract all lines where the first entry is 2. This can be done like this:
print a[a[:,0] == 2]
array([[2, 3, 4]])
a[:,0] denotes the first column of the array, == 2 returns a Boolean array marking the entries that match, and then we use advanced indexing to extract the respective rows.
Of course, NumPy needs to iterate over all entries, but this will be much faster than doing it in Python.
Numpy arrays are not indexed. If you need to perform this specific operation more effeciently than linear in the array size, then you need to use something other than numpy.

Resources