Array.sort

Hi,

I’m a novice programmer who is just starting out in Ruby. I’ve been
playing around with arrays and have run into a problem:

This works:

array = [3,2,1]
puts array.sort

=>123

BUT this doesn’t (error attached):

nums = Array.new

numplays = 5

numplays.times do

for values in 1…5
ball = rand(56)
redo if ball == 0 || nums.include?(ball)
nums [values] = ball
end
puts nums.sort
end

Can anyone shed light on this newby?

Alle mercoledì 29 agosto 2007, Mark R. ha scritto:

=>123
ball = rand(56)
redo if ball == 0 || nums.include?(ball)
nums [values] = ball
end
puts nums.sort
end

Can anyone shed light on this newby?

Attachments:
http://www.ruby-forum.com/attachment/183/array_sort.JPG

Your array ends up having 6 elements, the first of which is nil. This
happens
because your values variable starts from 1, while arrays indexes start
at 0.
sort doesn’t work on arrays which contain nil elements, because nil
doesn’t
have the <=> operator, which is used by sort to compare elements. To
solve
your problems, you should replace 1…5 with 0…4 (or use 5.times which,
in my
opinion, is much clearer).

By the way, you can avoid to check whether ball is 0 by replacing

ball = rand(56)

with

ball = rand(55) + 1

I hope this helps

Stefano

On 8/29/07, Mark R. [email protected] wrote:

=>123
ball = rand(56)
redo if ball == 0 || nums.include?(ball)
nums [values] = ball
end
puts nums.sort
end

Can anyone shed light on this newby?

The problem is that you start your array index at 1, not 0.

Orig: for values in 1…5
Mod: for values in 0…4

If you want to see what’s happening in your code, add a ‘puts
nums.inspect’ right after you assign the ball value to nums.

– Stephen

Hi,

On Wed, Aug 29, 2007 at 10:39:21PM +0900, Mark R. wrote:

=>123
ball = rand(56)
redo if ball == 0 || nums.include?(ball)
nums [values] = ball
puts nums.join(‘,’)
end
puts nums.sort
end

Can anyone shed light on this newby?

So what you are attempting to do is generate 25 random numbers between 1
and 55, with no duplicates?

http://www.ruby-forum.com/attachment/183/array_sort.JPG

The problem you are having is that when you get a number, you insert it
into the array at slots 1,2,3,4 and 5. But your array is actually a 0
based index. The first slot is nums[0]. That means when you do your
sort you are sorting for instance [nil,2,32,1,44,26] which is an array
of size 6, and nil doesn’t compare with an integer via the <=> operator.

The simpliest way to solve your issue is to change:

for values in 1..5

to

5.times do |values|

If you want to change it up even more and not have to ‘redo’ then you
might change nums to a Hash and use its keys to hold the ‘ball’ values

nums = {}
while nums.size < 5 do
    ball = rand(55) + 1   # gives a value 1..55
    nums[ball] = ball     # put ball into the hash
end
puts num.keys.sort.join(',')

It appears the basic problem you are doing is to choose 5 distinct
numbers from 1…55 N times. You may want to look at this ruby quiz for
interesting items:

http://www.rubyquiz.com/quiz39.html

enjoy,

-jeremy

Stefano C. wrote:

Alle mercoledì 29 agosto 2007, Mark R. ha scritto:

=>123
ball = rand(56)
redo if ball == 0 || nums.include?(ball)
nums [values] = ball
end
puts nums.sort
end

Can anyone shed light on this newby?

Attachments:
http://www.ruby-forum.com/attachment/183/array_sort.JPG

Your array ends up having 6 elements, the first of which is nil. This
happens
because your values variable starts from 1, while arrays indexes start
at 0.
sort doesn’t work on arrays which contain nil elements, because nil
doesn’t
have the <=> operator, which is used by sort to compare elements. To
solve
your problems, you should replace 1…5 with 0…4 (or use 5.times which,
in my
opinion, is much clearer).

By the way, you can avoid to check whether ball is 0 by replacing

ball = rand(56)

with

ball = rand(55) + 1

I hope this helps

Stefano

Stefano,

Thanks for the quick reply and help, now that you’ve pointed it out it
seems so obvious. The one thing I could not find was a lot of
information on the rand function so your help there is also greatly
appreciated!

Mark

On Aug 29, 8:39 am, Mark R. [email protected] wrote:

=>123
ball = rand(56)

Posted viahttp://www.ruby-forum.com/.

Ah, Stefano got to it before me, but here’s a reworking of it anyway:

numplays = 5
numballs = 5

numplays.times do
nums = Array.new
numballs.times do
ball = rand(55) + 1
redo if nums.include?(ball)
nums.push ball
end
puts ‘nums’
puts nums.sort
end

Mark R. wrote:

for values in 1…5
ball = rand(56)
redo if ball == 0 || nums.include?(ball)
nums [values] = ball
end

nums=(1…55).sort_by {rand}.first(5)

HTH,
Sebastian

Thanks again, its invaluable to see the same actions performed using
different code! I’ve been through many of the tutorials and 100 pages
into “Beginning Ruby on Rails” and have not seen ‘push’ or sorting a
hash using ‘.keys.sort.join(’,’) so again a great help!

On 8/29/07, Mark R. [email protected] wrote:

Thanks again, its invaluable to see the same actions performed using
different code! I’ve been through many of the tutorials and 100 pages
into “Beginning Ruby on Rails” and have not seen ‘push’ or sorting a
hash using ‘.keys.sort.join(’,') so again a great help!

Posted via http://www.ruby-forum.com/.

FYI, you can copy and paste from cmd.exe, you don’t need to take
screenshots. One way is click on the icon in the upper left hand
corner, go do to edit, and then mark, now you can select the text you
need, go back to the edit menu and hit copy.

into “Beginning Ruby on Rails” and have not seen ‘push’ or sorting a
hash using ‘.keys.sort.join(’,') so again a great help!

Posted via http://www.ruby-forum.com/.

FYI, you can copy and paste from cmd.exe, you don’t need to take
screenshots. One way is click on the icon in the upper left hand
corner, go do to edit, and then mark, now you can select the text you
need, go back to the edit menu and hit copy.

You can make that easier by right clicking on the icon in the upper left
and
going to Properties. Select “Quick Edit” mode, and apply. When asked
what
properties to edit (global or this one instance), select “Modify the
link”
and confirm.

Now you can select with the mouse instantly, hitting the Enter key will
put
the selection into the clipboard.

HTH,

Felix