dragons and factorials (keyboard input)

T

Thufir

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
 
T

Thufir

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! :)
 
B

bbxx789_05ss

Thufir said:
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
 
M

mo_mail

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.
 
B

bbxx789_05ss

Thufir said:
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

??
 
T

tim.pease

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
 
T

Thufir

On Nov 3, 12:59 pm, (e-mail address removed) 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
 
T

Todd Benson

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
 
T

Thufir

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
 
T

Todd Benson

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

Todd
 
T

Thufir

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 :)



-Thufir
 
T

Todd Benson

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 :)



-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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top