[SNIPPET] Binary counter

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:

  1. there doesn’t seem to be a builtin to_bin method on FixNum.
  2. 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 :wink:

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

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:

  1. there doesn’t seem to be a builtin to_bin method on FixNum.
  2. 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 :wink:

8.times {|i| 4.times {|j| print i[3-j]}; puts }
0000
0001
0010
0011
0100
0101
0110
0111
=> 8
class Fixnum; def to_bin(bits=31); a = ; bits.times{|i| a.unshift self[i]}; a end end
=> nil
10.times {|i| p i.to_bin(4)}
[0, 0, 0, 0]
[0, 0, 0, 1]
[0, 0, 1, 0]
[0, 0, 1, 1]
[0, 1, 0, 0]
[0, 1, 0, 1]
[0, 1, 1, 0]
[0, 1, 1, 1]
[1, 0, 0, 0]
[1, 0, 0, 1]

···

On Sat, Jul 19, 2003 at 04:05:39AM +0900, Phil Tomson wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Q: What’s the big deal about rm, I have been deleting stuff for years? And
never lost anything… oops!
A: …
– From the Frequently Unasked Questions

I wrote one recently (though using a considerably more mundane approach
) - it’s up at http://www.rubygarden.org/ruby?MultiCounter

martin

···

Phil Tomson ptkwt@shell1.aracnet.com wrote:

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.

------------------------------------------------------------ Fixnum#to_s
fix.to_s( base=10 ) → aString

···

On 18 Jul 2003 18:49:16 GMT ptkwt@shell1.aracnet.com (Phil Tomson) wrote:

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:

  1. there doesn’t seem to be a builtin to_bin method on FixNum.

 Returns a string containing the representation of fix radix base (2
 to 36).
    12345.to_s       #=> "12345"
    12345.to_s(2)    #=> "11000000111001"
    12345.to_s(8)    #=> "30071"
    12345.to_s(10)   #=> "12345"
    12345.to_s(16)   #=> "3039"
    12345.to_s(36)   #=> "9ix"

As others mentioned, ‘“%b” % n’ works too.

(0…3).collect { |n| n.to_s(2).split(//).collect { |n| n.to_i } }
=> [[0], [1], [1, 0], [1, 1]]
(0…3).collect { |n| (“%02b” % n).split(//).collect { |n| n.to_i } }
=> [[0, 0], [0, 1], [1, 0], [1, 1]]
(0…3).collect { |n| (“%02b” % n).split(//).collect { |n| (n.to_i == 0) ? “cat” : “dog” } }
=> [[“cat”, “cat”], [“cat”, “dog”], [“dog”, “cat”], [“dog”, “dog”]]

Jason Creighton

And also:

irb(main):003:0> 8.times { |i| puts “%04b” % i }
0000
0001
0010
0011
0100
0101
0110
0111
=> 8

···

On Sat, Jul 19, 2003 at 04:36:23AM +0900, Mauricio Fern?ndez wrote:

8.times {|i| 4.times {|j| print i[3-j]}; puts }
0000
0001
0010
0011
0100
0101
0110
0111
=> 8

Maybe not, but “%b” % n works nicely.

-Mark

···

On Sat, Jul 19, 2003 at 04:36:23AM +0900, Mauricio Fernández wrote:

I figured I could just increment an integer and, then convert
it to binary, but:

  1. there doesn’t seem to be a builtin to_bin method on FixNum.

In article 20030718193620.GA23206@student.ei.uni-stuttgart.de,

···

Mauricio Fernández batsman.geo@yahoo.com wrote:

On Sat, Jul 19, 2003 at 04:05:39AM +0900, Phil Tomson wrote:

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:

  1. there doesn’t seem to be a builtin to_bin method on FixNum.
  2. 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 :wink:

8.times {|i| 4.times {|j| print i[3-j]}; puts }
0000
0001
0010
0011
0100
0101
0110
0111
=> 8
class Fixnum; def to_bin(bits=31); a = ; bits.times{|i| a.unshift
self[i]}; a end end
=> nil
10.times {|i| p i.to_bin(4)}
[0, 0, 0, 0]
[0, 0, 0, 1]
[0, 0, 1, 0]
[0, 0, 1, 1]
[0, 1, 0, 0]
[0, 1, 0, 1]
[0, 1, 1, 0]
[0, 1, 1, 1]
[1, 0, 0, 0]
[1, 0, 0, 1]

Hmmm… that was a lot easier I say sheepishly :slight_smile:

But it doesn’t do that ‘dog’ ‘cat’ thing :wink:

Phil

In article 20030718202509.GA3472@uk.tiscali.com,

···

Brian Candler B.Candler@pobox.com wrote:

On Sat, Jul 19, 2003 at 04:36:23AM +0900, Mauricio Fern?ndez wrote:

8.times {|i| 4.times {|j| print i[3-j]}; puts }
0000
0001
0010
0011
0100
0101
0110
0111
=> 8

And also:

irb(main):003:0> 8.times { |i| puts “%04b” % i }
0000
0001
0010
0011
0100
0101
0110
0111
=> 8

You guys are spoiling all my fun with recursive functions :wink:

Phil

Sorry. Well for a bit more fun, how about writing a Gray code counter? The
characteristic of this sequence is that each number differs from the
previous one by exactly one bit.

0000
0001
0011
0010
0110
0111
0101
0100
1100
… etc

It has important practical applications: e.g. devices which detect the
rotational position of a shaft. You don’t have to worry about false readings
during awkward transitions like 0111->1000

Regards,

Brian.

···

On Sat, Jul 19, 2003 at 07:26:32AM +0900, Phil Tomson wrote:

You guys are spoiling all my fun with recursive functions :wink:

I found a homepage: ruby + gray code

http://www.public.asu.edu/~ncban/graycode.html

···

On Sat, 19 Jul 2003 18:04:07 +0900, Brian Candler wrote:

On Sat, Jul 19, 2003 at 07:26:32AM +0900, Phil Tomson wrote:

You guys are spoiling all my fun with recursive functions :wink:

Sorry. Well for a bit more fun, how about writing a Gray code counter? The
characteristic of this sequence is that each number differs from the
previous one by exactly one bit.


Simon Strandgaard

Saluton!

  • Brian Candler; 2003-07-19, 11:38 UTC:

The characteristic of this sequence is that each number differs
from the previous one by exactly one bit.

0000
0001
0011
0010
0110
0111
0101
0100
1100

It has important practical applications: e.g. devices which detect
the rotational position of a shaft.

I think it is worth to complete the series:

1101
1111
1110
1010
1011
1001
1000

0000
0001

This shows that the representation of 15 and that of 0 only differ in
one digit as well - this explains why a Gray code is especially
useful for periodic movements like rotations.

Gis,

Josef ‘Jupp’ Schugt

···


N’attribuez jamais à la malice ce que l’incompétence explique !
– Napoléon

Now you’re spoiling his fun again :slight_smile:

···

On Sat, Jul 19, 2003 at 08:09:08PM +0900, Simon Strandgaard wrote:

On Sat, 19 Jul 2003 18:04:07 +0900, Brian Candler wrote:

On Sat, Jul 19, 2003 at 07:26:32AM +0900, Phil Tomson wrote:

You guys are spoiling all my fun with recursive functions :wink:

Sorry. Well for a bit more fun, how about writing a Gray code counter? The
characteristic of this sequence is that each number differs from the
previous one by exactly one bit.

I found a homepage: ruby + gray code

http://www.public.asu.edu/~ncban/graycode.html

In article pan.2003.07.19.10.53.34.563639@sneakemail.com,

You guys are spoiling all my fun with recursive functions :wink:

Sorry. Well for a bit more fun, how about writing a Gray code counter? The
characteristic of this sequence is that each number differs from the
previous one by exactly one bit.

I found a homepage: ruby + gray code

http://www.public.asu.edu/~ncban/graycode.html

Very nice, compact algorithm there.

"Here’s an algorithm for translating binary to Gray code. It’s in a loop here,
but unlike the other algorithms we’ve looked at, it doesn’t have to be. This
algorithm can convert an arbitrary binary number to Gray code in finite time.
Wonderful!

#!/usr/bin/env ruby

bits = 4
(1 << bits).times do |binary|
grayCode = binary ^ (binary >> 1)
printf “%0#{bits}b\n”, grayCode
end

How does it work? Beats me. It’s magic. "

Phil

···

Simon Strandgaard 0bz63fz3m1qt3001@sneakemail.com wrote:

On Sat, 19 Jul 2003 18:04:07 +0900, Brian Candler wrote:

On Sat, Jul 19, 2003 at 07:26:32AM +0900, Phil Tomson wrote:

Algorithms which work in a finite time are the best ones, I find.

Regards,

Brian.

···

On Sun, Jul 20, 2003 at 01:50:43AM +0900, Phil Tomson wrote:

"Here’s an algorithm for translating binary to Gray code. It’s in a loop here,
but unlike the other algorithms we’ve looked at, it doesn’t have to be. This
algorithm can convert an arbitrary binary number to Gray code in finite time.