size of array in perl script loop - arrays

I am using below commands to find the size of array
$size_x = #x;
or
$size_x = $#x+1 ;
Both work well when I use in simple statement. But when I use them in the loop, the size becomes one number bigger. Why it is happening in that way. Below is example:
for ($i=1;$i<=10;$i++){
if (1**2+2**2>=1){
#x[$i] =2+3;
$size_x = #x;
}
print "my size is $size_x\n";
}
here is results:
my size is 2
my size is 3
my size is 4
my size is 5
my size is 6
my size is 7
my size is 8
my size is 9
my size is 10
my size is 11
The answer should be from 1 to 10 instead of 2 to 11, i think. What is a better way to get size correctly? Thanks.

After reading your code, I honestly can't figure out what you're trying to do here, but if you're trying to create an array with 11 elements and assign all of them to 5 except for the first one, then you've done an excellent job. Perhaps it would help to see a visualization of the array you've created:
[undef, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
If that's really what you were hoping for, there are faster/simpler/better ways to do the same thing, but I have to believe you were trying to accomplish something else. At a very basic level, arrays in Perl are 0-indexed:
Normal arrays are ordered lists of scalars indexed by number, starting
with 0.
Having said that, you very rarely see the C-style for loop in Perl code, and that's because it's very rarely necessary. More often, you would see something like this:
for (0 .. 9) {
# do something...
}
That code uses a foreach-style loop and the range operator (..) to generate a sequence (technically, a list of values from left to right, counting up by one). Enough about loops. Let's talk about your strange logic.
12 + 22 will always be 5, which will always be greater than 1. The same goes for 2 + 3. There's nothing dynamic about this code, which is why I have to think that you meant to use the loop iterator in your calculations somehow. Otherwise, you could easily fill a 10-element array with a bunch of 5's in one line:
my #x = (5) x 10;
Now, one last point that applies to this code and all Perl code you write from this point forward. Every single file must include the following two lines at the top:
use strict;
use warnings;

I believe that Perl arrays are zero-based, meaning that the first element is stored and accessed at index 0. Here is your for loop:
for ($i=1; $i<=10; $i++) {
if (1**2+2**2>=1) {
#x[$i] =2+3;
$size_x = #x;
}
print "my size is $size_x\n";
}
When you make the first assignment #x[1] = 2 + 3, the array is considered to already have an (empty) element in position zero, so the size is returned as being 2.
The easiest way to avoid this problem from happening would be to refactor your for loop to start at index 0:
for ($i=0; $i<10; $i++) {
...
}

When you start the index from 1 the size automatically increases by 1. Try starting the index from 0 or
#x[$i-1] =2+3;

Just as a side note:
Array elements in Perl are denoted with a starting $, not an #.
So #x is the whole array, while $x[$i] is the $i'th element of the array #x.
use warnings; should warn about this.
(I know this is more a comment than an answer, but as a SO newbie I'm not yet allowed to comment. Sorry.)

Related

algorithm which finds the numbers in a sequence which appear 3 times or more, and prints their indexes

Suppose I input a sequence of numbers which ends with -1.
I want to print all the values of the sequence that occur in it 3 times or more, and also print their indexes in the sequence.
For example , if the input is : 2 3 4 2 2 5 2 4 3 4 2 -1
so the expected output in that case is :
2: 0 3 4 6 10
4: 2 7 9
First I thought of using quick-sort , but then I realized that as a result I will lose the original indexes of the sequence. I also have been thinking of using count, but that sequence has no given range of numbers - so maybe count will be no good in that case.
Now I wonder if I might use an array of pointers (but how?)
Do you have any suggestions or tips for an algorithm with time complexity O(nlogn) for that ? It would be very appreciated.
Keep it simple!
The easiest way would be to scan the sequence and count the number of occurrence of each element, put the elements that match the condition in an auxiliary array.
Then, for each element in the auxiliary array, scan the sequence again and print out the indices.
First of all, sorry for my bad english (It's not my language) I'll try my best.
So similar to what #vvigilante told, here is an algorithm implemented in python (it is in python because is more similar to pseudo code, so you can translate it to any language you want, and moreover I add a lot of comment... hope you get it!)
from typing import Dict, List
def three_or_more( input_arr:int ) -> None:
indexes: Dict[int, List[int]] = {}
#scan the array
i:int
for i in range(0, len(input_arr)-1):
#create list for the number in position i
# (if it doesn't exist)
#and append the number
indexes.setdefault(input_arr[i],[]).append(i)
#for each key in the dictionary
n:int
for n in indexes.keys():
#if the number of element for that key is >= 3
if len(indexes[n]) >= 3:
#print the key
print("%d: "%(n), end='')
#print each element int the current key
el:int
for el in indexes[n]:
print("%d,"%(el), end='')
#new line
print("\n", end='')
#call the function
three_or_more([2, 3, 4, 2, 2, 5, 2, 4, 3, 4, 2, -1])
Complexity:
The first loop scan the input array = O(N).
The second one check for any number (digit) in the array,
since they are <= N (you can not have more number than element), so it is O(numbers) the complexity is O(N).
The loop inside the loop go through all indexes corresponding to the current number...
the complexity seem to be O(N) int the worst case (but it is not)
So the complexity would be O(N) + O(N)*O(N) = O(N^2)
but remember that the two nest loop can at least print all N indexes, and since the indexes are not repeated the complexity of them is O(N)...
So O(N)+O(N) ~= O(N)
Speaking about memory it is O(N) for the input array + O(N) for the dictionary (because it contain all N indexes) ~= O(N).
Well if you do it in c++ remember that maps are way slower than array, so if N is small, you should use an array of array (or std::vector> ), else you can also try an unordered map that use hashes
P.S. Remember that get the size of a vector is O(1) time because it is a difference of pointers!
Starting with a sorted list is a good idea.
You could create a second array of original indices and duplicate all of the memory moves for the sort on the indices array. Then checking for triplicates is trivial and only requires sort + 1 traversal.

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]

Find missing number in an array?

A friend of mine asked this question long time ago. He asked me to this without iterating the array. I had in my mind to find the sum on N number as then subtract from it the sum of array numbers. and another the XOR calculation.
But these solutions still needs to iterate the array.
I wounder if there exists such solution or algorithm to do this without iterating the array.
Also if you are going to flag this question duplicate please refer me the link.
What's the missing number in this array ?
1, 2, 3, 4, 5, 6, *
(The * stands for a number you are not allowed to read, otherwise that would be iterating.)
If there is a missing number in an array you have to inspect it, meaning iterate of the array. No way to do th is without iterating.
In general case, you can't do this. Imagine, that you're given Yves Daoust's sample:
[1, 2, 3, 4, 5, 6, ?]
and you're allowed to read any items of the array, but the last one. What is it? Do I hear seven? No, that's a typical wrong solution:
item = i + (i-1)*(i-2)*(i-3)*(i-4)*(i-5)*(i-6)*F(i)
where F(i) is an arbitrary function (well, not arbitrary, there're some loose restrictions, however - F(i) can't be, say 1/(i-3)). Let
F(i) == 0 -> last item == 7
F(i) == 1 -> last item == 727
F(i) == (pi-i)/720 -> last item == pi
...
You have to have more restrictions, e.g. array represents values of a polynom of the least possible power; in that case the solution is 7

Array Addition, why start at 'i = 2'?

Using the Ruby language, have the function ArrayAdditionI(arr) take the array of numbers stored in arr and return the string true if any combination of numbers in the array can be added up to equal the largest number in the array, otherwise return the string false. For example: if arr contains [4, 6, 23, 10, 1, 3] the output should return true because 4 + 6 + 10 + 3 = 23. The array will not be empty, will not contain all the same elements, and may contain negative numbers.
Could someone please explain to me why this code starts at 'i=2' and not 'i=0'?
def ArrayAdditionI(arr)
i = 2
while i < arr.length
return true if arr.combination(i).map{|comb| comb.inject(:+)}.include?(arr.max)
i += 1
end
false
end
ArrayAdditionI(STDIN.gets)
Correct me if I'm wrong but with i=2, the while loop will iterate [2..4] and then stop. But does this allow for all the potential combinations?...=> code works, so obviously it does but I'm just not seeing it.
i is not the index of the array it the number of elements that is being used to create a combination. So if the max number in the array can be made with the sum of just two elements it stops if not it tries three and so on.
array.combination(i) returns all possible combination of elements in an array with length i.
For example
if
ar=[4, 6, 23, 10]
then
array.combination(2).to_a
returns
[[4,6],[4,23],[4,10],[6,23],[6,10],[23,10]]
So basically you need to find sum in your program and getting sum requires combinations of length two (You need to operands in all possible combination ). Hence you don't start with i=0 or i=1.
You can not give it an empty array,so 0 leads to false. If you have 1 element in an array,it is also meaningless. So I guess 2 is a starting point which makes this test meaningful.

How to slice array in GUI function?

Because I am trying to let a GUI element slice my array, there will be a : (colon) sign in the variables. This returns me an error:
Error in gui_mainfcn (line 96)
feval(varargin{:});
line 96 refers to this code:
image(handles.data(1:handles.rows,1:handles.cols, temp))
Temp looks like this
temp =
1 1 1 1 2 1 1 1 1
And both handles.rows and cols are the value 64. So the problem seems to be that I use colons in the gui function. However, to slice I need to use colons. My question now is: Any idea how to work around this?
To clarify as requested below
The above code works when I manually enter it in the console. Also when I use handles.data(:,:,1,1,1,1,2,1,1,1,1), handles.data(1:end,1:end,1,1,1,1,2,1,1,1,1), handles.data(1:64,1:64,1,1,1,1,2,1,1,1,1), etc I get the same error from the gui. Manually they all work and return a 64 by 64 array of doubles which I can plot with image().
Might be related to these questions, however those deal with parfor difficulties and dont seem to answer my question:
matlab-parfor-slicing-issue
index-inside-parfor-slicing
I am now also reading the advanced topics for slicing variables. Still dont see what I am doing wrong though, so any help or explanation would still be greatly apprectiated. Thanks!
Explanation
By putting the vector temp as the third index into your data, you are not indexing the higher dimensions - you are repeatedly indexing the third. In other words, you get handles.data(:,:,[1 1 1 1 2 1 1 1 1]) instead of handles.data(:,:,1,1,1,1,2,1,1,1,1).
Solution
Here's a solution that doesn't require squeeze or eval. It exploits the comma-separated lists output of the {:} syntax with cell arrays, and the ability to apply linear indexing on the last subscripted dimension.
ctemp = num2cell(temp); % put each index into a cell
sz = size(handles.data); % i.e. sz = [256 256 1 1 2 1 2]
sliceind = sub2ind(sz(3:end),ctemp{:}); % compute high dim. linear index (scalar)
image(handles.data(:,:,sliceind));
This performs subscripting of a >3D array with only 3 subscripts by computing the last subscript as a linear index. It's weird, but convenient sometimes.
A heads up for people with the same problem, this error can not only result from not knowing how to slice, it could also result from not having defined your variables correctly: http://www.mathworks.nl/matlabcentral/answers/87417-how-to-slice-inside-gui-without-error-feval-varargin

Resources