How do I use an across loop in post condition to compare an old array and new array at certain indices? - eiffel

I have a method that shifts all the items, in an array, to the left by one position. In my post condition I need to ensure that my items have shifted to the left by one. I have already compared the first element of the old array to the last element of the new array. How do i across loop through the old array from 2 until count, loop through the new array from 1 until count-1 and compare them? This is my implementation so far.
items_shifted:
old array.deep_twin[1] ~ array[array.count]
and
across 2 |..| (old array.deep_twin.count) as i_twin all
across 1 |..| (array.count-1) as i_orig all
i_twin.item ~ i_orig.item
end
end
end
I expected the result to be true but instead I get a contract violation pointing to this post condition. I have tested the method out manually by printing out the array before and after the method and I get the expected result.

In the postcondition that fails, the loop cursors i_twin and i_orig iterate over sequences 2 .. array.count and 1 .. array.count - 1 respectively, i.e. their items are indexes 2, 3, ... and 1, 2, .... So, the loop performs comparisons 2 ~ 1, 3 ~ 2, etc. (at run-time, it stops on the first inequality). However, you would like to compare elements, not indexes.
One possible solution is shown below:
items_shifted:
across array as c all
c.item =
if c.target_index < array.upper then
(old array.twin) [c.target_index + 1]
else
old array [array.lower]
end
end
The loop checks that all elements are shifted. If the cursor points to the last element, it compares it against the old first element. Otherwise, it tests whether the current element is equal to the old element at the next index.
Cosmetics:
The postcondition does not assume that the array starts at 1, and uses array.lower and array.upper instead.
The postcondition does not perform a deep twin of the original array. This allows for comparing elements using = rather than ~.
Edit: To avoid potential confusion caused by precedence rules, and to highlight that comparison is performed for all items between old and new array, a better variant suggested by Eric Bezault looks like:
items_shifted:
across array as c all
c.item =(old array.twin)
[if c.target_index < array.upper then
c.target_index + 1
else
array.lower
end]
end

Related

Python: Finding the row index of a value in 2D array when a condition is met

I have a 2D array PointAndTangent of dimension 8500 x 5. The data is row-wise with 8500 data rows and 5 data values for each row. I need to extract the row index of an element in 4th column when this condition is met, for any s:
abs(PointAndTangent[:,3] - s) <= 0.005
I just need the row index of the first match for the above condition. I tried using the following:
index = np.all([[abs(s - PointAndTangent[:, 3])<= 0.005], [abs(s - PointAndTangent[:, 3]) <= 0.005]], axis=0)
i = int(np.where(np.squeeze(index))[0])
which doesn't work. I get the follwing error:
i = int(np.where(np.squeeze(index))[0])
TypeError: only size-1 arrays can be converted to Python scalars
I am not so proficient with NumPy in Python. Any suggestions would be great. I am trying to avoid using for loop as this is small part of a huge simulation that I am trying.
Thanks!
Possible Solution
I used the following
idx = (np.abs(PointAndTangent[:,3] - s)).argmin()
It seems to work. It returns the row index of the nearest value to s in the 4th column.
You were almost there. np.where is one of the most abused functions in numpy. Half the time, you really want np.nonzero, and the other half, you want to use the boolean mask directly. In your case, you want np.flatnonzero or np.argmax:
mask = abs(PointAndTangent[:,3] - s) <= 0.005
mask is a 1D array with ones where the condition is met, and zeros elsewhere. You can get the indices of all the ones with flatnonzero and select the first one:
index = np.flatnonzero(mask)[0]
Alternatively, you can select the first one directly with argmax:
index = np.argmax(mask)
The solutions behave differently in the case when there are no rows meeting your condition. Three former does indexing, so will raise an error. The latter will return zero, which can also be a real result.
Both can be written as a one-liner by replacing mask with the expression that was assigned to it.

The number of same elements in an array

My aim is to display the number of identical elements in an array.
Here is my code:
a = [5, 2, 4, 1, 2]
b = []
for i in a
unless b.include?(a[i])
b << a[i]
print i," appears ",a.count(i)," times\n"
end
end
I get this output:
5 appears 1 times
2 appears 2 times
4 appears 1 times
The output misses 1.
Here's a different way to do it, assuming I understand what "it" is (counting elements in an array):
a = [5,2,4,1,2]
counts = a.each_with_object(Hash.new(0)) do |element, counter|
counter[element] += 1
end
# => {5=>1, 2=>2, 4=>1, 1=>1}
# i.e. one 5, two 2s, one 4, one 1.
counts.each do |element, count|
puts "#{element} appears #{count} times"
end
# => 5 appears 1 times
# => 2 appears 2 times
# => 4 appears 1 times
# => 1 appears 1 times
Hash.new(0) initialises a hash with a default value 0. We iterate on a (while passing the hash as an additional object), so element will be each element of a in order, and counter will be our hash. We will increment the value of the hash indexed by the element by one; on the first go for each element, there won't be anything there, but our default value saves our bacon (and 0 + 1 is 1). The next time we encounter an element, it will increment whatever value already is present in the hash under that index.
Having obtained a hash of elements and their counts, we can print them, of course, puts is same as print but automatically inserts a newline; and rather than using commas to print several things, it is much nicer to put the values directly into the printed string itself using the string interpolation syntax ("...#{...}...").
The problems in your code are as follows:
[logic] for i in a will give you elements of a, not indices. Thus, a[i] will give you nil for the first element, not 5, since a[5] is outside the list. This is why 1 is missing from your output: a[1] (i.e. 2) is already in b when you try to process it.
[style] for ... in ... is almost never seen in Ruby code, with strong preference to each and other methods of Enumerable module
[performance] a.count(i) inside a loop increases your algorithmic complexity: count itself has to see the whole array, and you need to iterate the array to see i, which will be exponentially slower with huge arrays. The method above only has one loop, as access to hashes is very fast, and thus grows more or less linearly with the size of the array.
The stylistic and performance problems are minor, of course; you won't see performance drop till you need to process really large arrays, and style errors won't make your code not work; however, if you're learning Ruby, you should aim to work with the language from the start, to get used to its idioms as you go along, as it will give you much stronger foundation than transplanting other languages' idioms onto it.
a = [5,2,4,1,2]
b = a.uniq
for i in b
print i," appears ",a.count(i)," times\n"
end
print b
Result:
5 appears 1 times
2 appears 2 times
4 appears 1 times
1 appears 1 times
[5, 2, 4, 1]

Post-Condition Violation with Feature in Eiffel

This is part of the class. This class is called BAG[G -> {HASHABLE, COMPARABLE}]
it inherits from ADT_BAG which has deferred features such as count, extend, remove, remove_all, add_all... more, and domain to be re-implemented.
domain returns ARRAY[G] which is a sorted array list of G
i always get Post-condition violation "value_semantics" which is something to do with object comparison but I checked and there is no code for object comparison which is very weird.
I tried to remake the code for domain feature several times and it ALWAYS ends up with a post-condition violation or a fail.
When I check the debugger the array "a" that is returned from domain always has count 0 but this does not make sense because i move keys from table to "a" but count is still 0.
Maybe I am transferring the keys wrong to the array?
code:
count: INTEGER
-- cardinality of the domain
do
result := domain.count -- has to be domain.count because loop invariant: consistent: count = domain.count
end
domain: ARRAY[G]
-- sorted domain of bag
local
tmp: G
a: ARRAY[G]
do
create a.make_empty
across 1 |..| (a.count) as i -- MOVING keys from table to array
loop
across table as t
loop
if not a.has (t.key) then
a.enter (t.key, i.item)
i.forth
end
end
end
across 1 |..| (a.count-1) as i -- SORTING
loop
if a[i.item] > a[i.item+1] then
tmp := a[i.item]
a[i.item] := a[i.item+1]
a[i.item+1] := tmp
end
end
Result := a
ensure then
value_semantics: Result.object_comparison -- VIOLATION THROWN HERE
correct_items: across 1 |..| Result.count as j all
has(Result[j.item]) end
sorted: across 1 |..| (Result.count-1) as j all
Result[j.item] <= Result[j.item+1] end
end
test code:
t3: BOOLEAN
local
sorted_domain: ARRAY[STRING]
do
comment("t3:test sorted domain")
sorted_domain := <<"bolts", "hammers", "nuts">>
sorted_domain.compare_objects
Result := bag2.domain ~ sorted_domain -- fails here
check Result end
end
The first loop across 1 |..| (a.count) as i is not going to make a single iteration because a is empty (has no elements) at the beginning. Indeed, it has been just created with create a.make_empty.
Also, because keys in the table are unique it is useless to check whether a key has been added to the resulting array: the test not a.has (t.key) will always succeed.
Therefore the first loop should go over keys of a table and add them into the resulting array. The feature {ARRAY}.force may be of interest in this case. The addition of the new elements should not make any "holes" in the array though. One way to achieve this is to add a new element right after the current upper bound of the array.
The sorting loop is also incorrect. Here the situation is reversed compared to the previous one: sorting cannot be done in a single loop, at least two nested loops are required. The template seems to be using Insertion sort, its algorithm can be found elsewhere.
EDIT: the original answer referred to {ARRAY}.extend instead of {ARRAY}.force. Unfortunately {ARRAY}.extend is not generally available, but a.extend (x) would have the same effect as a.force (x, a.upper + 1).

Is it safe to delete from an Array inside each?

Is it possible to safely delete elements from an Array while iterating over it via each? A first test looks promising:
a = (1..4).to_a
a.each { |i| a.delete(i) if i == 2 }
# => [1, 3, 4]
However, I could not find hard facts on:
Whether it is safe (by design)
Since which Ruby version it is safe
At some points in the past, it seems that it was not possible to do:
It's not working because Ruby exits the .each loop when attempting to delete something.
The documentation does not state anything about deletability during iteration.
I am not looking for reject or delete_if. I want to do things with the elements of an array, and sometimes also remove an element from the array (after I've done other things with said element).
Update 1: I was not very clear on my definition of "safe", what I meant was:
do not raise any exceptions
do not skip any element in the Array
You should not rely on unauthorized answers too much. The answer you cited is wrong, as is pointed out by Kevin's comment to it.
It is safe (from the beginning of Ruby) to delete elements from an Array while each in the sense that Ruby will not raise an error for doing that, and will give a decisive (i.e., not random) result.
However, you need to be careful because when you delete an element, the elements following it will be shifted, hence the element that was supposed to be iterated next would be moved to the position of the deleted element, which has been iterated over already, and will be skipped.
In order to answer your question, whether it is "safe" to do so, you will first have to define what you mean by "safe". Do you mean
it doesn't crash the runtime?
it doesn't raise an Exception?
it does raise an Exception?
it behaves deterministically?
it does what you expect it to do? (What do you expect it to do?)
Unfortunately, the Ruby Language Specification is not exactly helpful:
15.2.12.5.10 Array#each
each(&block)
Visibility: public
Behavior:
If block is given:
For each element of the receiver in the indexing order, call block with the element as the only argument.
Return the receiver.
This seems to imply that it is indeed completely safe in the sense of 1., 2., 4., and 5. above.
The documentation says:
each { |item| block } → ary
Calls the given block once for each element in self, passing that element as a parameter.
Again, this seems to imply the same thing as the spec.
Unfortunately, none of the currently existing Ruby implementations interpret the spec in this way.
What actually happens in MRI and YARV is the following: the mutation to the array, including any shifting of the elements and/or indices becomes visible immediately, including to the internal implementation of the iterator code which is based on array indices. So, if you delete an element at or before the position you are currently iterating, you will skip the next element, whereas if you delete an element after the position you are currently iterating, you will skip that element. For each_with_index, you will also observe that all elements after the deleted element have their indices shifted (or rather the other way around: the indices stay put, but the elements are shifted).
So, this behavior is "safe" in the sense of 1., 2., and 4.
The other Ruby implementations mostly copy this (undocumented) behavior, but being undocumented, you cannot rely on it, and in fact, I believe at least one did experiment briefly with raising some sort of ConcurrentModificationException instead.
I would say that it is safe, based on the following:
2.2.2 :035 > a = (1..4).to_a
=> [1, 2, 3, 4]
2.2.2 :036 > a.each { |i| a.delete(i+1) if i > 1 ; puts i }
1
2
4
=> [1, 2, 4]
I'd infer from this test that Ruby correctly recognises while iterating through the contents that the element "3" has been deleted while element "2" was being processed, otherwise element "4" would also have been deleted.
However,
2.2.2 :040 > a.each { |i| puts i; a.delete(i) if i > 1 ; puts i }
1
1
2
2
4
4
This suggests that after "2" is deleted, the next element processed is whichever is now third in the array, so the element that used to be in third place does not get processed at all. each appears to re-examine the array to find the next element to process on every iteration.
I think that with that in mind, you ought to duplicate the array in your circumstances prior to processing.
It depends.
All .each does is returns an enumerator, which holds the collection an a pointer to where it left. Example:
a = [1,2,3]
b = a.each # => #<Enumerator: [1, 2, 3]:each>
b.next # => 1
a.delete(2)
b.next # => 3
a.clear
b.next # => StopIteration: iteration reached an end
Each with block calls next until the iteration reaches its end. So as long as you don't modify any 'future' array records it should be safe.
However there are so many helpful methods in ruby's Enumerable and Array you really shouldn't ever need to do this.
You are right, in the past it was advised not to remove items from the collection while iterating over it. In my tests and at least with version 1.9.3 in practice in an array this gives no problem, even when deleting prior or next elements.
It is my opinion that while you can you shouldn't.
A more clear and safe approach is to reject the elements and assign to a new array.
b = a.reject{ |i| i == 2 } #[1, 3, 4]
In case you want to reuse your a array that is also possible
a = a.reject{ |i| i == 2 } #[1, 3, 4]
which is in fact the same as
a.reject!{ |i| i == 2 } #[1, 3, 4]
You say you don't want to use reject because you want to do other things with the elements before deleting, but that is also possible.
a.reject!{ |i| puts i if i == 2;i == 2 }
# 2
#[1, 3, 4]

Finding whether a value is equal to the value of any array element in MATLAB

Can anyone tell me if there is a way (in MATLAB) to check whether a certain value is equal to any of the values stored within another array?
The way I intend to use it is to check whether an element index in one matrix is equal to the values stored in another array (where the stored values are the indices of the elements which meet a certain criteria).
So, if the indices of the elements which meet the criteria are stored in the matrix below:
criteriacheck = [3 5 6 8 20];
Going through the main array (called array) and checking if the index matches:
for i = 1:numel(array)
if i == 'Any value stored in criteriacheck'
%# "Do this"
end
end
Does anyone have an idea of how I might go about this?
The excellent answer previously given by #woodchips applies here as well:
Many ways to do this. ismember is the first that comes to mind, since it is a set membership action you wish to take. Thus
X = primes(20);
ismember([15 17],X)
ans =
0 1
Since 15 is not prime, but 17 is, ismember has done its job well here.
Of course, find (or any) will also work. But these are not vectorized in the sense that ismember was. We can test to see if 15 is in the set represented by X, but to test both of those numbers will take a loop, or successive tests.
~isempty(find(X == 15))
~isempty(find(X == 17))
or,
any(X == 15)
any(X == 17)
Finally, I would point out that tests for exact values are dangerous if the numbers may be true floats. Tests against integer values as I have shown are easy. But tests against floating point numbers should usually employ a tolerance.
tol = 10*eps;
any(abs(X - 3.1415926535897932384) <= tol)
you could use the find command
if (~isempty(find(criteriacheck == i)))
% do something
end
Note: Although this answer doesn't address the question in the title, it does address a more fundamental issue with how you are designing your for loop (the solution of which negates having to do what you are asking in the title). ;)
Based on the for loop you've written, your array criteriacheck appears to be a set of indices into array, and for each of these indexed elements you want to do some computation. If this is so, here's an alternative way for you to design your for loop:
for i = criteriacheck
%# Do something with array(i)
end
This will loop over all the values in criteriacheck, setting i to each subsequent value (i.e. 3, 5, 6, 8, and 20 in your example). This is more compact and efficient than looping over each element of array and checking if the index is in criteriacheck.
NOTE: As Jonas points out, you want to make sure criteriacheck is a row vector for the for loop to function properly. You can form any matrix into a row vector by following it with the (:)' syntax, which reshapes it into a column vector and then transposes it into a row vector:
for i = criteriacheck(:)'
...
The original question "Can anyone tell me if there is a way (in MATLAB) to check whether a certain value is equal to any of the values stored within another array?" can be solved without any loop.
Just use the setdiff function.
I think the INTERSECT function is what you are looking for.
C = intersect(A,B) returns the values common to both A and B. The
values of C are in sorted order.
http://www.mathworks.de/de/help/matlab/ref/intersect.html
The question if i == 'Any value stored in criteriacheck can also be answered this way if you consider i a trivial matrix. However, you are proably better off with any(i==criteriacheck)

Resources