A better way implement "it" the ruby way

Hi,

I come from the world of other programming languages and in the process
of learning Ruby I am trying to implement a few algorithms.

It would be great if you could assist me with proposal for implementing
it in a more “ruby” way tham directly following the pattern from “java”
for example.

I would like to convert integers to strings where the strings are of the
form XXX. X is a digit from 0 to 9 or a letter from A to Z. So 11 gets
converted to 00B. 37 is 010. And 46656 gets converted to ZZZ.

An example for the algorithm is:

public String generateKey(int number) {
StringBuilder builder = new StringBuilder();
int mod = number % 36;
int k = number;
do {
appendSymbol(mod, builder);
k = k / 36;
mod = k % 36;
} while (k != 0);
if (builder.length() < 3)
appendSymbol(mod, builder);
if (number < 36)
builder.append(“0”);
return builder.reverse().toString();
}
private char convertToLetter(int start) {
int number = start - 10 + ‘A’;
return (char) number;
}

private void appendSymbol(int i, StringBuilder builder) {
if (i < 10)
builder.append(Integer.toString(i));
else
builder.append(convertToLetter(i));
}

I am sure there are plenty of ways to implement this in Ruby more
clearly in a number of lines. It would be great if you could share your
ideas for the implementation.

This code is pretty easy to translate to straight Ruby, I spent about
15 minutes refactoring this, and there’s one non-obvious thing:

I tend to make code like this an object, via something like “Replace
Method with Method Object”[1]. It’s a refactoring that’s used
primarily for extracting long methods out of a parent class, but I’ve
found that every time I want to write some sort of function rather
than a method, I end up having to write two or three, then I wrap them
in a module, and it ends up basically becoming an object with a few
methods anyway. Don’t use ‘compute’ though, it’s a terrible name. I’d
end up using something like “Key.generate(number)” for a final
interface.

in the process of learning Ruby I am trying to implement a few algorithms.

You won’t find a whole lot different in straight up algorithmic code.
Ruby offers basically the same things other languages do, so it won’t
really be all that different. However, in more complicated situations,
where you have lots of moving parts interacting, Ruby really starts to
shine.

1: Replace Method with Method Object

On Feb 8, 2012, at 08:36 , Bravo M. wrote:

form XXX. X is a digit from 0 to 9 or a letter from A to Z. So 11 gets
converted to 00B. 37 is 010. And 46656 gets converted to ZZZ.

I know you’re trying to do some exercises to learn ruby so this
suggestion is probably not entirely apropros, but I think your math
might be bad (OR: I’m uncaffienated, OR: I missed something obvious).

11.to_s 36
=> “b”

37.to_s 36
=> “11”

46656.to_s 36
=> “1000”

46655.to_s 36
=> “zzz”

the rest of the formatting can easily be done using String methods:

37.to_s(36).rjust(3,‘0’)
=> “011”

And I agree with Steve… the name is terrible. In this case I’d
probably put a method on Fixnum and name it to_key or somesuch.

37.to_key # => “011”

On Wed, Feb 8, 2012 at 10:36 AM, Bravo M. [email protected]
wrote:

I am sure there are plenty of ways to implement this in Ruby more
clearly in a number of lines. It would be great if you could share your
ideas for the implementation.

As others suggested, rand(…).to_s(…).rjust(…) is obviously the
best
way, but here is another option:

3.times.map { [0…9,‘A’…‘Z’].sample }.join

3.times will create an enumerator – an object waiting to be invoked
with a
block that it will then call 3 times.

Then we convert it to another enumerator with map, which, for each of
the
times, will invoke the block we give it and populate the result into an
array.

In the block, the 0…9 and ‘A’…‘Z’ are ranges of digits and characters.
Placing the splat in front of them turns them into arrays (note that in
many places you have to surround this with parens, we don’t here because
we’re in an array literal). Calling sample on this will choose one of
its
elements at random, and since this is the last expression in the block,
it
will be returned.

All this so far gives us an array of size 3 with the digits and
characters
we want, we call join to turn them into a string.

Hate to be a party pooper, but… there’s a method in core for it.
Fixnum#to_s can accept an optional argument, which is the base of
result, between 2 and 36 inclusive. Bases between 11 and 36 use
letters when there are not enough numbers.

11.to_s 36 #=> “b”
46655.to_s 36 #=> “zzz”

:slight_smile:

– Matma R.