Related
How to represent (serialise) an arbitrarily nested array, as a one-dimensional array of values (and meta-data) so that the original nested array and it's structure can be recreated from the serialised one-dimensional array?
I'm looking for a space efficient algorithms for this problem.
For example:
[
[
[1, 2, 3, 4]
],
[
[5, 6, 7, 8],
[9, 10]
]
]
Should be serialised / deserialised to / from something like this
[/* elements of meta data* /, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
You could represent a nested array with a sequence that first contains the length of that array (also providing the information that the following content is a sub-array) and then the elements themselves.
If you only have positive numbers as your values, but can store negative numbers, you could use negative numbers as the indicator for sub-arrays (if not, you can of course just use an offset O, which is the highest number you want to store, and treat all numbers greater then O as indicator for a new sub-array). The serialized version of your example would then look like this:
[-2, -1, -4, 1, 2, 3, 4, -2, -4, 5, 6, 7, 8, -2, 9, 10]
To understand better how it's working, here is an indented version of the same serialized array:
[-2,
-1,
-4
1, 2, 3, 4
-2
-4
5, 6, 7, 8
-2
9, 10
]
This structure can be serialized and deserialized in linear time using a recursive algorithm.
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
Suppose I have an array with 10 elements, e.g. a=np.arange(10). If I want to create another array with the 1st, 3rd, 5th, 7th, 9th, 10th elements of the original array, i.e. b=np.array([0,2,4,6,8,9]), how can I do it efficiently?
thanks
a[[0, 2, 4, 6, 8, 9]]
Index a with a list or array representing the desired indices. (Not 1, 3, 5, 7, 9, 10, because indexing starts from 0.) It's a bit confusing that the indices and the values are the same here, so have a different example:
>>> a = np.array([5, 4, 6, 3, 7, 2, 8, 1, 9, 0])
>>> a[[0, 2, 4, 6, 8, 9]]
array([5, 6, 7, 8, 9, 0])
Note that this creates a copy, not a view. Also, note that this might not generalize to multiple axes the way you expect.
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.
I search a fast method to perform my problem.
imagine ordered seats numeroted from 1 to 8, imagine they are people on seats [ 2, 6, 5, 3 ]. i want to get back the second (interval +2) people after the seat number 4 (start value)
for examples :
with this array : [2, 5, 8, 7, 1] , i started with value 3 and i move +2 times,
the third next number in the list is 5, the second is 7, the method must return this value
with the same [2, 5, 8, 7, 1] , i started from 7 and i move +3 times
here the method must return to the minimal value. trought 8.. 1.. 2.., result : 2
with [1, 3], start 4, count +2, result 3
with [5, 3, 9], start 3, count +1, result 5
with [5, 3, 9], start 3, count +2, result 9
I hope someone will understand my problem.
thanks you
Sort your list, use bisect to find the starting index, then mod the result of the addition by the length of the list.
So, this is basically just an example implementation of Ignacio's algorithm in Python:
from bisect import bisect
def circular_highest(lst, start, move):
slst = sorted(lst)
return slst[(bisect(slst, start) - 1 + move) % len(lst)]
print circular_highest([2, 5, 8, 7, 1], 3, 2)
print circular_highest([2, 5, 8, 7, 1], 7, 3)
print circular_highest([1, 3], 4, 2)
print circular_highest([5, 3, 9], 3, 1)
print circular_highest([5, 3, 9], 3, 2)
Output:
7
2
3
5
9