[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Question about multi-demension hash initialization

Ruby Student

9/19/2008 6:22:00 PM

[Note: parts of this message were removed to make it a legal post.]

Team,
Is there a quick (perhaps one liner) way to initialize the following hashes
into just one hash?

def xwing(ia)

p ia

puts " "
p @xwing

r1 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
0, "8" => 0, "9" => 0}
r2 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
0, "8" => 0, "9" => 0}
r3 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
0, "8" => 0, "9" => 0}
r4 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
0, "8" => 0, "9" => 0}
r5 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
0, "8" => 0, "9" => 0}
r6 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
0, "8" => 0, "9" => 0}
r7 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
0, "8" => 0, "9" => 0}
r8 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
0, "8" => 0, "9" => 0}
r9 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
0, "8" => 0, "9" => 0}

end


(0..8).each do |r|
xwing(@xwing[[r][0]]) # @xwing is defined previously
end


Actually, I wanted just one hash, @frequency, but I did not know how to do
it.

Thank you

Ruby student

4 Answers

Robert Klemme

9/20/2008 2:53:00 PM

0

On 19.09.2008 20:21, Ruby Student wrote:
> [Note: parts of this message were removed to make it a legal post.]
>
> Team,
> Is there a quick (perhaps one liner) way to initialize the following hashes
> into just one hash?
>
> def xwing(ia)
>
> p ia
>
> puts " "
> p @xwing
>
> r1 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
> 0, "8" => 0, "9" => 0}
> r2 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
> 0, "8" => 0, "9" => 0}
> r3 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
> 0, "8" => 0, "9" => 0}
> r4 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
> 0, "8" => 0, "9" => 0}
> r5 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
> 0, "8" => 0, "9" => 0}
> r6 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
> 0, "8" => 0, "9" => 0}
> r7 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
> 0, "8" => 0, "9" => 0}
> r8 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
> 0, "8" => 0, "9" => 0}
> r9 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
> 0, "8" => 0, "9" => 0}
>
> end
>
>
> (0..8).each do |r|
> xwing(@xwing[[r][0]]) # @xwing is defined previously
> end
>
>
> Actually, I wanted just one hash, @frequency, but I did not know how to do
> it.

Err, what? You know how to create nine hashes but you do not know how
to create one? I'm suspecting that there is something missing from your
posting.

Maybe you wanted something like this:

irb(main):004:0> require 'pp'
=> true
irb(main):005:0> pp Array.new(9) { Hash[*(1..9).map
{|i|[i.to_s,0]}.flatten] }
[{"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
{"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
{"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
{"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
{"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
{"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
{"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
{"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
{"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0}]
=> nil
irb(main):006:0>

However, given the structure of your Hashes I wonder why you do not want
to use Arrays instead. E.g.

irb(main):001:0> pp Array.new(9) { Array.new(9, 0) }
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]]
=> nil

Or even use a Matrix.

irb(main):006:0> require 'matrix'
=> true
irb(main):007:0> pp Matrix.zero 9
Matrix[[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0,
0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0
], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0,
0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [
0, 0, 0, 0, 0, 0, 0, 0, 0]]
=> nil
irb(main):008:0> pp Matrix.zero(9).to_a
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]]
=> nil
irb(main):009:0>

Kind regards

robert

Ruby Student

9/20/2008 7:31:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

On Sat, Sep 20, 2008 at 10:47 AM, Robert Klemme
<shortcutter@googlemail.com>wrote:

> On 19.09.2008 20:21, Ruby Student wrote:
>
>> [Note: parts of this message were removed to make it a legal post.]
>>
>>
>> Team,
>> Is there a quick (perhaps one liner) way to initialize the following
>> hashes
>> into just one hash?
>>
>> def xwing(ia)
>>
>> p ia
>>
>> puts " "
>> p @xwing
>>
>> r1 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
>> 0, "8" => 0, "9" => 0}
>> r2 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
>> 0, "8" => 0, "9" => 0}
>> r3 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
>> 0, "8" => 0, "9" => 0}
>> r4 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
>> 0, "8" => 0, "9" => 0}
>> r5 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
>> 0, "8" => 0, "9" => 0}
>> r6 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
>> 0, "8" => 0, "9" => 0}
>> r7 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
>> 0, "8" => 0, "9" => 0}
>> r8 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
>> 0, "8" => 0, "9" => 0}
>> r9 = {"1" => 0, "2" => 0, "3" => 0, "4" => 0, "5" => 0, "6" => 0, "7" =>
>> 0, "8" => 0, "9" => 0}
>>
>> end
>>
>>
>> (0..8).each do |r|
>> xwing(@xwing[[r][0]]) # @xwing is defined previously
>> end
>>
>>
>> Actually, I wanted just one hash, @frequency, but I did not know how to do
>> it.
>>
>
> Err, what? You know how to create nine hashes but you do not know how to
> create one? I'm suspecting that there is something missing from your
> posting.
>
> Maybe you wanted something like this:
>
> irb(main):004:0> require 'pp'
> => true
> irb(main):005:0> pp Array.new(9) { Hash[*(1..9).map
> {|i|[i.to_s,0]}.flatten] }
> [{"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
> {"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
> {"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
> {"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
> {"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
> {"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
> {"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
> {"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0},
> {"6"=>0, "7"=>0, "8"=>0, "9"=>0, "1"=>0, "2"=>0, "3"=>0, "4"=>0, "5"=>0}]
> => nil
> irb(main):006:0>
>
> However, given the structure of your Hashes I wonder why you do not want to
> use Arrays instead. E.g.
>
> irb(main):001:0> pp Array.new(9) { Array.new(9, 0) }
> [[0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0]]
> => nil
>
> Or even use a Matrix.
>
> irb(main):006:0> require 'matrix'
> => true
> irb(main):007:0> pp Matrix.zero 9
> Matrix[[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0,
> 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0
> ], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0,
> 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [
> 0, 0, 0, 0, 0, 0, 0, 0, 0]]
> => nil
> irb(main):008:0> pp Matrix.zero(9).to_a
> [[0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0],
> [0, 0, 0, 0, 0, 0, 0, 0, 0]]
> => nil
> irb(main):009:0>
>
> Kind regards
>
> robert
>
>
> Robert,
First, thank you for your help and sample code.

What I need to do is to pass an integer compose of minimum 2 digits and
maximum of 8 and count the how many time a digit appears.
For example, I have a multidimensional array (9x9), which I then take each
row and each column at a time.

For instance, the following are two rows extracted from the 9x9 array:

r1 = [345, 8, 459, 125679, 123, 45679, 379, 679, 79]
r8 = [9, 4, 6789, 356, 1, 357, 2356, 257, 67]

So, for row r1:
1s = 2, 2s = 2, 3s = 3, 4s = 3, 5s = 4, 6s = 3, 7s = 5, 8s = 1, 9s = 6

The same reasoning follows for r8.
So the 9x9 hash represents the 9x9 array for Sudoku, but instead of
representing a Sudoku element, the key = the number while the value is the
count (frequency) of that key.
I am not sure if I am explaining myself clearly.

I need this information in order to successfully implement one of the Sudoku
rules, the so called x-wing rule, which explanation can be found at:
http://www.sudokuoftheday.com/pages/techni...

I can find my way around with arrays, but with hashes I am not familiar at
all.

Again, thank you for your help.

Ruby Student

Robert Klemme

9/21/2008 8:51:00 AM

0

On 20.09.2008 21:30, Ruby Student wrote:
> On Sat, Sep 20, 2008 at 10:47 AM, Robert Klemme
> <shortcutter@googlemail.com>wrote:
>> On 19.09.2008 20:21, Ruby Student wrote:
> First, thank you for your help and sample code.

You're welcome.

> What I need to do is to pass an integer compose of minimum 2 digits and
> maximum of 8 and count the how many time a digit appears.

That's easy.

irb(main):006:0> i = rand 100000000
=> 3976173
irb(main):007:0> h = Hash.new 0
=> {}
irb(main):008:0> i.to_s(10).scan(/\d/) {|dg| h[dg] += 1}
=> "3976173"
irb(main):009:0> h
=> {"6"=>1, "7"=>2, "9"=>1, "1"=>1, "3"=>2}
irb(main):010:0>

> For example, I have a multidimensional array (9x9), which I then take each
> row and each column at a time.

This is a _two_ dimensional Array.

> For instance, the following are two rows extracted from the 9x9 array:
>
> r1 = [345, 8, 459, 125679, 123, 45679, 379, 679, 79]
> r8 = [9, 4, 6789, 356, 1, 357, 2356, 257, 67]
>
> So, for row r1:
> 1s = 2, 2s = 2, 3s = 3, 4s = 3, 5s = 4, 6s = 3, 7s = 5, 8s = 1, 9s = 6
>
> The same reasoning follows for r8.
> So the 9x9 hash represents the 9x9 array for Sudoku, but instead of
> representing a Sudoku element, the key = the number while the value is the
> count (frequency) of that key.
> I am not sure if I am explaining myself clearly.

Me, too. ;-) Given the fact that you are dealing with Sudoku it is a
complete mystery to me why you want to count "digits". It seems, a
Sudoku can have _numbers_ in all locations and you want to make sure
that no number appears twice in a row and in a column. Basically there
are many ways to do this, one would be a bit set (you can use an integer
for that, see at end).

> I need this information in order to successfully implement one of the Sudoku
> rules, the so called x-wing rule, which explanation can be found at:
> http://www.sudokuoftheday.com/pages/techni...
>
> I can find my way around with arrays, but with hashes I am not familiar at
> all.

Since you are indexing by number (or more precisely: digit) anyway what
do you gain by using a Hash?

Cheers

robert


A half baked example to illustrate what I mean with the bit set check:

#!/bin/env ruby

require 'pp'

class Sudoku
def initialize(size)
raise ArgumentError unless 2 <= size
@size = size
@dat = Array.new(size * size)
@rows = Array.new(size, 0)
@cols = Array.new(size, 0)
end

def [](x,y)
@dat[pos(x,y)]
end

def []=(x,y,v)
raise "Not allowed" if @rows[x][v] == 1 || @cols[y][v] == 1
@dat[pos(x,y)] = v
@rows[x] |= 1 << v
@cols[y] |= 1 << v
end

def to_s
s = ""
@size.times do |i|
s << "[" << @dat[i * @size, @size].join(", ") << "]\n"
end
s
end

private
def pos(x,y)
raise ArgumentError unless [x,y].all? {|a| Integer === a}
x * @size + y
end
end

s = Sudoku.new 9

s[2,0] = 1
puts s

s[1,0] = 1

Ruby Student

9/21/2008 10:57:00 AM

0

[Note: parts of this message were removed to make it a legal post.]

On Sun, Sep 21, 2008 at 4:47 AM, Robert Klemme
<shortcutter@googlemail.com>wrote:

> On 20.09.2008 21:30, Ruby Student wrote:
>
>> On Sat, Sep 20, 2008 at 10:47 AM, Robert Klemme
>> <shortcutter@googlemail.com>wrote:
>>
>>> On 19.09.2008 20:21, Ruby Student wrote:
>>>
>> First, thank you for your help and sample code.
>>
>
> You're welcome.
>
> What I need to do is to pass an integer compose of minimum 2 digits and
>> maximum of 8 and count the how many time a digit appears.
>>
>
> That's easy.
>
> irb(main):006:0> i = rand 100000000
> => 3976173
> irb(main):007:0> h = Hash.new 0
> => {}
> irb(main):008:0> i.to_s(10).scan(/\d/) {|dg| h[dg] += 1}
> => "3976173"
> irb(main):009:0> h
> => {"6"=>1, "7"=>2, "9"=>1, "1"=>1, "3"=>2}
> irb(main):010:0>
>
> For example, I have a multidimensional array (9x9), which I then take each
>> row and each column at a time.
>>
>
> This is a _two_ dimensional Array.
>
> For instance, the following are two rows extracted from the 9x9 array:
>>
>> r1 = [345, 8, 459, 125679, 123, 45679, 379, 679, 79]
>> r8 = [9, 4, 6789, 356, 1, 357, 2356, 257, 67]
>>
>> So, for row r1:
>> 1s = 2, 2s = 2, 3s = 3, 4s = 3, 5s = 4, 6s = 3, 7s = 5, 8s = 1, 9s = 6
>>
>> The same reasoning follows for r8.
>> So the 9x9 hash represents the 9x9 array for Sudoku, but instead of
>> representing a Sudoku element, the key = the number while the value is the
>> count (frequency) of that key.
>> I am not sure if I am explaining myself clearly.
>>
>
> Me, too. ;-) Given the fact that you are dealing with Sudoku it is a
> complete mystery to me why you want to count "digits". It seems, a Sudoku
> can have _numbers_ in all locations and you want to make sure that no number
> appears twice in a row and in a column. Basically there are many ways to do
> this, one would be a bit set (you can use an integer for that, see at end).
>
> I need this information in order to successfully implement one of the
>> Sudoku
>> rules, the so called x-wing rule, which explanation can be found at:
>> http://www.sudokuoftheday.com/pages/techni...
>>
>> I can find my way around with arrays, but with hashes I am not familiar at
>> all.
>>
>
> Since you are indexing by number (or more precisely: digit) anyway what do
> you gain by using a Hash?
>
> Cheers
>
> robert
>
>
> A half baked example to illustrate what I mean with the bit set check:
>
> #!/bin/env ruby
>
> require 'pp'
>
> class Sudoku
> def initialize(size)
> raise ArgumentError unless 2 <= size
> @size = size
> @dat = Array.new(size * size)
> @rows = Array.new(size, 0)
> @cols = Array.new(size, 0)
> end
>
> def [](x,y)
> @dat[pos(x,y)]
> end
>
> def []=(x,y,v)
> raise "Not allowed" if @rows[x][v] == 1 || @cols[y][v] == 1
> @dat[pos(x,y)] = v
> @rows[x] |= 1 << v
> @cols[y] |= 1 << v
> end
>
> def to_s
> s = ""
> @size.times do |i|
> s << "[" << @dat[i * @size, @size].join(", ") << "]\n"
> end
> s
> end
>
> private
> def pos(x,y)
> raise ArgumentError unless [x,y].all? {|a| Integer === a}
> x * @size + y
> end
> end
>
> s = Sudoku.new 9
>
> s[2,0] = 1
> puts s
>
> s[1,0] = 1
>
> Robert,
Again, thanks a bunch.
You have given me enough material for a good few days to digest.
I'll play and learn from your sample code.

Thanks again,

Ruby Student