I have a code block like this:
hash["value"].delete_if{|cell| cell["id"]["name"] == ('foo')}
There is a simple way to count how many times the delete_if has actually acted ?
counter
Since every integer is truthy, you could write :
count = 0
hash["value"].delete_if{|cell| cell["id"]["name"] == ('foo') && count += 1}
cell will be deleted every time count is incremented, and count is incremented every time cell["id"]["name"] == ('foo').
As an example :
count = 0
true && count += 1
false && count += 1
true && count += 1
false && count += 1
true && count += 1
count
# 3
difference
Since delete_if is destructive, you can simply compare the size difference before and after the method call.
original_size = hash["value"].size
hash["value"].delete_if{|cell| cell["id"]["name"] == ('foo') && count += 1}
original_size - hash["value"].size
partition
If you need not only the number of times delete_if has acted, but for which elements, you could use partition :
deleted, hash["value"] = hash["value"].partition{|cell| cell["id"]["name"] == ('foo')}
deleted.size
# deleted contains the deleted cells from `hash['value']`
Related
I know this sounds kind of simple but I'm trying to get the count of "countdown" sequences that exists in my array. Example:
[1,2,3,2,5,4,3,0] - > 2 ([3,2] and [5,4,3])
I just need a little push, please!
Just iterate through the list every time the countdown breaks you increment the counter
Python, also known as pseudo code:
def count_finder(l):
prev = l[0]
counter = 0
inCount = False
for num in l[1:]:
if num == prev-1: #Checks if the previous was 1 greater than this one
inCount = True # if it is then "inCount" is True
elif num+1 != prev and inCount: #Checks if your exiting a countdown
inCount = False
counter += 1 #Increment Counter
prev = num #Change previous number to current number for next loop
if inCount: counter+=1 #If the loop ends while in a count down increment counter
return counter
print(count_finder([9, 8, 7, 6, 5, 4]))
How can I get the number of iterations/steps that this method takes to find an answer?
def binary_search(array, n)
min = 0
max = (array.length) - 1
while min <= max
middle = (min + max) / 2
if array[middle] == n
return middle
elsif array[middle] > n
max = middle - 1
elsif array[middle] < n
min = middle + 1
end
end
"#{n} not found in this array"
end
One option to use instead of a counter is the .with_index keyword. To use this you'll need to use loop instead of while, but it should work the same. Here's a basic example with output.
arr = [1,2,3,4,5,6,7,8]
loop.with_index do |_, index| # The underscore is to ignore the first variable as it's not used
if (arr[index] % 2).zero?
puts "even: #{arr[index]}"
else
puts "odd: #{arr[index]}"
end
break if index.eql?(arr.length - 1)
end
=>
odd: 1
even: 2
odd: 3
even: 4
odd: 5
even: 6
odd: 7
even: 8
Just count the number of iterations.
Set a variable to 0 outside the loop
Add 1 to it inside the loop
When you return the index, return the count with it (return [middle, count]).
I assume the code to count numbers of interations required by binary_search is to be used for testing or optimization. If so, the method binary_search should be modified in such a way that to produce production code it is only necessary to remove (or comment out) lines of code, as opposed to modifying statements. Here is one way that might be done.
def binary_search(array, n)
# remove from production code lines marked -> #******
_bin_srch_iters = 0 #******
begin #******
min = 0
max = (array.length) - 1
loop do
_bin_srch_iters += 1 #******
middle = (min + max) / 2
break middle if array[middle] == n
break nil if min == max
if array[middle] > n
max = middle - 1
else # array[middle] < n
min = middle + 1
end
end
ensure #******
puts "binary_search reqd #{_bin_srch_iters} interations" #******
end #******
end
x = binary_search([1,3,6,7,9,11], 3)
# binary_search reqd 3 interations
#=> 1
binary_search([1,3,6,7,9,11], 5)
# binary_search reqd 3 interations
#=> nil
The code below returns "Arithmetic", "Geometric" if the input array is an arithmetic and geometric series respectively and -1 if it is neither.
Although the code works fine, when I change
if s = arr.length - 1
to
if s == arr.length - 1
in the while loop, the code is not working properly anymore.
I do not understand why. Shouldn't == work instead of =?
def ArithGeo(arr)
# code goes here
len = arr.length
difference = arr[len-1] - arr[len-2]
ratio = arr[len-1]/arr[len-2]
k = 0
s = k + 1
while (arr[s] - arr[k]) == difference && s < arr.length
if s = arr.length - 1
return "Arithmetic"
end
k += 1
end
k = 0
while arr[s] / arr[k] == ratio && s < arr.length
if s = arr.length - 1
return "Geometric"
end
k += 1
end
return -1
end
You're never changing the value of s which I think you want to do. You should do that at the point that you increment k
k += 1
s = k + 1
Also, at the point where you reinitialize k for the geometric test, you want to reset s as well...
k = 0
s = k + 1
You could also get rid of the variable s completely and make it a method... add these three lines at the top of the code
def s(k)
k + 1
end
And remove all the lines where you assign a value to s and use s(k)... s(k) will be a method that always returns the next higher value to k
The difference between those two statements is that variable s is set for the first statement but not for the second. The first if statement has thus a side effect of setting s to arr.length - 1
if s = arr.length - 1 # s => arr.length - 1
if s == arr.length - 1 # s => undefined
Because the if statement is inside a while loop which uses s in its expression the change of the statement changes the behavior of the programm.
If you put == the statement will try to check if they are equals , with just = the statement work properly because your are only setting the value to a value , so this is always true.
If it's different compare something to equals than just set a variable , that can be always true.
I am learning ruby and the way I am going about this is by learning and implementing sort algorithms. While working on selection sort, I tried to modify it as follows:
In every pass, instead of finding the smallest and moving it to the top or beginning of the array, find the smallest and the largest and move them to both ends
For every pass, increment the beginning and decrease the ending positions of the array that has to be looped through
While swapping, if the identified min and max are in positions that get swapped with each other, do the swap once (otherwise, two swaps will be done, 1 for the min and 1 for the max)
This doesn't seem to work in all cases. Am I missing something in the logic? If the logic is correct, I will revisit my implementation but for now I haven't been able to figure out what is wrong.
Please help.
Update: This is my code for the method doing this sort:
def mss(array)
start = 0;
stop = array.length - 1;
num_of_pass = 0
num_of_swap = 0
while (start <= stop) do
num_of_pass += 1
min_val = array[start]
max_val = array[stop]
min_pos = start
max_pos = stop
(start..stop).each do
|i|
if (min_val > array[i])
min_pos = i
min_val = array[i]
end
if (max_val < array[i])
max_pos = i
max_val = array[i]
end
end
if (min_pos > start)
array[start], array[min_pos] = array[min_pos], array[start]
num_of_swap += 1
end
if ((max_pos < stop) && (max_pos != start))
array[stop], array[max_pos] = array[max_pos], array[stop]
num_of_swap += 1
end
start += 1
stop -= 1
end
puts "length of array = #{array.length}"
puts "Number of passes = #{num_of_pass}"
puts "Number of swaps = #{num_of_swap}"
return array
end
The problem can be demonstrated with this input array
7 5 4 2 6
After searching the array the first time, we have
start = 0
stop = 4
min_pos = 3
min_val = 2
max_pos = 0 note: max_pos == start
max_val = 7
The first if statement will swap the 2 and 7, changing the array to
2 5 4 7 6
The second if statement does not move the 7 because max_pos == start. As a result, the 6 stays at the end of the array, which is not what you want.
I am currently doing Project Euler problem 1. I have no idea why these two loops are not the same.
total = 0
for i in 0..1000
if (i % 3 == 0 || i % 5 == 0)
total += i
end
end
and
total = 0
(0...1000).each do |i|
total += i if (i % 3 == 0 || i % 5 == 0)
end
puts total
When you use three dots in range (0...1000), the end value is not part of the range - it is equivalent to (0..999)
So, in first case 1000 is part of the loop, but in second case it is not.