3
\$\begingroup\$

I am building an array of strings to form the "empty" representation of a puzzle onto which I will overwrite single characters as necessary for debugging purposes. However, building the array using scalar multiplication results in shared string instances among the rows which breaks when I modify them.

> grid = [["... " * 3] * 3, ""].flatten * 3

This produces the desired output

> puts grid * "\n"

... ... ...
... ... ...
... ... ...

... ... ...
... ... ...
... ... ...

... ... ...
... ... ...
... ... ...

But the array contains only two string instances: nine of "... ... ..." and two of "". To solve this I use map to clone each string:

grid = ([["... " * 3] * 3, ""].flatten * 3).map(&:clone)

Is there a better way?

The main question here is how best to make sure each array element is a separate string instance.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Do I smell the beginning of a weekend-challenge submission? \$\endgroup\$ Dec 16, 2013 at 1:44
  • 1
    \$\begingroup\$ I generally use "ruby-like" since it's very easy to write perl, C, or even python in ruby. "The Ruby Way" is a great book and also used in this context. \$\endgroup\$ Dec 18, 2013 at 16:33

1 Answer 1

3
\$\begingroup\$

I might do this:

grid = 9.times.map { "... " * 3 }

Or, better yet, as Naklion proposes in the comments:

grid = Array.new(9) { "... " * 3 }

to get the rows (as separate string instances), and this

grid.each_slice(3) { |rows| puts rows, "\n"  }

to print it similar to yours. But I wouldn't call either approach "idiomatic", just variations on a theme. I don't know if anything really idiomatic can be said to exist for this

However, it might be easier to approach this from a higher level, rather than rely on a string representation. I.e. parse the input grid into Cell, Row etc. objects (I'm obviously assuming this is sudoku we're talking about).
Of course, if you have a clever idea that relies on string manipulation, then go for it!

My point is more that I know you can get far with, say, bitwise representations of sudoku, but implementing that in Ruby (while totally possible) seems "crude". Ruby's not geared toward twiddling bits, but toward more high-level OOP abstractions. It'd be right at home in C/C++, though.

*) I'd go with "rubyesque" or just "ruby" as in "the ruby way of doing things" :)

\$\endgroup\$
4
  • 2
    \$\begingroup\$ grid = Array.new(9){ "... " * 3 } \$\endgroup\$
    – Nakilon
    Dec 16, 2013 at 15:46
  • \$\begingroup\$ @Naklion Better! I'll update the answer. I always forget about the block initializers on Array and Hash. Thanks! \$\endgroup\$
    – Flambino
    Dec 16, 2013 at 17:14
  • \$\begingroup\$ I like the 9.times.map bit because it seems more explicit, but I'm returning the built string from this method rather than displaying it immediately, so I can't do the each_slice trick. This is just for debugging, but it should still probably be moved into a model class. Each 3x3 block is a representation of the possible numbers a Cell may still take; this isn't the actual storage mechanism. \$\endgroup\$ Dec 16, 2013 at 17:16
  • \$\begingroup\$ @Nakilon Hah! I'm using that all over the place for building the internal data structures, yet I didn't think of it here. It is indeed a nifty trick. \$\endgroup\$ Dec 16, 2013 at 17:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.