Question about multi-demension hash initialization

R

Ruby Student

[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
 
R

Robert Klemme

[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
 
R

Ruby Student

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

[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/techniques-8.php

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
 
R

Robert Klemme

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/techniques-8.php

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
 
R

Ruby Student

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

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/techniques-8.php

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top