Dragons and factorials (keyboard input)

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 .
11/03/2007 12:15 PM …
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:infact’
from C:/code/makeDragon.rb:16

C:\code>
C:\code>

thanks,

Thufir

On Sat, 3 Nov 2007, Thufir wrote:

puts "\nenter an integer "
number=gets

Add number = number.to_i or number = Integer(number)

gets returns a string, so you need to convert it to an integer.

print “\n\n\n” + number + “\n\n”

print “Dragon replies\n\n”
print fact(number)

Aditya

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

Might I recommend that you read a book about Ruby and/ or programming (I
think Ruby). In either case, reading Chris P.'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.

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! :slight_smile:

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

??

On Nov 3, 12:59 pm, [email protected] 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

On 11/3/07, Thufir [email protected] 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

On Nov 6, 4:12 pm, Todd B. [email protected] 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

On Nov 6, 2007 10:55 PM, Thufir [email protected] 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

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

On Nov 7, 2007 3:00 PM, Thufir [email protected] wrote:

Thanks for the response, Todd. I kinda sorta follow what you were
doing, but that’s good, I can come back to it later as I get better :slight_smile:

-Thufir

Well I sorta kinda screwed up. The Math in the original should be M.
I guess that’s what happens when you can’t cut and paste. It brings
up an interesting point for you, though. You could just add the
factorial method to the existing module Math yourself on the fly.

#reopen Math module
module Math
def self.factorial n
#whatever factorial technique you want here
end
end

Todd

Thanks for the response, Todd. I kinda sorta follow what you were
doing, but that’s good, I can come back to it later as I get better :slight_smile:

-Thufir