Class and inheritance

Hi All,

I am not a programmer, yet. I am trying ruby on for size, most things
fit ok, but Classes are puzzling me.

<code>
class Roll
         def Roll(base,range)
           @base=base
           @range=range
          @roll = base+random(range)
         end
end

class Stats
    def power
     @power=Roll.new(10,8)
     end
    def speed
      @speed=Roll.new(10,8)
     end
    def smarts
     @smarts=Roll.new(10,8)
    end
end

class Attribs < Stats
   def acc
      @acc=0.75*self.power+(self.speed/self.smarts)
   end
    def health
    @health = self.power*(self.smarts/self.speed)
  end
end
class Npc < Attribs
  def name(name)
@name=name
end
end

joe=Npc.new
joe.name('Joe')
#puts joe.name.to_s+' = name'
puts joe.power.to_s+' = power'
puts joe.smarts.to_s+' = smarts'
puts joe.speed.to_s+' = speed'
puts joe.health.to_s+' = health'
puts joe.acc+' = acc'
puts joe
puts '======================='
puts 'Calculations'
puts 0.75*joe.power+(joe.speed/joe.smarts)
</code>

OK, so why is this broken?

Hi.

I am not a programmer, yet. I am trying ruby on for size, most things
fit ok, but Classes are puzzling me.

<code>
class Roll
  def Roll(base,range)

     @power=Roll.new(10,8)

OK, so why is this broken?

The constructor in ruby is named initialize, not the name of the class
like in Java. Try :

class Roll
  def initialize(base, range)
    ...
  end
  ...
end

Fred

···

Le 03 mars à 16:03, August0866 a écrit :
--
- The light at the end of the tunnel is the explosives around that
  little ball of Pu239. (Mike Andrews in the SDM)
- The darkness at the end of the tunnel is an oncoming train with
  broken headlights. (Lars Balker Rasmussen in the SDM)

There are many reasons your code doesn't work. Let's see what happens running
it in ruby (by the way, when asking for help about a piece of code which
produces an error, it's better to also show the error message):

* FIRST TRY:
./prova.rb:13:in `initialize': wrong number of arguments (2 for 0)
(ArgumentError)

This means that some initialize method is called with 2 arguments, when it
should receive no argument on line 11. The line in question is:

@power = Roll.new(10, 8)

Apparently, there's no call to initialize here. What you're trying to do in
this line, is to create an instance of class Roll, calling Roll.new. For most
classes, the 'new' method first creates a new object, then calls its
'initialize' method, which, as the name implies, is used to perform
initialization on the object (for example, giving starting values to instance
variables). Since you didn't define an initialize method for class Roll, it
uses the one defined for the parent class, which is Object.
The initialize method defined for class Object takes no argument, so you get
an error.

Looking at the definition of class Roll, i see you defined a method called
Roll, which takes two arguments and sets instance variables, just like
initialize should do. I guess you thought that method would have been called
by new. Let's rename it to initialize and see if it solves the problem.

* SECOND TRY:
./prova.rb:5:in `initialize': undefined method `random' for #<Roll:0xb7c10c70
@range=8, @base=10> (NoMethodError)

This is easy: you're calling a method named 'random', which doesn't exist.
The method which generates a random number in ruby is called rand, so we'll
replace random with rand

* THIRD TRY:
./prova.rb:26:in `health': undefined method `/' for #<Roll:0xb7beeb34
@range=8, @base=10, @roll=15> (NoMethodError)
        from ./prova.rb:41

Now, ruby hits an error while calling the health method: in particular, in
line 26 there's a call to a method '/' which is undefined. Line 26 is:

@health = self.power*(self.smarts/self.speed)

In ruby, operators such as +, -, * and / are simply methods, so that when you
write, for example 2 + 3, ruby calls the '+' method of the object 2 passing
it the object 3 as argument. In your code, you're dividing self.smarts by
self.speed, which are both of class Roll. Class Roll doesn't have a method
called '/', so you get the error.

This problem could be solved defining a sensible / method for class Roll, or,
more simply, by defining a method which allows to get the value of the
variable @roll of an instance of roll (which is a number), and use that
instead of the instance of Roll itself. It may be worth asking whether class
Roll really needs to exist. If you won't require the @base and @range values
somewhere else, then it would be much easier to replace the whole class with
a method such as this:

def roll(base, range)
  base + rand(range)
end

At any rate, let's assume that Roll needs to be a class and add a method
which allows to extract the @roll instance variable. We could define it by
hand, but ruby does it automatically if we add this line inside class Roll:

attr_reader :roll

This generates a method called roll which returns @roll.

Then, we need to replace speed and smarts and power with speed.roll,
smarts.roll and power.roll in lines 24, 26 and 47 (we would get an analogous
problem with the acc method if we leaved it as it is).

* FOURTH TRY
#<Roll:0xb7cd0b60> = power
#<Roll:0xb7cd0afc> = smarts
#<Roll:0xb7cd0aac> = speed
0 = health
./prova.rb:43:in `+': String can't be coerced into Float (TypeError)
        from ./prova.rb:43

Before looking at the error, there are two things to notice: first, power,
smarts and speed aren't numbers but instances of class Roll. If this isn't
what you expected, then most likely you should replace class Roll with the
method roll as I mentioned above. Second, health is 0 (of course, this will
depend on the random number which have been generated). Since both
smarts.roll and speed.roll are integers, the division will return 0 if the
divider is greater than the divisor. To avoid this, add a call to to_f to one
of the operands. to_f will convert the integer to a float, so the division
will use decimals.

Looking at the error, it simply means that, in line 43, we're trying to add a
number with a string. The reason is simply that you forget to call the to_s
method on joe.acc as you did for the other ones.

* FIFTH TRY
#<Roll:0xb7c79af4> = power
#<Roll:0xb7c79a90> = smarts
#<Roll:0xb7c79a40> = speed
10 = health
10.75 = acc
#<Npc:0xb7c79b6c>

code.rb (958 Bytes)

···

On Monday 03 March 2008, August0866 wrote:

Hi All,

I am not a programmer, yet. I am trying ruby on for size, most things
fit ok, but Classes are puzzling me.

<code>
class Roll
         def Roll(base,range)
           @base=base
           @range=range
          @roll = base+random(range)
         end
end

class Stats
    def power
     @power=Roll.new(10,8)
     end
    def speed
      @speed=Roll.new(10,8)
     end
    def smarts
     @smarts=Roll.new(10,8)
    end
end

class Attribs < Stats
   def acc
      @acc=0.75*self.power+(self.speed/self.smarts)
   end
    def health
    @health = self.power*(self.smarts/self.speed)
  end
end
class Npc < Attribs
  def name(name)
@name=name
end
end

joe=Npc.new
joe.name('Joe')
#puts joe.name.to_s+' = name'
puts joe.power.to_s+' = power'
puts joe.smarts.to_s+' = smarts'
puts joe.speed.to_s+' = speed'
puts joe.health.to_s+' = health'
puts joe.acc+' = acc'
puts joe
puts '======================='
puts 'Calculations'
puts 0.75*joe.power+(joe.speed/joe.smarts)
</code>

OK, so why is this broken?

=======================
Calculations
11.5

Now, it works.

Attached, you'll find a copy of the code with all the modifications I spoke
about.

I hope this helps

Stefano

ok, new attempt

class Roll
         def initialize(base, range)
          @roll = base+rand(range)
          return @roll
         end
end

class Stats
    def power
      @power=Roll.new(10,8)
    end

    def speed
      @speed=Roll.new(10,8)
    end

    def smarts
     @smarts=Roll.new(10,8)
    end
  end

class Attribs < Stats
   def acc
      @acc=self.power+(self.speed / self.smarts)# doesnt want to do
the math ?Why?
    end

    def health
      @health = 0.00+self.power*(self.smarts/self.speed)# doesnt want
to do the math ?Why?
    end
  end
  class Npc < Attribs
      def initialize(name)
        @name=name
      end
      def job
          puts 'stuff'
      end
  end

class Test
  def test
    a=Roll.new(10,8)
    b=Stats.new
    c=Attribs.new
    d=Npc.new('Joe')

    puts '++++++++++++++++A+++++++++++++++++++'
    puts 'a object is '+a.to_s
    puts 'a\'s method is called roll '+a.inspect
    puts '++++++++++++++++A+++++++++++++++++++'
    puts '================B==================='
    puts 'b is object '+b.inspect.to_s
    puts 'b methods are power = '+b.power.to_s
    puts ', speed ='+b.speed.to_s
    puts ', and finaly smarts = '+b.smarts.to_s
    puts '================B=================='
    puts '________________C__________________'
    puts 'now on to c'
    puts c.to_s+' is the object name for c'
    puts 'c has all the methods of a and b plus its own'
    puts ' c has a power of '+c.power.inspect.to_s
    puts ' c has a speed of '+c.speed.inspect.to_s
    puts ' c has a smarts of '+c.smarts.inspect.to_s
    puts ' plus c has an Accuracy of '+c.acc.to_s
    puts ' plus c has a health of '+c.health.to_s
    puts '________________C____________________'
    puts '||||||||||||||||D||||||||||||||||||||'

    puts 'D is the goal'
    puts d.inspect

  end
end
s=Test.new
puts s.test

···

On Mar 3, 10:15 am, "F. Senault" <f...@lacave.net> wrote:

Le 03 mars à 16:03, August0866 a écrit :

Hi.

> I am not a programmer, yet. I am trying ruby on for size, most things
> fit ok, but Classes are puzzling me.

> <code>
> class Roll
> def Roll(base,range)
> @power=Roll.new(10,8)
> OK, so why is this broken?

The constructor in ruby is named initialize, not the name of the class
like in Java. Try :

class Roll
  def initialize(base, range)
    ...
  end
  ...
end

Fred

My intent is when i call class Npc(str) i want to get back
3 random values power,speed,smarts 2 derived values => accuracy and =>
health and a derived string => job

like this
joe=Npc.new('Joe')
puts joe

output like "Joe" 11 12 15 10.15 8.8 "smithy"

Ok. Here's an adapted version of your code.

- I gave you the way to create a "Roll" objetct, but you don't really
    need it ; what you need is an "helper function" that returns a
    number. So, I made a module to contain it.
- Constructors in Ruby _always_ return the new object, regardless of the
    explicit return clause.
- Rolling dice every time you access one of your base characteristics is
    not the way to go ; here, I assign them at constructing time, and
    give them an accessor.
- Using the #{} interpolation mechanism is way more legible than the
    concatenation with xxx.to_s (BTW, inspect returns a string, no need
    for to_s).
- Puts returns nil, not the string passed ; puts test where your test
    method itself is writing on the screen is useless.
- If you want to convert your object to a string (for instance for
    puts), all you need to do is define a to_s method.

Oh, and last : you should _really_ pay attention to the formatting of
your code...

class Roll
  def Roll.roll(base, range)
    base+rand(range)
  end
end

class Stats
  attr_reader :power, :speed, :smarts
  def initialize()
    @power = Roll.roll(10,8)
    @speed = Roll.roll(10,8)
    @smarts = Roll.roll(10,8)
  end
end

class Attribs < Stats
  def acc
    (@power.to_f + (@speed.to_f / @smarts.to_f)).round
  end

  def health
    (@power.to_f * (@smarts.to_f / @speed.to_f)).round
  end
end

class Npc < Attribs
  def initialize(name)
    @name = name
    super()
  end
  def job
    'stuff'
  end
  def to_s
    "#{@name} - pw#{power}, sp#{speed}, sm#{smarts}, ac#{acc}, "\
      "he#{health} - #{job}"
  end
end

class Test
  def test
    a = Roll.roll(10,8)
    b = Stats.new
    c = Attribs.new
    d = Npc.new('Joe')

    puts "++++++++++++++++A+++++++++++++++++++"
    puts "a object is #{a.to_s}"
    puts "a's method is called roll #{a.inspect}"
    puts "++++++++++++++++A+++++++++++++++++++"
    puts "================B==================="
    puts "b is object #{b.inspect}"
    puts "b methods are power = #{b.power}, "
    puts "speed = #{b.speed}, "
    puts "and finaly smarts = #{b.smarts.to_s}"
    puts "================B=================="
    puts "________________C__________________"
    puts "now on to c"
    puts "#{c.to_s} is the object name for c"
    puts "c has all the methods of a and b plus its own"
    puts " c has a power of #{c.power}"
    puts " c has a speed of #{c.speed}"
    puts " c has a smarts of #{c.smarts}"
    puts " plus c has an Accuracy of #{c.acc}"
    puts " plus c has a health of #{c.health}"
    puts "________________C____________________"
    puts "||||||||||||||||D||||||||||||||||||||"

    puts 'D is the goal'
    puts d.inspect
    puts d

  end
end
s=Test.new
s.test

Fred

···

Le 03 mars à 17:53, August0866 a écrit :

My intent is when i call class Npc(str) i want to get back
3 random values power,speed,smarts 2 derived values => accuracy and =>
health and a derived string => job

like this
joe=Npc.new('Joe')
puts joe

output like "Joe" 11 12 15 10.15 8.8 "smithy"

--
Yes, Java is so bulletproofed that to a C programmer it feels like
being in a straightjacket, but it's a really comfy and warm
straightjacket, and the world would be a safer place if everyone was
straightjacketed most of the time. (Mark Hughes in the SDM)

Thank you for taking time i appreciate the help,

Oh, and last : you should _really_ pay attention to the formatting of
your code...

being painfully new at this i don't know what you mean, what can i do
better format wise next time

···

On Mar 3, 1:01 pm, "F. Senault" <f...@lacave.net> wrote:

Le 03 mars à 17:53, August0866 a écrit :

Hi,

- I gave you the way to create a "Roll" objetct, but you don't really
   need it ; what you need is an "helper function" that returns a
   number. So, I made a module to contain it.

class Roll

def Roll.roll(base, range)
   base+rand(range)
end
end

You could use a regular ol'module for that:

module Roll
  def self.roll(base, range)
    base + rand(range)
  end
end

Arlen

···

On Tue, Mar 4, 2008 at 5:04 AM, F. Senault <fred@lacave.net> wrote:

First and before all, indentation. Try to indent your statements by two
spaces, and to keep the code aligned (the end keyword should be at the
same column than the corresponding def or class keyword, etc).

After that, try to add some space around operators and such.

It makes code much more legible, which is important when you write code
that you'll have to understand later, and doubly so if you post it to a
public forum where _other_ people have to understand it...

CYA,

Fred

···

Le 03 mars à 20:39, August0866 a écrit :

On Mar 3, 1:01 pm, "F. Senault" <f...@lacave.net> wrote:

Oh, and last : you should _really_ pay attention to the formatting of
your code...

being painfully new at this i don't know what you mean, what can i do
better format wise next time

--
- I've always maintained that no software should be released that can't
withstand three hours of enthusiastic yet undirected pounding-on by a
typical five-year-old. - You've just described Microsoft's entire
development process. (Joe Thompson & Malcolm Ray in the SDM)

Indeed. I wanted to make that modification, but it seems I forgot it...
Thanks.

Fred

···

Le 04 mars à 06:52, Arlen Cuss a écrit :

You could use a regular ol'module for that:

module Roll
  def self.roll(base, range)
    base + rand(range)
  end
end

--
All that is now All that is gone All that's to come
And everything under the sun is in tune
But the sun is eclipsed by the moon
                                                   (Pink Floyd, Eclipse)

OK, 2 dumb questions What is the difference between a class and a
module and

What is wrong here, the logic or the syntax

<stub location =( class => Npc, def => job)>

  def job
       if
         @power.to_f > 12 && @smarts.to_f > 14 && @speed.to_f > 14
         @job = 'Adventurer'
    elsif
      @power.to_f > 14 and (@smarts.to_f <14 or @speed.to_f < 14)
        @job = 'laborer'
    elsif
        @power.to_f < 14 and (@smarts.to_f > 14 and @speed.to_f > 14)
        @job = 'coureror'
    elsif
        @power.to_f < 14 and (@smarts.to_f > 14 and @speed.to_f < 14)
        @job='teacher'
    else
        @job = 'commoner'
    end
end
</stub>

the result is sometimes joe is an adventurer otherwise nothing is
output

A module is a container for methods and a namespace
for constants.

A class is a module (Class inherits from Module) that
provides a framework for instantiating and initializing
instances as well as organizing method lookup through
the inheritance hierarchy.

If you think of classes as blueprints for creating
instances, then modules are like common sub-systems
that are reused in the blueprints of one or more
classes.

Gary Wright

···

On Mar 4, 2008, at 9:50 AM, August0866 wrote:

OK, 2 dumb questions What is the difference between a class and a
module and

Not sure, but I think the logic. (@smarts.to_f < 14 or @speed.to_f <
14) will be true the same time (@smarts.to_f > 14 and @speed.to_f <
14) is true. Your decision set is not mutually exclusive because of
that first 12 (What if your 13?). Just a guess...

Todd

···

On Tue, Mar 4, 2008 at 8:50 AM, August0866 <august0866@hotmail.com> wrote:

OK, 2 dumb questions What is the difference between a class and a
module and

What is wrong here, the logic or the syntax

<stub location =( class => Npc, def => job)>

  def job
       if
         @power.to_f > 12 && @smarts.to_f > 14 && @speed.to_f > 14
         @job = 'Adventurer'
    elsif
      @power.to_f > 14 and (@smarts.to_f <14 or @speed.to_f < 14)
        @job = 'laborer'
    elsif
        @power.to_f < 14 and (@smarts.to_f > 14 and @speed.to_f > 14)
        @job = 'coureror'
    elsif
        @power.to_f < 14 and (@smarts.to_f > 14 and @speed.to_f < 14)
        @job='teacher'
    else
        @job = 'commoner'
    end
end
</stub>

the result is sometimes joe is an adventurer otherwise nothing is
output

> OK, 2 dumb questions What is the difference between a class and a
> module and

> What is wrong here, the logic or the syntax

> <stub location =( class => Npc, def => job)>

> def job
> if
> @power.to_f > 12 && @smarts.to_f > 14 && @speed.to_f > 14
> @job = 'Adventurer'
> elsif
> @power.to_f > 14 and (@smarts.to_f <14 or @speed.to_f < 14)
> @job = 'laborer'
> elsif
> @power.to_f < 14 and (@smarts.to_f > 14 and @speed.to_f > 14)
> @job = 'coureror'
> elsif
> @power.to_f < 14 and (@smarts.to_f > 14 and @speed.to_f < 14)
> @job='teacher'
> else
> @job = 'commoner'
> end
> end
> </stub>

> the result is sometimes joe is an adventurer otherwise nothing is
> output

Not sure, but I think the logic. (@smarts.to_f < 14 or @speed.to_f <
14) will be true the same time (@smarts.to_f > 14 and @speed.to_f <
14) is true. Your decision set is not mutually exclusive because of
that first 12 (What if your 13?). Just a guess...

Todd

Ok, i'm looking for a true false answer to choose a job. For example
Joe - smarts = 15 power = 9 speed = 17

<pseudo code>

          adventurer job needs power >= 12 and speed >=14 and smarts

= 14 ?joe an adventurer = false

          laborer job needs power >= 12 but smarts and speed <=
12 ?joe laborer = false
          mailman job needs power >=12 speed >=12 but smarts

=9 ?joe mailman = false

          teacher job needs power <=14 speed <=14 but smarts

=14 ?joe teacher =

</pseudo code>

D'oh i see the problem..... i need to rethink the jobs

···

On Mar 4, 1:23 pm, Todd Benson <caduce...@gmail.com> wrote:

On Tue, Mar 4, 2008 at 8:50 AM, August0866 <august0...@hotmail.com> wrote:

One other thing, though. Maybe you want your code to cascade the
decision like that. In any case, your code works just fine on my
system, as long as I properly #rand my power, smarts, and speed :slight_smile:
On 1.8.6, the if/elsif construct seems to correctly jump out. In
other words, if my power is 13, then it will will leave the loop with
the second result and never get to the fourth.

My distribution for 10_000 people for one run using rand(20 for each
attribute turns out to be...

adventurer: 211
laborer: 2260
courier: 416
teacher: 1261
commoner: 5852

...which doesn't look too bad.

Todd

···

On Tue, Mar 4, 2008 at 12:23 PM, Todd Benson <caduceass@gmail.com> wrote:

Not sure, but I think the logic. (@smarts.to_f < 14 or @speed.to_f <
14) will be true the same time (@smarts.to_f > 14 and @speed.to_f <
14) is true. Your decision set is not mutually exclusive because of
that first 12 (What if your 13?). Just a guess...

Thanks Todd,

how would i go about defining a job and its requirements and then
match the npc to the job

<pseudo>
            job[[Adventurer,14,14,14],[Courier,14,10,14] .... ]

the numbers are the minimum stats for the job these jobs are actually
categories i am going to break them down to specific occupations
next

</pseudo>

···

On Mar 4, 2:35 pm, Todd Benson <caduce...@gmail.com> wrote:

On Tue, Mar 4, 2008 at 12:23 PM, Todd Benson <caduce...@gmail.com> wrote:

> Not sure, but I think the logic. (@smarts.to_f < 14 or @speed.to_f <
> 14) will be true the same time (@smarts.to_f > 14 and @speed.to_f <
> 14) is true. Your decision set is not mutually exclusive because of
> that first 12 (What if your 13?). Just a guess...

One other thing, though. Maybe you want your code to cascade the
decision like that. In any case, your code works just fine on my
system, as long as I properly #rand my power, smarts, and speed :slight_smile:
On 1.8.6, the if/elsif construct seems to correctly jump out. In
other words, if my power is 13, then it will will leave the loop with
the second result and never get to the fourth.

My distribution for 10_000 people for one run using rand(20 for each
attribute turns out to be...

adventurer: 211
laborer: 2260
courier: 416
teacher: 1261
commoner: 5852

..which doesn't look too bad.

Todd

I'll make a couple assumptions here. I think you want to have minimum
requirements, and then have the job assignment go to the least
requirement. In other words, in your above pseudo, if I had stats
like [14,15,14], I would be an adventurer, and if I had stats
[10,14,14] I would fail to be either (but maybe something else).
Least common denominator?

I would approach it probably in an eccentric way. Most people would
suggest side by side iteration of Arrays (which, IIRC, was added as a
feature to Ruby 1.9). That is probably the best way to do it. I'm
kind of a set theory guy, though, so tend towards slower but
conceptually more sound (to me) methods.

I'd probably build a matrix of the person's stats and use that...

require 'matrix'
joblist = ['adventurer', 'courier']
attributes = ['power', 'smarts', 'speed']
n, j = attributes.length, joblist.length
a = [[14, 14, 14], [14, 10, 14]]
some_poor_guys_stats_copies = Array.new(j, Array.new(n) {rand(20) + 1})
s = Matrix[*some_poor_guys_stats_copies]
e = Matrix[*a]
poss =
(s - e).to_a.each_with_index do |v, i|
  poss << i if (v.select {|j| j >= 0}).length == n
end
p joblist[poss.min] rescue p "Commoner"

It's not even close to clean, but I like using Matrix for this kind of
thing instead of the side by side iterating.

I suppose it's way better to use a Hash, too, like so...

requirements = {
  :adventurer => {
    :power => 14,
    :smarts => 14.
    :speed => 14
  }
  :courier => {
    :power => 14,
    :smarts => 10,
    :speed => 14
}

person = {
  :power => rand(die_number),
  :smarts => rand(die_number),
  :speed => rand(die_number)
}

I'm pretty sure you can use the Hash.new block form to build these if
you wanted to.

I should mention also that many people frown upon using the rescue
word for conditional use (in other words, my code above is not good
for application use, but probably ok for a script).

Todd

···

On Tue, Mar 4, 2008 at 6:04 PM, August0866 <august0866@hotmail.com> wrote:

On Mar 4, 2:35 pm, Todd Benson <caduce...@gmail.com> wrote:

> On Tue, Mar 4, 2008 at 12:23 PM, Todd Benson <caduce...@gmail.com> wrote:
>
> > Not sure, but I think the logic. (@smarts.to_f < 14 or @speed.to_f <
> > 14) will be true the same time (@smarts.to_f > 14 and @speed.to_f <
> > 14) is true. Your decision set is not mutually exclusive because of
> > that first 12 (What if your 13?). Just a guess...
>
> One other thing, though. Maybe you want your code to cascade the
> decision like that. In any case, your code works just fine on my
> system, as long as I properly #rand my power, smarts, and speed :slight_smile:
> On 1.8.6, the if/elsif construct seems to correctly jump out. In
> other words, if my power is 13, then it will will leave the loop with
> the second result and never get to the fourth.
>
> My distribution for 10_000 people for one run using rand(20 for each
> attribute turns out to be...
>
> adventurer: 211
> laborer: 2260
> courier: 416
> teacher: 1261
> commoner: 5852
>
> ..which doesn't look too bad.
>
> Todd

Thanks Todd,

how would i go about defining a job and its requirements and then
match the npc to the job

<pseudo>
            job[[Adventurer,14,14,14],[Courier,14,10,14] .... ]

the numbers are the minimum stats for the job these jobs are actually
categories i am going to break them down to specific occupations
next

I should point out, too, that my use of #min only works if you want to
pick the first on the list that fits. Maybe what you really want are
_all_ the jobs that apply for a person.

Todd

···

On Wed, Mar 5, 2008 at 3:08 AM, Todd Benson <caduceass@gmail.com> wrote:

Least common denominator?

Wow Crunchy code. it will take ma awhile to decipher all the things
going on up there.

originally the idea was first match out. I think that approach may
not be where i end up in the end.

thanks again for the help

···

On Mar 5, 4:36 am, Todd Benson <caduce...@gmail.com> wrote:

On Wed, Mar 5, 2008 at 3:08 AM, Todd Benson <caduce...@gmail.com> wrote:
> Least common denominator?

I should point out, too, that my use of #min only works if you want to
pick the first on the list that fits. Maybe what you really want are
_all_ the jobs that apply for a person.

Todd

With comments...

require 'matrix'
#need this for Matrix class
joblist = ['adventurer', 'courier']
attributes = ['power', 'smarts', 'speed']
n, j = attributes.length, joblist.length
a = [[14, 14, 14], [14, 10, 14]]
#cheating here, need Hash really
some_poor_guys_stats_copies = Array.new(j, Array.new(n) {rand(20) + 1})
#an array of arrays to be a matrix
s = Matrix[*some_poor_guys_stats_copies]
#make the requirements Matrix
#using e for "employment", bad choice
e = Matrix[*a]
poss =
#using poss for possibilities, bad choice
(s - e).to_a.each_with_index do |v, i|
poss << i if (v.select {|j| j >= 0}).length == n
end
p joblist[poss.min] rescue p "Commoner"

Okay, the key here is:

I have two matrices of same dimensions. I take the guys stats,
subtract the requirements, and remove anything that is negative in
each ability check.

I'm not certain at the moment how I would clean that up for production
use, but I have a few ideas. The only dodgy part of the code
(discounting the variable names), IMHO, is the a = [[14, 14, 14], [14,
10, 14]] part. Not because of the logic, but because of the fact
we're depending on the order of the array called "a". Like, what if
somebody changes the attributes array? A Hash object would fit better
here even if it requires more code.

hth,
Todd

···

On Thu, Mar 6, 2008 at 7:20 PM, August0866 <august0866@hotmail.com> wrote:

On Mar 5, 4:36 am, Todd Benson <caduce...@gmail.com> wrote:

> On Wed, Mar 5, 2008 at 3:08 AM, Todd Benson <caduce...@gmail.com> wrote:
> > Least common denominator?
>
> I should point out, too, that my use of #min only works if you want to
> pick the first on the list that fits. Maybe what you really want are
> _all_ the jobs that apply for a person.
>
> Todd

Wow Crunchy code. it will take ma awhile to decipher all the things
going on up there.

originally the idea was first match out. I think that approach may
not be where i end up in the end.

thanks again for the help