I needed to test a class which had a certain number of ‘binary’ inputs (ie. each input
takes either 0 or 1 (or false or true) ). In order to do this I needed to try out every
possible combination of inputs - essentially a binary count, like:
0,0,0,0
0,0,0,1
…
1,1,1,0
1,1,1,1
I figured I could just increment an integer and, then convert it to binary, but:
- there doesn’t seem to be a builtin to_bin method on FixNum.
- I’d still have to deal with indexing, etc.
(OK, it wouldn’t be that hard to implement #1 and #2 is not that hard either, but I
decided to go a different route for fun
So I made a BinCounter class and I present it here in case anyone else has need for it:
class BinaryCounter
attr_reader :bin
def initialize(num_bits, tv=1,fv=0)
@trueval = tv
@falseval = fv
@bin = Array.new(num_bits,@falseval)
end
def bincount(array=@bin,&block)
recurse(array,0,@falseval,&block)
recurse(array,0,@trueval,&block)
end
private
def recurse(array,idx,val,&block)
if idx == array.length
yield array if val == @falseval && block_given?
return
end
array[idx] = val
recurse(array,idx+1,@falseval,&block)
recurse(array,idx+1,@trueval,&block)
end
end
bc = BinaryCounter.new(4)
bc.bincount { |array| p array }
#end
Which produces:
[0, 0, 0, 0]
[0, 0, 0, 1]
…
[1, 1, 1, 0]
[1, 1, 1, 1]
…it’s also possible to change the values, like:
bc = BinaryCounter.new(2,‘cat’,‘dog’)
bc.bincount { |array| p array }
which produces:
[“dog”, “dog”]
[“dog”, “cat”]
[“cat”, “dog”]
[“cat”, “cat”]
…well, I suppose if you’re a ‘dog person’ you’ll want to swap it:
[“cat”, “cat”]
[“cat”, “dog”]
[“dog”, “cat”]
[“dog”, “dog”]
Hmmm… Crazy idea: One could use code generation to create N’ary counter
classes where N is the number of values that each slot could take.
Phil