Skip to content

Instantly share code, notes, and snippets.

@dannysperry
Created January 20, 2015 03:47
Show Gist options
  • Save dannysperry/3c6230e53ffc0a2a8a52 to your computer and use it in GitHub Desktop.
Save dannysperry/3c6230e53ffc0a2a8a52 to your computer and use it in GitHub Desktop.
Encoder
# Helper Class that takes binary numbers as a string literal
class BinaryString
HEX_HASH = { 10 => 'a', 11 => 'b', 12 => 'c', 13 => 'd', 14 => 'e', 15 => 'f' }
attr_accessor :val
def initialize(val)
@val = val.to_s(2)
end
# nybble = 4 bits
# byte = 8 bits
def to_hex
bytes = halfize(@val).map do |num|
to_bytes num
end
nybbles = bytes.map { |x| halfize x }.flatten!
nybbles.map! { |nybble| nybble_to_hex nybble }
nybbles.join
end
def to_bytes(binary_str)
raise ArgumentError, 'must contain 8 or less characters' if binary_str.length > 8
remaining_length = 8 - binary_str.length
"#{'0' * remaining_length}".insert(-1, binary_str)
end
private
def halfize(binary)
index = (binary.length / 2)
head = binary.slice(0, index)
tail = binary.slice(index, binary.length)
[head, tail]
end
def nybble_to_hex(binary_str)
raise ArgumentError, 'must contain 4 characters' if binary_str.length != 4
raise ArgumentError, "must contains 0's and 1's" unless binary_str.chars.all? {|x| x == '0' || x == '1'}
chars = binary_str.chars
(1..4).each do |i|
chars[-i] = "#{chars[-i].to_i * 2**(i-1)}"
end
char = chars.map(&:to_i).inject(:+)
char = int_to_alphanumeric_hex(char)
end
def int_to_alphanumeric_hex(int)
return int.to_s if int < 10
HEX_HASH[int]
end
end
# Encoder class for 14-bit integers
class Encoder
MIN_NUM = -8192
MAX_NUM = 8191
attr_reader :int
def initialize(int)
fail RuntimeError unless int.between?(MIN_NUM, MAX_NUM)
@int = int + MAX_NUM + 1
end
def encode
binary = BinaryString.new @int
binary.to_hex
end
end
require 'minitest/autorun'
# Encoder class tests
class TestEncoder < Minitest::Test
def test_constants_are_set_to_14_bit_range
assert_equal Encoder::MIN_NUM, -8192
assert_equal Encoder::MAX_NUM, 8191
end
def test_accepts_14_bit_range
assert_raises RuntimeError do
Encoder.new(9000)
end
end
def test_int_is_a_readable_attribute
encoder = Encoder.new(5000)
assert_respond_to encoder, :int
end
def test_int_is_a_valid_positive_integer
assert_equal 8192, Encoder.new(0).int
assert_equal 0, Encoder.new(-8192).int
assert_equal 16_383, Encoder.new(8191).int
assert_equal 10_240, Encoder.new(2048).int
assert_equal 4_096, Encoder.new(-4096).int
end
def test_encode_splits_in_half
assert_equal '4000', Encoder.new(0).encode
assert_equal '0000', Encoder.new(-8192).encode
assert_equal '7f7f', Encoder.new(8191).encode
assert_equal '5000', Encoder.new(2048).encode
assert_equal '2000', Encoder.new(-4096).encode
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment