Two if statements in a for loop? - arrays

class Solution:
def transformArray(self, arr: List[int]) -> List[int]:
x=arr
while True:
f=True
for i in range(1,len(arr)-1):
if arr[i-1]<arr[i] and arr[i]>arr[i+1]:
f=False
x[i]=x[i]-1
print(x[i])
if arr[i-1]>arr[i] and arr[i]<arr[i+1]:
f=False
x[i]=x[i]+1
print(x[i])
#print(x)
x=arr
if f==True:
break
return x
In the above code both the if statements don't execute , only the second one does. I have tried using elif but it still doesn't work. What am i missing here?

For your code, I considered two types of examples as input for the array list
For example 1, when the arr = [1, 2, 1, 4], the 2nd element is bigger than 1st and 3rd
The first if statement (if arr[i-1]<arr[i] and arr[i]>arr[i+1]:) is working, because both the conditions are met and it gives the output x = [1, 1, 1, 4]
In example 2, when the arr = [3, 2, 3, 4], the 2nd element is smaller than the 1st and 3rd
The second if statement (if arr[i-1]>arr[i] and arr[i]<arr[i+1]:) is working, because both the conditions are met and it gives the output x = [3, 3, 3, 4]
So, the working of if statements largely depends on the elements in the array. Both the if statements' purpose is totally opposite. If one satisfies the condition the other will not.
Hope my answer provides some clarification.

Related

Is there any way to increment past an array element in Python? (Like how you can with pointer arithmetic in C?)

I have
arr = [6, 5, 4, 3, 2, 1]
I want to use the ...5, 4, 3, 2, 1] part of the array in a recursive call while keeping the 6 in the array (at its current position) for future use.
It feels very similar to pointer arithmetic in C, I'm just not sure how to implement something like that in Python (ver 3.7). I'm lost as to how to preserve the 6 in the array at it's position, which is essential as the array needs to be maintained in sorted descending order.
Any guidance on how to get around this is appreciated.
You can access the elements of the arr list in the following manner while not disturbing the elements of it
>>> arr[2:]
[4, 3, 2, 1]
>>> arr[1:]
[5, 4, 3, 2, 1]
>>> arr
[6, 5, 4, 3, 2, 1]
>>> arr[2:4]
[4, 3]
List indexing doesn't affect the elements inside. I hope this answers your question
You can use a part of an array in a recursive call without changing the original array using start and end index.
arr=[6,5,4,3,2,1], now if you want to use arr from index=1 then just pass
start and end i.e, fun(arr, start, end) in the function fun where, start=1 and end=length-1, this will not modify the original array and at the same time you can use array from start to end in recursive calls.

How to remove a single value from an array in Ruby?

I want to remove the first instance of the lowest value in the array.
arr = [1,2,3,1,2,3]
arr.reject {|i| i == arr.min}
#=> [2,3,2,3]
But my code removes all instances of the lowest value in the array. I want a result such that:
[...]
#=> [2,3,1,2,3]
What's the most elegant solution to this problem?
On first blush, here are a couple of options:
arr.delete_at(arr.index(arr.min))
# or less readable but still valid
arr.delete_at arr.index arr.min
arr.delete_at(arr.each_with_index.min[1])
# or
arr.delete_at(arr.each_with_index.min.pop)
# or
arr.delete_at(arr.each_with_index.min.last)
The first is less code and more readable but makes two passes through the list instead of one. I have doubts as to whether any other construct will surpass option #1 in elegance, as ugly as it may (or may not?) be.
Note that both choices crash on an empty array. Here's a safer version:
arr.delete_at arr.index(arr.min) || 0
Just out of curiosity:
[1,2,3,1,2,3].tap { |a| a.delete_at a.each_with_index.min.last }
#⇒ [2, 3, 1, 2, 3]
You can use Enumerable#drop_while for this purpose
arr = [1,2,3,1,2,3]
arr.drop_while { |i| i == arr.min }
#=> [2, 3, 1, 2, 3]

Removing 'nil's from a column using transpose

I have a nested array:
arr = [[1,nil,2,3,4], [2,nil,4,5,6], [6,nil,3,3,5]]
Any elements at the same index in the subarrays that are nil across the array must be removed. The second index in all subarrays have nil.
I did this:
collection = arr.transpose.select(&:any?).transpose
# => [[1, 2, 3, 4], [2, 4, 5, 6], [6, 3, 3, 5]]
It works for me, albiet I am using transpose twice. Could this technique lead to data getting mixed up? It looks fool proof to me.
With the nil-vs-false caveat that #CarySwoveland noted in a comment, yes, your double-transpose is safe: it will only work on data that's rectangular to begin with, and it will produce equally-rectangular data as output. You're filtering out whole rows, so nothing can get misaligned.
While it's not super efficient, it's not too bad, and is far more expressive & readable than more direct looping & manipulation.

Does ruby support an enumerable map_cons method or its equivalent?

Ruby has a handy function for enumerables called each_cons. Which "Iterates the given block for each array of consecutive elements." This is really nice. Except that this is definitely an each method, which returns nil upon completion and not an array of the values you've looped over like map would.
However, if I have a situation where I need to iterate over an enumerable type, take an element and its cons, then perform some operation on them and return them back into an array what can I do? Normally, I'd use map for this sort of behavior. But map_cons doesn't exist.
An example:
Given a list of integers, I need to see which ones of those integers repeat and return a list of just those integers
[1, 1, 4, 5, 6, 2, 2] ## I need some function that will get me [1, 2]
I can say:
[1, 1, 4, 5, 6, 2, 2].each_cons(2) {|e| e[0] if e[0] == e[1]}
But, since it eachs over the array, it will complete successfully and return nil at the end. I need it to behave like map and not like each.
Is this behavior something that ruby supports? Am I coming at it from the wrong direction entirely?
The documentation of each_cons ends with this innocent phrase: "If no block is given, returns an enumerator." Most methods of Enumerable do this. What can you do with an Enumerator? Nothing truly impressive . But Enumerators include Enumerable, which does provide a large amount of powerful methods, map being one of them. So, as Stefan Pochmann does:
[1, 1, 4, 5, 6, 2, 2].each_cons(2).map { |e| e[0] if e[0] == e[1] }
each_consis called without a block, so it returns an Enumerator. mapis simply one of its methods.
Just add map?
[1, 1, 4, 5, 6, 2, 2].each_cons(2).map { |e| e[0] if e[0] == e[1] }
=> [1, nil, nil, nil, nil, 2]
Ruby 2.7 added the method filter_map which makes this even easier:
p [1, 1, 4, 5, 6, 2, 2].each_cons(2).filter_map{|a,b| a if a == b} # => [1, 2]

Ruby: Remove first and last element of an Array - why the solution works one way & not the other

I's like to know why the second solution works but the first one, which has chained methods, doesn't work.
This chained method doesn't work:
nopers = [5, 6, 7, 8, 9]
class Array
define_method(:trimy) do
self.shift().pop()
end
end
When I test it, nopers.trimy(), it gives an undefined error message. "method 'pop' for 1:Fixnum, in 'block in '" and only executes the .pop() method, removing the 5.
But, this version works:
yuppers = [1, 2, 3, 4, 5, 6]
class Array
define_method(:trim) do
self.shift()
self.pop()
end
end
yuppers.trim()
When I test it, yuppers gives me: [2, 3, 4, 5]
I would say that:
yuppers[1..-2]
is the most simple solution
This is because both shift and pop return the value that is removed:
[1, 2, 3].pop # => returns 3
[1, 2, 3].shift # => returns 1
So when you chain them together you're calling #pop on the result of #shift, which is an Integer which isn't allowed.

Resources