I'd do it something like:
def factorial(number)
(2 .. number).inject(1) { |m, n| m * n }
end
factorial(1) # => 1
factorial(2) # => 2
factorial(3) # => 6
factorial(5) # => 120
inject
is a useful method for things like this, and isn't limited to use with numbers.
It can be written even more concisely:
(1..n).inject(:*) || 1
which comes from "Ruby factorial function". That'll give you something to chew on for a while.
Your code is doing several things that aren't correct:
a
isn't ever defined prior to running, soa*x
is doomed to fail because you can't multiply anil
byx
.upto
will pass the current value into the block asx
, but assigning toa
will fail because it's always a new local variablea
. There is no static memory ofa
unless you define it outside the block's scope.- In a lot of Ruby iterators, the value of the block can be used as a return value.
upto
doesn't work that way. You'll get the seed value returned, so, you'd get back1
.
Working out these sort of problems is best done using IRB, which comes with Ruby. Inside the interactive session you can try variations on your code to see what works. It's a lot faster/easier and more convenient than trying to write a script and go through the edit/run cycle.
What about this:
factorial = Hash.new{ |x,y| x[y]= y<2 ? 1 : x[y-1]*y }
Let's test that out by dropping into IRB to see what it does:
>> factorial = Hash.new{ |x,y| x[y]= y<2 ? 1 : x[y-1]*y }
{}
>> factorial[1]
1
>> factorial
{
1 => 1
}
>> factorial[2]
2
>> factorial
{
1 => 1,
2 => 2
}
>> factorial[100]
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
>> factorial
{
1 => 1,
2 => 2,
3 => 6,
4 => 24,
5 => 120,
6 => 720,
7 => 5040,
8 => 40320,
9 => 362880,
10 => 3628800,
...
100 => 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
}
YOW! You're going to compute every intermediate value!? It's going to rapidly consume memory, with very little advantage.