[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Data Structure for n-dimension values with defaults

Gavin Kistner

3/26/2006 11:24:00 PM

Help! I can't figure out how to store a rather particular set of data.

An object in my system has properties. Each property has a value.
However, the value of each property can change based on a number of
"build axes". There are an arbitrary number of orthogonal build axes,
none of which is more important than another. (However, if it's needed,
I am happy to impose a particular ordering on them.)

Each build axis has a number of 'notches', or discrete values along the
axis. In addition to all the notches, there is one special notch named
"Master". A value set in this notch is a fallback, default value if
other notches in the axis have no values.

So, for example, assume I'm talking about a Text object. One of it's
properties is "textString".
The system has two build axes: "Language" and "Rating".

The "Language" axis has "French", "English", "German", and "Jibbrish"
notches in addition to the Master notch. The "Rating" axis has "G",
"PG", "R", and "X" values.

Here's a monospace-font diagram of the values I want to store:

-------------------Language-------------------------

Master English French German Jibbrish
R Master (yell) - - Ach! -
A G - Wow! Oh! - -
T PG - Holy Crap! Merde! - -
I R - Holy Shit! Mon Dieu! - -
N X $!@* - - XXX -
G

With the above, the textString property should have a value of "Ach!"
if the Language axis is set to German and the Rating axis is set to G,
PG, or R.

If the Rating is set to "X", then the textString should be set to
"$!@*" regardless of the Language axis setting...except for if the
Language is set to German, in which case it should be "XXX"

If the Language is set to "Jibbrish", then the value is "(yell)",
except when the Rating is "X".

If the Rating is set to "PG" and the Language is set to "English", then
the textString value should be set to "Holy Crap!". And so on for other
values that are explicitly set for all axis combinations.


Hopefully that example is clear enough to show that explicit values win
over master values.

So, how the heck would you store this sort of information? I mostly
don't even care about speed.

11 Answers

Logan Capaldo

3/26/2006 11:45:00 PM

0


On Mar 26, 2006, at 6:28 PM, Phrogz wrote:

> Help! I can't figure out how to store a rather particular set of data.
>
> An object in my system has properties. Each property has a value.
> However, the value of each property can change based on a number of
> "build axes". There are an arbitrary number of orthogonal build axes,
> none of which is more important than another. (However, if it's
> needed,
> I am happy to impose a particular ordering on them.)
>
> Each build axis has a number of 'notches', or discrete values along
> the
> axis. In addition to all the notches, there is one special notch named
> "Master". A value set in this notch is a fallback, default value if
> other notches in the axis have no values.
>
> So, for example, assume I'm talking about a Text object. One of it's
> properties is "textString".
> The system has two build axes: "Language" and "Rating".
>
> The "Language" axis has "French", "English", "German", and "Jibbrish"
> notches in addition to the Master notch. The "Rating" axis has "G",
> "PG", "R", and "X" values.
>
> Here's a monospace-font diagram of the values I want to store:
>
> -------------------Language-------------------------
>
> Master English French German Jibbrish
> R Master (yell) - - Ach! -
> A G - Wow! Oh! - -
> T PG - Holy Crap! Merde! - -
> I R - Holy Shit! Mon Dieu! - -
> N X $!@* - - XXX -
> G
>
> With the above, the textString property should have a value of "Ach!"
> if the Language axis is set to German and the Rating axis is set to G,
> PG, or R.
>
> If the Rating is set to "X", then the textString should be set to
> "$!@*" regardless of the Language axis setting...except for if the
> Language is set to German, in which case it should be "XXX"
>
> If the Language is set to "Jibbrish", then the value is "(yell)",
> except when the Rating is "X".
>
> If the Rating is set to "PG" and the Language is set to "English",
> then
> the textString value should be set to "Holy Crap!". And so on for
> other
> values that are explicitly set for all axis combinations.
>
>
> Hopefully that example is clear enough to show that explicit values
> win
> over master values.
>
> So, how the heck would you store this sort of information? I mostly
> don't even care about speed.
>
>

An array of hashes? Actually a hash of structs would probably be better

Row = Struct.new(:master, :english, :french, :german, :gibberish)

table = {
:G => Row.new('(yell)', nil, nil, 'Ach!', nil),
:PG => Row.new(nil, 'Wow!', 'Oh!', nil, nil),
:R => Row.new(nil, 'Holy Shit!', 'Mon Dieu!',
nil, nil),
:X => Row.new('$!@*', nil, nil, 'XXX', nil)
}

def table.get(rating, language)
res = self[rating].send(language)
if res.nil?
self[rating].master
else
res
end
end



irb(main):040:0> table.get(:X, :german)
=> "XXX"
irb(main):041:0> table.get(:X, :english)
=> "$!@*"






Gavin Kistner

3/26/2006 11:53:00 PM

0

Close, but it fails from the ordered-axis problem I've been seeing.

puts table.get( :R, :german )
#=> nil

that should be "Ach!"

Logan Capaldo

3/27/2006 12:14:00 AM

0


On Mar 26, 2006, at 6:53 PM, Phrogz wrote:

> Close, but it fails from the ordered-axis problem I've been seeing.
>
> puts table.get( :R, :german )
> #=> nil
>
> that should be "Ach!"
>
>

Improved version:
% cat table_structure.rb
Row = Struct.new(:master, :english, :french, :german, :gibberish)

table = {
:master => Row.new('(yell)', nil, nil, 'Ach!', nil),
:G => Row.new(nil, 'Wow!', 'Oh!', nil, nil),
:PG => Row.new(nil, 'Holy Crap!', 'Merde!', nil, nil),
:R => Row.new(nil, 'Holy Shit!', 'Mon Dieu!', nil, nil),
:X => Row.new('$!@*', nil, nil, 'XXX', nil)
}

def table.get(rating, language)
res = self[rating].send(language)
if res.nil?
res = self[rating].master
end
if res.nil?
res = self[:master].send(language)
end
if res.nil?
res = self[:master].master
end
res
end

puts table.get(:R, :german)
puts table.get(:X, :german)
puts table.get(:X, :english)


% ruby table_structure.rb
Ach!
XXX
$!@*




Gavin Kistner

3/27/2006 12:19:00 AM

0

Cool, that seems to do it. So now, I just need to figure out how that
resolution algorithm scales in the n-dimensional case when I'm trying
to optimize for the fewest number of master values involved. And, as
Ryan Davis pointed out on IRC, what my logic is when conflicting values
have the same weight (and if I should even be able to get into such a
situation).

This is helpful, though. I was previously trying to approach the
problem from some sort of default-hash value solution. This has made
apparent that I need to be storing n-dimensional data, and only if I
find a nil value at the intersection of all axes do I go into a
separate resolution mode for searching for the best value.

Ernest Obusek

3/27/2006 5:18:00 PM

0

I'm new to Ruby so perhaps this is obvious to you but not to me. Can
anyone tell me what is wrong with my simple script below:

$ cat t.rb

#!/usr/bin/ruby

puts "Timer set to #{ARGV[0]} seconds. Press <ENTER> to start the
countdown."
gets


$ ./t.rb 60
Timer set to 60 seconds. Press <ENTER> to start the countdown.
/t.rb:4:in `gets': No such file or directory - 60 (Errno::ENOENT)
from ./t.rb:4

It seems to think the argument of 60 should be a file or
directory... ????

Thanks,

Ernest



Ara.T.Howard

3/27/2006 5:30:00 PM

0

Eric Armstrong

3/27/2006 11:16:00 PM

0

ara.t.howard@noaa.gov wrote:
> On Tue, 28 Mar 2006, Ernest Obusek wrote:
>
>> #!/usr/bin/ruby
>>
>> puts "Timer set to #{ARGV[0]} seconds. Press <ENTER> to start the
>> countdown."
>> gets
>>
>> It seems to think the argument of 60 should be a file or directory...
>> ????
>
> you have not given a receiver to gets and the default one is ARGF (see
> pickaxe for desc). try
>
> STDIN.gets
>
That almost makes sense, except for the name of the receiver.
gets is supposed to read from a file, if specified. Otherwise
it reads from piped input (according to the ancient books I've
consulted).

I can understand that you would need to specify a different
receiver to specify "current console device". But surely
the input pipe is standard input, yes? So STDIN is the current
console device, and that's not the same as standard in???

Signed, Confused in Peoria.
:_)


Ara.T.Howard

3/27/2006 11:24:00 PM

0

Eric Armstrong

3/27/2006 11:44:00 PM

0

ara.t.howard@noaa.gov wrote:
> gets is a method of IO and it does read from piped input.
> however, there is a magic variable called ARGF which is the list of
> all files on the command line, or stdin if none are given. so 'cat',
> in ruby could be written as
>
> ARGF.each{|line| print line}
>
So far, so good. Makes perfect sense.
What is more perplexing is that the formula for console I/O
would look like this:

puts prompt_string
STDIN.gets --succeeds?

Why would standard input work there, but fail in this case:

puts prompt_string
gets --fails?

If no file is specified on the command line, why doesn't that
invocation gets do the same thing as STDIN.gets?


ara.t.howard@noaa.gov wrote:
> On Tue, 28 Mar 2006, Eric Armstrong wrote:
>
>> ara.t.howard@noaa.gov wrote:
>>> On Tue, 28 Mar 2006, Ernest Obusek wrote:
>>>
>>>> #!/usr/bin/ruby
>>>>
>>>> puts "Timer set to #{ARGV[0]} seconds. Press <ENTER> to start the
>>>> countdown."
>>>> gets
>>>>
>>>> It seems to think the argument of 60 should be a file or
>>>> directory... ????
>>>
>>> you have not given a receiver to gets and the default one is ARGF
>>> (see pickaxe for desc). try
>>>
>>> STDIN.gets
>>>
>> That almost makes sense, except for the name of the receiver.
>> gets is supposed to read from a file, if specified. Otherwise
>> it reads from piped input (according to the ancient books I've
>> consulted).
>>
>> I can understand that you would need to specify a different
>> receiver to specify "current console device". But surely
>> the input pipe is standard input, yes? So STDIN is the current
>> console device, and that's not the same as standard in???
>>
>> Signed, Confused in Peoria.
>> :_)
>>
>
> yes and no. first off gets is a method of IO and it does read from piped
> input. however, there is a magic variable called ARGF which is the list of
> all files on the command line, or stdin if none are given. so 'cat', in
> ruby
> could be written as
>
> ARGF.each{|line| print line}
>
> and this would work with
>
> cat one | ruby a.rb
> ruby a.rb < two
> ruby a.rb one two three
>
> make sense? see ARGF in pickaxe for more.
>
> regards.
>
> -a


Ara.T.Howard

3/27/2006 11:51:00 PM

0