[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

dragons and factorials (keyboard input

Thufir Hawat

11/3/2007 7:32:00 PM

I'm getting keyboard input successfully, but I'm getting a string. I
need to convert it to a number. But ruby is a dynamic language?
What's happening please?

(Did I mention that this list is awesome?)

Here's what I have:

C:\code>
C:\code>
C:\code>dir
Volume in drive C has no label.
Volume Serial Number is 0491-510F

Directory of C:\code

11/03/2007 12:15 PM <DIR> .
11/03/2007 12:15 PM <DIR> ..
11/03/2007 11:42 AM 827 Creature.rb
11/03/2007 11:35 AM 122 doFactorial.rb
11/03/2007 11:58 AM 449 Dragon.rb
11/03/2007 11:34 AM 114 factorial.rb
11/03/2007 11:32 AM 353 Hello.rb
11/03/2007 12:17 PM 71 input.rb
11/03/2007 12:25 PM 283 makeDragon.rb
7 File(s) 2,219 bytes
2 Dir(s) 28,967,956,480 bytes free

C:\code>
C:\code>type Dragon.rb
require 'Creature'

class Dragon < Creature
life 1340 # tough scales
strength 451 # bristling veins
charisma 1020 # toothy smile
weapon 939 # fire breath

def toString()

print "\n\n\nThis Dragon\n"
print "-------------------"

print "\nLife:\t\t"
print life

print "\nStrength:\t"
print strength

print "\nCharisma:\t"
print charisma

print "\nWeapon:\t\t"
print weapon
print "\n\n\n\n"
end
end
C:\code>
C:\code>type Creature.rb
# The guts of life force within Dwemthy's Array
class Creature
# Get a metaclass for this class
def self.metaclass; class << self; self; end; end
# Advanced metaprogramming code for nice, clean traits
def self.traits( *arr )
return @traits if arr.empty?
# 1. Set up accessors for each variable
attr_accessor *arr
# 2. Add a new class method to for each trait.
arr.each do |a|
metaclass.instance_eval do
define_method( a ) do |val|
@traits ||= {}
@traits ||= {}
@traits[a] = val
end
end
end
# 3. For each monster, the `initialize' method
# should use the default number for each trait.
class_eval do
define_method( :initialize ) do
self.class.traits.each do |k,v|
instance_variable_set("@#{k}", v)
end
end
end
end
# Creature attributes are read-only
traits :life, :strength, :charisma, :weapon
end
C:\code>
C:\code>type factorial.rb
def fact(n)
if n <= 1
1
else
n * fact(n - 1)
end
end
C:\code>
C:\code>type makeDragon.rb
require 'Dragon'
require 'factorial'

aDragon = Dragon.new

aDragon.toString

number=0
print "\n\n\nthe Dragon will calculate a factorial now."
puts "\nenter an integer "
number=gets

# print "\n\n\n" + number + "\n\n"

print "Dragon replies\n\n"
print fact(number)
C:\code>
C:\code>
C:\code>makeDragon.rb



This Dragon
-------------------
Life: 1340
Strength: 451
Charisma: 1020
Weapon: 939






the Dragon will calculate a factorial now.
enter an integer
9
Dragon replies

../factorial.rb:2:in `<=': comparison of String with 1 failed
(ArgumentError)
from ./factorial.rb:2:in `fact'
from C:/code/makeDragon.rb:16

C:\code>
C:\code>




thanks,

Thufir

12 Answers

Aditya Mahajan

11/3/2007 7:40:00 PM

0

Thufir Hawat

11/3/2007 7:44:00 PM

0

I googled, didn't find the answer, posted, googled more, found the
answer:

C:\code>
C:\code>
C:\code>
C:\code>
C:\code>type makeDragon.rb
require 'Dragon'
require 'factorial'

aDragon = Dragon.new

aDragon.toString

number=0
print "\n\n\nthe Dragon will calculate a factorial now."
puts "\nenter an integer "
#number=gets
number = gets.chomp.to_i

# print "\n\n\n" + number + "\n\n"

answer=fact(number)
print "Dragon replies\n\n"
print answer
#print fact(number)
C:\code>
C:\code>makeDragon.rb



This Dragon
-------------------
Life: 1340
Strength: 451
Charisma: 1020
Weapon: 939






the Dragon will calculate a factorial now.
enter an integer
11
Dragon replies

39916800
C:\code>




A bit chagrined,

Thufir





ps: I'm thinking about class, inheritance and so forth. I'm going to
review another thread where I was asking about the ruby equivalent to
"static class methods" for, specifically, the factorial which I want
ensure cannot be instantiated. I know it's an object, because
everything's an object in Ruby, but have to think about that one.

I think I also want to make some private methods, and a friend was
suggesting to insert some error if the Dragon has low intelligence! :)

7stud --

11/3/2007 7:45:00 PM

0

Thufir wrote:
> I'm getting keyboard input successfully, but I'm getting a string. I
> need to convert it to a number. But ruby is a dynamic language?
> What's happening please?
>
><snip -- too much to read through>
>

Look at this and see if it helps:

print "Enter an integer: "
str_int = gets

print "Enter a float: "
str_float = gets

the_int = str_int.to_i
the_float = str_float.to_f

puts the_int + the_float

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

Mohit Sindhwani

11/3/2007 8:10:00 PM

0

Might I recommend that you read a book about Ruby and/ or programming (I
think Ruby). In either case, reading Chris Pine's "How to Program" will
give you all that you need to know about walking - and I think you'll be
able to run after that.

Things like to_i and to_s, etc. are quite elementary to any language
and are covered in detail in books about the language.

Cheers,
Mohit.
11/4/2007 | 4:08 AM.

Thufir wrote:
> I googled, didn't find the answer, posted, googled more, found the
> answer:
>
> C:\code>
> C:\code>
> C:\code>
> C:\code>
> C:\code>type makeDragon.rb
> require 'Dragon'
> require 'factorial'
>
> aDragon = Dragon.new
>
> aDragon.toString
>
> number=0
> print "\n\n\nthe Dragon will calculate a factorial now."
> puts "\nenter an integer "
> #number=gets
> number = gets.chomp.to_i
>
> # print "\n\n\n" + number + "\n\n"
>
> answer=fact(number)
> print "Dragon replies\n\n"
> print answer
> #print fact(number)
> C:\code>
> C:\code>makeDragon.rb
>
>
>
> This Dragon
> -------------------
> Life: 1340
> Strength: 451
> Charisma: 1020
> Weapon: 939
>
>
>
>
>
>
> the Dragon will calculate a factorial now.
> enter an integer
> 11
> Dragon replies
>
> 39916800
> C:\code>
>
>
>
>
> A bit chagrined,
>
> Thufir
>
>
>
>
>
> ps: I'm thinking about class, inheritance and so forth. I'm going to
> review another thread where I was asking about the ruby equivalent to
> "static class methods" for, specifically, the factorial which I want
> ensure cannot be instantiated. I know it's an object, because
> everything's an object in Ruby, but have to think about that one.
>
> I think I also want to make some private methods, and a friend was
> suggesting to insert some error if the Dragon has low intelligence! :)
>
>
>
>
>



7stud --

11/3/2007 8:21:00 PM

0

Thufir wrote:
> I googled, didn't find the answer, posted, googled more, found the
> answer:
>
> number = gets.chomp.to_i
>

------------------------------------------------------------ String#to_i
str.to_i(base=10) => integer
------------------------------------------------------------------------
Returns the result of interpreting ***leading characters*** in
_str_ as
an integer... .Extraneous characters
past the end of a valid number are ****ignored***.

If there is not a valid
number at the start of _str_, +0+ is returned. This method never
raises an exception.


----------------------------------------------------------- String#chomp
str.chomp(separator=$/) => new_str
------------------------------------------------------------------------
Returns a new +String+ with the given record separator removed from
the end of _str_ (if present)....

"hello".chomp #=> "hello"
"hello\n".chomp #=> "hello"
"hello\r\n".chomp #=> "hello"
"hello\n\r".chomp #=> "hello\n"
"hello\r".chomp #=> "hello"
"hello \n there".chomp #=> "hello \n there"
"hello".chomp("llo") #=> "he"




Based on those descriptions will the result returned by

input.chomp().to_i

be any different than the result returned by:

input.to_i

??
--
Posted via http://www.ruby-....

Tim Pease

11/3/2007 8:59:00 PM

0

On Nov 3, 2007, at 1:35 PM, Thufir wrote:

> I'm getting keyboard input successfully, but I'm getting a string. I
> need to convert it to a number. But ruby is a dynamic language?
> What's happening please?
>

Others have already answered your question, and it appears you
figured it out or yourself, too.

Ruby does not perform coercion on strings. Perl allows you to do
this ...

1 + "2" #=> 3

However, Matz decided to make type coercion the responsibility of the
programmer and not the programming language. Whenever input is read
(from a file or the command line) it is returned as a string. It is
up to your program to convert that string into an Integer, a Float,
and imaginary number, etc. In ruby you would need to write ...

1 + Integer("2") #=> 3
1 + "2".to_i #=> 3
1 + "2" #=> raises an error

You can write your own coerce method for the string class, if you are
so inclined, in order to make ruby strings behave like Perl strings.

class String
def coerce( other )
case other
when Integer: [other, Integer(self)]
when Float: [other, Float(self)]
else raise TypeError, "can't coerce into '#{other.class.name}'" end
end
end

WIth a coerce method defined for String, you can now write the
following in Ruby ...

1 + "2" #=> 3

Blessings,
TwP

Thufir Hawat

11/6/2007 9:12:00 PM

0

On Nov 3, 12:59 pm, tim.pe...@gmail.com wrote:
[...]
> WIth a coerce method defined for String, you can now write the
> following in Ruby ...
>
> 1 + "2" #=> 3
[...]

In Java String is immutable partly for security reasons. I don't see
that security is a concern with Ruby, however. No?



thanks,

Thufir

Todd Benson

11/7/2007 12:12:00 AM

0

On 11/3/07, Thufir <hawat.thufir@gmail.com> wrote:

> ps: I'm thinking about class, inheritance and so forth. I'm going to
> review another thread where I was asking about the ruby equivalent to
> "static class methods" for, specifically, the factorial which I want
> ensure cannot be instantiated. I know it's an object, because
> everything's an object in Ruby, but have to think about that one.

You want to avoid method's being instantiated per object? You can
attach the method directly to a class...

class C
def self.fact
puts "factorial goes here"
end
end
C.fact

...or to a module...

module M
def fact
puts "factorial goes here"
end
end
include M
foo

...or to a module while preserving namespace...

module M
def self.fact
puts "factorial goes here"
end
end
M::foo

For factorial, I like the Rubyish...

def fact n
(1..n).inject { |fact, i| fact * i }
end

...unless there is some performance thing I'm not aware of (or I'm
answering the wrong question).

Todd

Thufir Hawat

11/7/2007 4:53:00 AM

0

On Nov 6, 4:12 pm, Todd Benson <caduce...@gmail.com> wrote:
[...]
> You want to avoid method's being instantiated per object? You can
> attach the method directly to a class...

For instance:

C:\code>
C:\code>
C:\code>type factorial.rb
def fact(n)
if n <= 1
1
else
n * fact(n - 1)
end
end
C:\code>
C:\code>


I think that factorial would best be a module, as module's cannot be
instantiated. However, I would also want to prevent factorial from
being extended so that nothing "from" it can be instantiated. The
idea of a factorial "object", or an object which descends from it,
strikes me as ludicrous. Is this un-ruby-ish thinking?


-Thufir

Todd Benson

11/7/2007 9:53:00 AM

0

On Nov 6, 2007 10:55 PM, Thufir <hawat.thufir@gmail.com> wrote:

>
> I think that factorial would best be a module, as module's cannot be
> instantiated. However, I would also want to prevent factorial from
> being extended so that nothing "from" it can be instantiated. The
> idea of a factorial "object", or an object which descends from it,
> strikes me as ludicrous. Is this un-ruby-ish thinking?

No, not really. But keep in mind you can always make a copy of a
method on the fly in Ruby (unless $SAFE level alters this behavior;
which I'm not sure of)...

module M
def self.factorial n; (1..n).inject { |f,i| f * i }; end
end

class C; end

c.extend(M)
c.fact # will result in error, which is what you want
m = Math.method(:factorial)
m.call 3 # will result in 6
Math.method(:factorial) == Math.method(:factorial)
# will result in true
Math.method(:factorial).object_id == Math.method(:factorial).object_id
# will result in false on my machine, but that's what I expect

> -Thufir

Todd