Base conversion: decode and encode base to integer












4














I encountered this question as I am preparing for my code interview. I was implementing a base function that can decode and encode any bases from base 2 to base 36. I think my decode and encode functions work fine. It can convert digits from binary (base 2 - 36).



My task:




Decode digits from hexadecimal (base 16). Decode given digits in given base to number in base 10.




Also:




Decode digits from any base (2 up to 36).




I created a helper function that handles hexadecimal digit_from_letter, as it checks if the digit is a digit else it's a letter.



import string

def letter_from_num(num):
""" Convert letter from number:
input: int -- integer representation of number (in base 10)
return: strings of letters """
letters ='abcdefghijklmnopqrstuvwxyz'
return letters[num - 10]

def digit_from_letter(letter):
"""
input: any letter
return: int -- number representation of number (in base 10)
handles digits from hexadecimal (base 16)
handles digits from any base (2 up to 36)
math function that calculate the number based on math conversion
this calculate from the 36 letters -97 + 1
"""
num = ord(letter) - 97 + 10
return num

def decode(digits, base):
"""Decode given digits in given base to number in base 10.
digits: str -- string representation of number (in given base)
base: int -- base of given number
return: result is int -- integer representation of number (in base 10)"""
# Handle up to base 36 [0-9a-z]
assert 2 <= base <= 36, 'base is out of range: {}'.format(base)
result = 0
# Loop through the enumeration
# index and digit
# create a helper function that handles hexadecimal digit_from_letter
for index, digit in enumerate(digits):
if digit.isdigit():
digit_to_add = int(digit)
else:
digit_to_add = digit_from_letter(digit)
# add them together on the result with the digital_to_add to the result
result += digit_to_add
if index is not len(digits) - 1:
result *= base
else:
1
# Return the result decimal digit
return result

def encode(number, base):
"""Encode given number in base 10 to digits in given base.
number: int -- integer representation of number (in base 10)
base: int -- base to convert to
return: str -- string representation of number (in given base)"""
# Handle up to base 36 [0-9a-z]
assert 2 <= base <= 36, 'base is out of range: {}'.format(base)
new_base_number = ''
# encode helps me to make sure that we will work
while number != 0:
remainder = number % base
number = number // base
if (remainder >= 10 and base > 10):
remainder = letter_from_num(remainder)
else:
remainder
new_base_number += str(remainder)
# Reverse
new_base_number = new_base_number[::-1]
return new_base_number


def convert(digits, base1, base2):
"""Convert given digits in base1 to digits in base2.
digits: str -- string representation of number (in base1)
base1: int -- base of given number
base2: int -- base to convert to
return: str -- string representation of number (in base2)"""
assert 2 <= base1 <= 36, 'base1 is out of range: {}'.format(base1)
assert 2 <= base2 <= 36, 'base2 is out of range: {}'.format(base2)
# result = convert(digits, base1, base2)
# if
if base1 == 10:
new_base_number = encode(int(decimal_digit), base2)
else:
decimal_digit = decode(digits, base1)
new_base_number = encode(decimal_digit, base2)
# Return
return new_base_number



def main():
"""Read command-line arguments and convert given digits between bases."""
import sys
args = sys.argv[1:] # Ignore script file name
if len(args) == 3:
digits = args[0]
base1 = int(args[1])
base2 = int(args[2])
# Convert given digits between bases
result = convert(digits, base1, base2)
print('{} in base {} is {} in base {}'.format(digits, base1, result, base2))
else:
print('Usage: {} digits base1 base2'.format(sys.argv[0]))
print('Converts digits from base1 to base2')



if __name__ == '__main__':
main()
print(decode('123456', 8))
print(decode('123456', 9))
print(decode('123456', 10))
print(decode('123456', 12))
print(decode('123456', 15))
print(decode('123456', 20))
print(decode('123456', 25))
print(decode('123456', 30))
print(decode('123456', 35))
print(decode('123456', 36))


I think my code is pretty robust because it passes all these unittest cases too.



#!python

from bases import decode, encode, convert
import unittest


class BasesDecodeTest(unittest.TestCase):

def test_decode_binary(self):
assert decode('0', 2) == 0
assert decode('1', 2) == 1
assert decode('10', 2) == 2
assert decode('11', 2) == 3
assert decode('100', 2) == 4
assert decode('101', 2) == 5
assert decode('110', 2) == 6
assert decode('111', 2) == 7
assert decode('1000', 2) == 8
assert decode('1001', 2) == 9
assert decode('1010', 2) == 10
assert decode('1011', 2) == 11
assert decode('1100', 2) == 12
assert decode('1101', 2) == 13
assert decode('1110', 2) == 14
assert decode('1111', 2) == 15

def test_decode_decimal(self):
assert decode('5', 10) == 5
assert decode('9', 10) == 9
assert decode('10', 10) == 10
assert decode('25', 10) == 25
assert decode('64', 10) == 64
assert decode('99', 10) == 99
assert decode('123', 10) == 123
assert decode('789', 10) == 789
assert decode('2345', 10) == 2345
assert decode('6789', 10) == 6789
assert decode('13579', 10) == 13579
assert decode('24680', 10) == 24680

def test_decode_123456(self):
assert decode('123456', 8) ==42798
assert decode('123456', 9) == 74733
assert decode('123456', 10) == 123456
assert decode('123456', 12) == 296130
assert decode('123456', 15) == 871731
assert decode('123456', 20) == 3545706
assert decode('123456', 25) == 10596381
assert decode('123456', 30) == 26004756
assert decode('123456', 35) == 55656831
assert decode('123456', 36) == 63970746

def test_decode_hexadecimal(self):
assert decode('a', 16) == 10
assert decode('f', 16) == 15
assert decode('99', 16) == 153
assert decode('ff', 16) == 255
assert decode('ace', 16) == 2766
assert decode('cab', 16) == 3243
assert decode('bead', 16) == 48813
assert decode('face', 16) == 64206
assert decode('c0ffee', 16) == 12648430
assert decode('facade', 16) == 16435934
assert decode('deadbeef', 16) == 3735928559
assert decode('f007ba11', 16) == 4027038225

def test_decode_10(self):
assert decode('10', 2) == 2
assert decode('10', 4) == 4
assert decode('10', 8) == 8
assert decode('10', 10) == 10
assert decode('10', 16) == 16
assert decode('10', 25) == 25
assert decode('10', 32) == 32
assert decode('10', 36) == 36

def test_decode_1010(self):
assert decode('1010', 2) == 10
assert decode('1010', 4) == 68
assert decode('1010', 8) == 520
assert decode('1010', 10) == 1010
assert decode('1010', 16) == 4112
assert decode('1010', 25) == 15650
assert decode('1010', 32) == 32800
assert decode('1010', 36) == 46692

def test_decode_101101(self):
assert decode('101101', 2) == 45
assert decode('101101', 4) == 1105
assert decode('101101', 8) == 33345
assert decode('101101', 10) == 101101
assert decode('101101', 16) == 1052929
assert decode('101101', 25) == 9781876
assert decode('101101', 32) == 33588225
assert decode('101101', 36) == 60514129


class BasesEncodeTest(unittest.TestCase):

def test_encode_binary(self):
# assert encode(0, 2) == '0' # Should '' be valid?
assert encode(1, 2) == '1'
assert encode(2, 2) == '10'
assert encode(3, 2) == '11'
assert encode(4, 2) == '100'
assert encode(5, 2) == '101'
assert encode(6, 2) == '110'
assert encode(7, 2) == '111'
assert encode(8, 2) == '1000'
assert encode(9, 2) == '1001'
assert encode(10, 2) == '1010'
assert encode(11, 2) == '1011'
assert encode(12, 2) == '1100'
assert encode(13, 2) == '1101'
assert encode(14, 2) == '1110'
assert encode(15, 2) == '1111'

def test_encode_decimal(self):
# assert encode(0, 10) == '0' # Should '' be valid?
assert encode(5, 10) == '5'
assert encode(10, 10) == '10'
assert encode(25, 10) == '25'
assert encode(64, 10) == '64'
assert encode(99, 10) == '99'
assert encode(123, 10) == '123'
assert encode(789, 10) == '789'
assert encode(2345, 10) == '2345'
assert encode(6789, 10) == '6789'
assert encode(13579, 10) == '13579'
assert encode(24680, 10) == '24680'

def test_encode_hexadecimal(self):
assert encode(10, 16) == 'a'
assert encode(15, 16) == 'f'
assert encode(153, 16) == '99'
assert encode(255, 16) == 'ff'
assert encode(2766, 16) == 'ace'
assert encode(3243, 16) == 'cab'
assert encode(48813, 16) == 'bead'
assert encode(64206, 16) == 'face'
assert encode(12648430, 16) == 'c0ffee'
assert encode(16435934, 16) == 'facade'
assert encode(3735928559, 16) == 'deadbeef'
assert encode(4027038225, 16) == 'f007ba11'

def test_encode_1234(self):
assert encode(1234, 2) == '10011010010'
assert encode(1234, 3) == '1200201'
assert encode(1234, 4) == '103102'
assert encode(1234, 5) == '14414'
assert encode(1234, 8) == '2322'
assert encode(1234, 10) == '1234'
assert encode(1234, 16) == '4d2'
assert encode(1234, 32) == '16i'

def test_encode_248975(self):
assert encode(248975, 2) == '111100110010001111'
assert encode(248975, 4) == '330302033'
assert encode(248975, 8) == '746217'
assert encode(248975, 10) == '248975'
assert encode(248975, 16) == '3cc8f'
assert encode(248975, 25) == 'fn90'
assert encode(248975, 32) == '7j4f'
assert encode(248975, 36) == '5c3z'

def test_encode_into_10(self):
assert encode(2, 2) == '10'
assert encode(4, 4) == '10'
assert encode(8, 8) == '10'
assert encode(10, 10) == '10'
assert encode(16, 16) == '10'
assert encode(25, 25) == '10'
assert encode(32, 32) == '10'
assert encode(36, 36) == '10'

def test_encode_into_1010(self):
assert encode(10, 2) == '1010'
assert encode(68, 4) == '1010'
assert encode(520, 8) == '1010'
assert encode(1010, 10) == '1010'
assert encode(4112, 16) == '1010'
assert encode(15650, 25) == '1010'
assert encode(32800, 32) == '1010'
assert encode(46692, 36) == '1010'

def test_encode_into_101101(self):
assert encode(45, 2) == '101101'
assert encode(1105, 4) == '101101'
assert encode(33345, 8) == '101101'
assert encode(101101, 10) == '101101'
assert encode(1052929, 16) == '101101'
assert encode(9781876, 25) == '101101'
assert encode(33588225, 32) == '101101'
assert encode(60514129, 36) == '101101'


class BasesConvertTest(unittest.TestCase):

def test_convert_from_binary(self):
assert convert('1101', 2, 3) == '111'
assert convert('1101', 2, 4) == '31'
assert convert('1101', 2, 8) == '15'
assert convert('1101', 2, 10) == '13'
assert convert('101010', 2, 3) == '1120'
assert convert('101010', 2, 4) == '222'
assert convert('101010', 2, 8) == '52'
assert convert('101010', 2, 10) == '42'
assert convert('101010', 2, 16) == '2a'
assert convert('101010', 2, 25) == '1h'
assert convert('101010', 2, 32) == '1a'
assert convert('101010', 2, 36) == '16'

def test_convert_to_binary(self):
assert convert('111', 3, 2) == '1101'
assert convert('31', 4, 2) == '1101'
assert convert('15', 8, 2) == '1101'
assert convert('13', 10, 2) == '1101'
assert convert('101', 3, 2) == '1010'
assert convert('101', 4, 2) == '10001'
assert convert('101', 8, 2) == '1000001'
assert convert('101', 10, 2) == '1100101'
assert convert('101', 16, 2) == '100000001'
assert convert('101', 25, 2) == '1001110010'
assert convert('101', 32, 2) == '10000000001'
assert convert('101', 36, 2) == '10100010001'

def test_convert_hexadecimal_to_decimal(self):
assert convert('a', 16, 10) == '10'
assert convert('f', 16, 10) == '15'
assert convert('99', 16, 10) == '153'
assert convert('ff', 16, 10) == '255'
assert convert('ace', 16, 10) == '2766'
assert convert('cab', 16, 10) == '3243'
assert convert('bead', 16, 10) == '48813'
assert convert('face', 16, 10) == '64206'
assert convert('c0ffee', 16, 10) == '12648430'
assert convert('facade', 16, 10) == '16435934'
assert convert('deadbeef', 16, 10) == '3735928559'
assert convert('f007ba11', 16, 10) == '4027038225'

def test_convert_decimal_to_hexadecimal(self):
assert convert('10', 10, 16) == 'a'
assert convert('15', 10, 16) == 'f'
assert convert('153', 10, 16) == '99'
assert convert('255', 10, 16) == 'ff'
assert convert('2766', 10, 16) == 'ace'
assert convert('3243', 10, 16) == 'cab'
assert convert('48813', 10, 16) == 'bead'
assert convert('64206', 10, 16) == 'face'
assert convert('12648430', 10, 16) == 'c0ffee'
assert convert('16435934', 10, 16) == 'facade'
assert convert('3735928559', 10, 16) == 'deadbeef'
assert convert('4027038225', 10, 16) == 'f007ba11'

def test_convert_hexadecimal_to_binary(self):
assert convert('a', 16, 2) == '1010'
assert convert('b', 16, 2) == '1011'
assert convert('c', 16, 2) == '1100'
assert convert('d', 16, 2) == '1101'
assert convert('e', 16, 2) == '1110'
assert convert('f', 16, 2) == '1111'
assert convert('c840', 16, 2) == '1100100001000000'
assert convert('d951', 16, 2) == '1101100101010001'
assert convert('ea62', 16, 2) == '1110101001100010'
assert convert('fb73', 16, 2) == '1111101101110011'

def test_convert_binary_to_hexadecimal(self):
assert convert('1010', 2, 16) == 'a'
assert convert('1011', 2, 16) == 'b'
assert convert('1100', 2, 16) == 'c'
assert convert('1101', 2, 16) == 'd'
assert convert('1110', 2, 16) == 'e'
assert convert('1111', 2, 16) == 'f'
assert convert('1100100001000000', 2, 16) == 'c840'
assert convert('1101100101010001', 2, 16) == 'd951'
assert convert('1110101001100010', 2, 16) == 'ea62'
assert convert('1111101101110011', 2, 16) == 'fb73'


if __name__ == '__main__':
unittest.main()









share|improve this question




















  • 5




    You do know that the built-in int can already do the job of your decode, right? Try int("abcdefghijklmnopqrstuvwxyz0123456789", 36). Re-inventing existing functionality is fine (especially for interviews or for learning purposes), but you should say that you are. We even have a tag for it (reinventing-the-wheel).
    – Graipher
    Nov 5 '17 at 9:28


















4














I encountered this question as I am preparing for my code interview. I was implementing a base function that can decode and encode any bases from base 2 to base 36. I think my decode and encode functions work fine. It can convert digits from binary (base 2 - 36).



My task:




Decode digits from hexadecimal (base 16). Decode given digits in given base to number in base 10.




Also:




Decode digits from any base (2 up to 36).




I created a helper function that handles hexadecimal digit_from_letter, as it checks if the digit is a digit else it's a letter.



import string

def letter_from_num(num):
""" Convert letter from number:
input: int -- integer representation of number (in base 10)
return: strings of letters """
letters ='abcdefghijklmnopqrstuvwxyz'
return letters[num - 10]

def digit_from_letter(letter):
"""
input: any letter
return: int -- number representation of number (in base 10)
handles digits from hexadecimal (base 16)
handles digits from any base (2 up to 36)
math function that calculate the number based on math conversion
this calculate from the 36 letters -97 + 1
"""
num = ord(letter) - 97 + 10
return num

def decode(digits, base):
"""Decode given digits in given base to number in base 10.
digits: str -- string representation of number (in given base)
base: int -- base of given number
return: result is int -- integer representation of number (in base 10)"""
# Handle up to base 36 [0-9a-z]
assert 2 <= base <= 36, 'base is out of range: {}'.format(base)
result = 0
# Loop through the enumeration
# index and digit
# create a helper function that handles hexadecimal digit_from_letter
for index, digit in enumerate(digits):
if digit.isdigit():
digit_to_add = int(digit)
else:
digit_to_add = digit_from_letter(digit)
# add them together on the result with the digital_to_add to the result
result += digit_to_add
if index is not len(digits) - 1:
result *= base
else:
1
# Return the result decimal digit
return result

def encode(number, base):
"""Encode given number in base 10 to digits in given base.
number: int -- integer representation of number (in base 10)
base: int -- base to convert to
return: str -- string representation of number (in given base)"""
# Handle up to base 36 [0-9a-z]
assert 2 <= base <= 36, 'base is out of range: {}'.format(base)
new_base_number = ''
# encode helps me to make sure that we will work
while number != 0:
remainder = number % base
number = number // base
if (remainder >= 10 and base > 10):
remainder = letter_from_num(remainder)
else:
remainder
new_base_number += str(remainder)
# Reverse
new_base_number = new_base_number[::-1]
return new_base_number


def convert(digits, base1, base2):
"""Convert given digits in base1 to digits in base2.
digits: str -- string representation of number (in base1)
base1: int -- base of given number
base2: int -- base to convert to
return: str -- string representation of number (in base2)"""
assert 2 <= base1 <= 36, 'base1 is out of range: {}'.format(base1)
assert 2 <= base2 <= 36, 'base2 is out of range: {}'.format(base2)
# result = convert(digits, base1, base2)
# if
if base1 == 10:
new_base_number = encode(int(decimal_digit), base2)
else:
decimal_digit = decode(digits, base1)
new_base_number = encode(decimal_digit, base2)
# Return
return new_base_number



def main():
"""Read command-line arguments and convert given digits between bases."""
import sys
args = sys.argv[1:] # Ignore script file name
if len(args) == 3:
digits = args[0]
base1 = int(args[1])
base2 = int(args[2])
# Convert given digits between bases
result = convert(digits, base1, base2)
print('{} in base {} is {} in base {}'.format(digits, base1, result, base2))
else:
print('Usage: {} digits base1 base2'.format(sys.argv[0]))
print('Converts digits from base1 to base2')



if __name__ == '__main__':
main()
print(decode('123456', 8))
print(decode('123456', 9))
print(decode('123456', 10))
print(decode('123456', 12))
print(decode('123456', 15))
print(decode('123456', 20))
print(decode('123456', 25))
print(decode('123456', 30))
print(decode('123456', 35))
print(decode('123456', 36))


I think my code is pretty robust because it passes all these unittest cases too.



#!python

from bases import decode, encode, convert
import unittest


class BasesDecodeTest(unittest.TestCase):

def test_decode_binary(self):
assert decode('0', 2) == 0
assert decode('1', 2) == 1
assert decode('10', 2) == 2
assert decode('11', 2) == 3
assert decode('100', 2) == 4
assert decode('101', 2) == 5
assert decode('110', 2) == 6
assert decode('111', 2) == 7
assert decode('1000', 2) == 8
assert decode('1001', 2) == 9
assert decode('1010', 2) == 10
assert decode('1011', 2) == 11
assert decode('1100', 2) == 12
assert decode('1101', 2) == 13
assert decode('1110', 2) == 14
assert decode('1111', 2) == 15

def test_decode_decimal(self):
assert decode('5', 10) == 5
assert decode('9', 10) == 9
assert decode('10', 10) == 10
assert decode('25', 10) == 25
assert decode('64', 10) == 64
assert decode('99', 10) == 99
assert decode('123', 10) == 123
assert decode('789', 10) == 789
assert decode('2345', 10) == 2345
assert decode('6789', 10) == 6789
assert decode('13579', 10) == 13579
assert decode('24680', 10) == 24680

def test_decode_123456(self):
assert decode('123456', 8) ==42798
assert decode('123456', 9) == 74733
assert decode('123456', 10) == 123456
assert decode('123456', 12) == 296130
assert decode('123456', 15) == 871731
assert decode('123456', 20) == 3545706
assert decode('123456', 25) == 10596381
assert decode('123456', 30) == 26004756
assert decode('123456', 35) == 55656831
assert decode('123456', 36) == 63970746

def test_decode_hexadecimal(self):
assert decode('a', 16) == 10
assert decode('f', 16) == 15
assert decode('99', 16) == 153
assert decode('ff', 16) == 255
assert decode('ace', 16) == 2766
assert decode('cab', 16) == 3243
assert decode('bead', 16) == 48813
assert decode('face', 16) == 64206
assert decode('c0ffee', 16) == 12648430
assert decode('facade', 16) == 16435934
assert decode('deadbeef', 16) == 3735928559
assert decode('f007ba11', 16) == 4027038225

def test_decode_10(self):
assert decode('10', 2) == 2
assert decode('10', 4) == 4
assert decode('10', 8) == 8
assert decode('10', 10) == 10
assert decode('10', 16) == 16
assert decode('10', 25) == 25
assert decode('10', 32) == 32
assert decode('10', 36) == 36

def test_decode_1010(self):
assert decode('1010', 2) == 10
assert decode('1010', 4) == 68
assert decode('1010', 8) == 520
assert decode('1010', 10) == 1010
assert decode('1010', 16) == 4112
assert decode('1010', 25) == 15650
assert decode('1010', 32) == 32800
assert decode('1010', 36) == 46692

def test_decode_101101(self):
assert decode('101101', 2) == 45
assert decode('101101', 4) == 1105
assert decode('101101', 8) == 33345
assert decode('101101', 10) == 101101
assert decode('101101', 16) == 1052929
assert decode('101101', 25) == 9781876
assert decode('101101', 32) == 33588225
assert decode('101101', 36) == 60514129


class BasesEncodeTest(unittest.TestCase):

def test_encode_binary(self):
# assert encode(0, 2) == '0' # Should '' be valid?
assert encode(1, 2) == '1'
assert encode(2, 2) == '10'
assert encode(3, 2) == '11'
assert encode(4, 2) == '100'
assert encode(5, 2) == '101'
assert encode(6, 2) == '110'
assert encode(7, 2) == '111'
assert encode(8, 2) == '1000'
assert encode(9, 2) == '1001'
assert encode(10, 2) == '1010'
assert encode(11, 2) == '1011'
assert encode(12, 2) == '1100'
assert encode(13, 2) == '1101'
assert encode(14, 2) == '1110'
assert encode(15, 2) == '1111'

def test_encode_decimal(self):
# assert encode(0, 10) == '0' # Should '' be valid?
assert encode(5, 10) == '5'
assert encode(10, 10) == '10'
assert encode(25, 10) == '25'
assert encode(64, 10) == '64'
assert encode(99, 10) == '99'
assert encode(123, 10) == '123'
assert encode(789, 10) == '789'
assert encode(2345, 10) == '2345'
assert encode(6789, 10) == '6789'
assert encode(13579, 10) == '13579'
assert encode(24680, 10) == '24680'

def test_encode_hexadecimal(self):
assert encode(10, 16) == 'a'
assert encode(15, 16) == 'f'
assert encode(153, 16) == '99'
assert encode(255, 16) == 'ff'
assert encode(2766, 16) == 'ace'
assert encode(3243, 16) == 'cab'
assert encode(48813, 16) == 'bead'
assert encode(64206, 16) == 'face'
assert encode(12648430, 16) == 'c0ffee'
assert encode(16435934, 16) == 'facade'
assert encode(3735928559, 16) == 'deadbeef'
assert encode(4027038225, 16) == 'f007ba11'

def test_encode_1234(self):
assert encode(1234, 2) == '10011010010'
assert encode(1234, 3) == '1200201'
assert encode(1234, 4) == '103102'
assert encode(1234, 5) == '14414'
assert encode(1234, 8) == '2322'
assert encode(1234, 10) == '1234'
assert encode(1234, 16) == '4d2'
assert encode(1234, 32) == '16i'

def test_encode_248975(self):
assert encode(248975, 2) == '111100110010001111'
assert encode(248975, 4) == '330302033'
assert encode(248975, 8) == '746217'
assert encode(248975, 10) == '248975'
assert encode(248975, 16) == '3cc8f'
assert encode(248975, 25) == 'fn90'
assert encode(248975, 32) == '7j4f'
assert encode(248975, 36) == '5c3z'

def test_encode_into_10(self):
assert encode(2, 2) == '10'
assert encode(4, 4) == '10'
assert encode(8, 8) == '10'
assert encode(10, 10) == '10'
assert encode(16, 16) == '10'
assert encode(25, 25) == '10'
assert encode(32, 32) == '10'
assert encode(36, 36) == '10'

def test_encode_into_1010(self):
assert encode(10, 2) == '1010'
assert encode(68, 4) == '1010'
assert encode(520, 8) == '1010'
assert encode(1010, 10) == '1010'
assert encode(4112, 16) == '1010'
assert encode(15650, 25) == '1010'
assert encode(32800, 32) == '1010'
assert encode(46692, 36) == '1010'

def test_encode_into_101101(self):
assert encode(45, 2) == '101101'
assert encode(1105, 4) == '101101'
assert encode(33345, 8) == '101101'
assert encode(101101, 10) == '101101'
assert encode(1052929, 16) == '101101'
assert encode(9781876, 25) == '101101'
assert encode(33588225, 32) == '101101'
assert encode(60514129, 36) == '101101'


class BasesConvertTest(unittest.TestCase):

def test_convert_from_binary(self):
assert convert('1101', 2, 3) == '111'
assert convert('1101', 2, 4) == '31'
assert convert('1101', 2, 8) == '15'
assert convert('1101', 2, 10) == '13'
assert convert('101010', 2, 3) == '1120'
assert convert('101010', 2, 4) == '222'
assert convert('101010', 2, 8) == '52'
assert convert('101010', 2, 10) == '42'
assert convert('101010', 2, 16) == '2a'
assert convert('101010', 2, 25) == '1h'
assert convert('101010', 2, 32) == '1a'
assert convert('101010', 2, 36) == '16'

def test_convert_to_binary(self):
assert convert('111', 3, 2) == '1101'
assert convert('31', 4, 2) == '1101'
assert convert('15', 8, 2) == '1101'
assert convert('13', 10, 2) == '1101'
assert convert('101', 3, 2) == '1010'
assert convert('101', 4, 2) == '10001'
assert convert('101', 8, 2) == '1000001'
assert convert('101', 10, 2) == '1100101'
assert convert('101', 16, 2) == '100000001'
assert convert('101', 25, 2) == '1001110010'
assert convert('101', 32, 2) == '10000000001'
assert convert('101', 36, 2) == '10100010001'

def test_convert_hexadecimal_to_decimal(self):
assert convert('a', 16, 10) == '10'
assert convert('f', 16, 10) == '15'
assert convert('99', 16, 10) == '153'
assert convert('ff', 16, 10) == '255'
assert convert('ace', 16, 10) == '2766'
assert convert('cab', 16, 10) == '3243'
assert convert('bead', 16, 10) == '48813'
assert convert('face', 16, 10) == '64206'
assert convert('c0ffee', 16, 10) == '12648430'
assert convert('facade', 16, 10) == '16435934'
assert convert('deadbeef', 16, 10) == '3735928559'
assert convert('f007ba11', 16, 10) == '4027038225'

def test_convert_decimal_to_hexadecimal(self):
assert convert('10', 10, 16) == 'a'
assert convert('15', 10, 16) == 'f'
assert convert('153', 10, 16) == '99'
assert convert('255', 10, 16) == 'ff'
assert convert('2766', 10, 16) == 'ace'
assert convert('3243', 10, 16) == 'cab'
assert convert('48813', 10, 16) == 'bead'
assert convert('64206', 10, 16) == 'face'
assert convert('12648430', 10, 16) == 'c0ffee'
assert convert('16435934', 10, 16) == 'facade'
assert convert('3735928559', 10, 16) == 'deadbeef'
assert convert('4027038225', 10, 16) == 'f007ba11'

def test_convert_hexadecimal_to_binary(self):
assert convert('a', 16, 2) == '1010'
assert convert('b', 16, 2) == '1011'
assert convert('c', 16, 2) == '1100'
assert convert('d', 16, 2) == '1101'
assert convert('e', 16, 2) == '1110'
assert convert('f', 16, 2) == '1111'
assert convert('c840', 16, 2) == '1100100001000000'
assert convert('d951', 16, 2) == '1101100101010001'
assert convert('ea62', 16, 2) == '1110101001100010'
assert convert('fb73', 16, 2) == '1111101101110011'

def test_convert_binary_to_hexadecimal(self):
assert convert('1010', 2, 16) == 'a'
assert convert('1011', 2, 16) == 'b'
assert convert('1100', 2, 16) == 'c'
assert convert('1101', 2, 16) == 'd'
assert convert('1110', 2, 16) == 'e'
assert convert('1111', 2, 16) == 'f'
assert convert('1100100001000000', 2, 16) == 'c840'
assert convert('1101100101010001', 2, 16) == 'd951'
assert convert('1110101001100010', 2, 16) == 'ea62'
assert convert('1111101101110011', 2, 16) == 'fb73'


if __name__ == '__main__':
unittest.main()









share|improve this question




















  • 5




    You do know that the built-in int can already do the job of your decode, right? Try int("abcdefghijklmnopqrstuvwxyz0123456789", 36). Re-inventing existing functionality is fine (especially for interviews or for learning purposes), but you should say that you are. We even have a tag for it (reinventing-the-wheel).
    – Graipher
    Nov 5 '17 at 9:28
















4












4








4


1





I encountered this question as I am preparing for my code interview. I was implementing a base function that can decode and encode any bases from base 2 to base 36. I think my decode and encode functions work fine. It can convert digits from binary (base 2 - 36).



My task:




Decode digits from hexadecimal (base 16). Decode given digits in given base to number in base 10.




Also:




Decode digits from any base (2 up to 36).




I created a helper function that handles hexadecimal digit_from_letter, as it checks if the digit is a digit else it's a letter.



import string

def letter_from_num(num):
""" Convert letter from number:
input: int -- integer representation of number (in base 10)
return: strings of letters """
letters ='abcdefghijklmnopqrstuvwxyz'
return letters[num - 10]

def digit_from_letter(letter):
"""
input: any letter
return: int -- number representation of number (in base 10)
handles digits from hexadecimal (base 16)
handles digits from any base (2 up to 36)
math function that calculate the number based on math conversion
this calculate from the 36 letters -97 + 1
"""
num = ord(letter) - 97 + 10
return num

def decode(digits, base):
"""Decode given digits in given base to number in base 10.
digits: str -- string representation of number (in given base)
base: int -- base of given number
return: result is int -- integer representation of number (in base 10)"""
# Handle up to base 36 [0-9a-z]
assert 2 <= base <= 36, 'base is out of range: {}'.format(base)
result = 0
# Loop through the enumeration
# index and digit
# create a helper function that handles hexadecimal digit_from_letter
for index, digit in enumerate(digits):
if digit.isdigit():
digit_to_add = int(digit)
else:
digit_to_add = digit_from_letter(digit)
# add them together on the result with the digital_to_add to the result
result += digit_to_add
if index is not len(digits) - 1:
result *= base
else:
1
# Return the result decimal digit
return result

def encode(number, base):
"""Encode given number in base 10 to digits in given base.
number: int -- integer representation of number (in base 10)
base: int -- base to convert to
return: str -- string representation of number (in given base)"""
# Handle up to base 36 [0-9a-z]
assert 2 <= base <= 36, 'base is out of range: {}'.format(base)
new_base_number = ''
# encode helps me to make sure that we will work
while number != 0:
remainder = number % base
number = number // base
if (remainder >= 10 and base > 10):
remainder = letter_from_num(remainder)
else:
remainder
new_base_number += str(remainder)
# Reverse
new_base_number = new_base_number[::-1]
return new_base_number


def convert(digits, base1, base2):
"""Convert given digits in base1 to digits in base2.
digits: str -- string representation of number (in base1)
base1: int -- base of given number
base2: int -- base to convert to
return: str -- string representation of number (in base2)"""
assert 2 <= base1 <= 36, 'base1 is out of range: {}'.format(base1)
assert 2 <= base2 <= 36, 'base2 is out of range: {}'.format(base2)
# result = convert(digits, base1, base2)
# if
if base1 == 10:
new_base_number = encode(int(decimal_digit), base2)
else:
decimal_digit = decode(digits, base1)
new_base_number = encode(decimal_digit, base2)
# Return
return new_base_number



def main():
"""Read command-line arguments and convert given digits between bases."""
import sys
args = sys.argv[1:] # Ignore script file name
if len(args) == 3:
digits = args[0]
base1 = int(args[1])
base2 = int(args[2])
# Convert given digits between bases
result = convert(digits, base1, base2)
print('{} in base {} is {} in base {}'.format(digits, base1, result, base2))
else:
print('Usage: {} digits base1 base2'.format(sys.argv[0]))
print('Converts digits from base1 to base2')



if __name__ == '__main__':
main()
print(decode('123456', 8))
print(decode('123456', 9))
print(decode('123456', 10))
print(decode('123456', 12))
print(decode('123456', 15))
print(decode('123456', 20))
print(decode('123456', 25))
print(decode('123456', 30))
print(decode('123456', 35))
print(decode('123456', 36))


I think my code is pretty robust because it passes all these unittest cases too.



#!python

from bases import decode, encode, convert
import unittest


class BasesDecodeTest(unittest.TestCase):

def test_decode_binary(self):
assert decode('0', 2) == 0
assert decode('1', 2) == 1
assert decode('10', 2) == 2
assert decode('11', 2) == 3
assert decode('100', 2) == 4
assert decode('101', 2) == 5
assert decode('110', 2) == 6
assert decode('111', 2) == 7
assert decode('1000', 2) == 8
assert decode('1001', 2) == 9
assert decode('1010', 2) == 10
assert decode('1011', 2) == 11
assert decode('1100', 2) == 12
assert decode('1101', 2) == 13
assert decode('1110', 2) == 14
assert decode('1111', 2) == 15

def test_decode_decimal(self):
assert decode('5', 10) == 5
assert decode('9', 10) == 9
assert decode('10', 10) == 10
assert decode('25', 10) == 25
assert decode('64', 10) == 64
assert decode('99', 10) == 99
assert decode('123', 10) == 123
assert decode('789', 10) == 789
assert decode('2345', 10) == 2345
assert decode('6789', 10) == 6789
assert decode('13579', 10) == 13579
assert decode('24680', 10) == 24680

def test_decode_123456(self):
assert decode('123456', 8) ==42798
assert decode('123456', 9) == 74733
assert decode('123456', 10) == 123456
assert decode('123456', 12) == 296130
assert decode('123456', 15) == 871731
assert decode('123456', 20) == 3545706
assert decode('123456', 25) == 10596381
assert decode('123456', 30) == 26004756
assert decode('123456', 35) == 55656831
assert decode('123456', 36) == 63970746

def test_decode_hexadecimal(self):
assert decode('a', 16) == 10
assert decode('f', 16) == 15
assert decode('99', 16) == 153
assert decode('ff', 16) == 255
assert decode('ace', 16) == 2766
assert decode('cab', 16) == 3243
assert decode('bead', 16) == 48813
assert decode('face', 16) == 64206
assert decode('c0ffee', 16) == 12648430
assert decode('facade', 16) == 16435934
assert decode('deadbeef', 16) == 3735928559
assert decode('f007ba11', 16) == 4027038225

def test_decode_10(self):
assert decode('10', 2) == 2
assert decode('10', 4) == 4
assert decode('10', 8) == 8
assert decode('10', 10) == 10
assert decode('10', 16) == 16
assert decode('10', 25) == 25
assert decode('10', 32) == 32
assert decode('10', 36) == 36

def test_decode_1010(self):
assert decode('1010', 2) == 10
assert decode('1010', 4) == 68
assert decode('1010', 8) == 520
assert decode('1010', 10) == 1010
assert decode('1010', 16) == 4112
assert decode('1010', 25) == 15650
assert decode('1010', 32) == 32800
assert decode('1010', 36) == 46692

def test_decode_101101(self):
assert decode('101101', 2) == 45
assert decode('101101', 4) == 1105
assert decode('101101', 8) == 33345
assert decode('101101', 10) == 101101
assert decode('101101', 16) == 1052929
assert decode('101101', 25) == 9781876
assert decode('101101', 32) == 33588225
assert decode('101101', 36) == 60514129


class BasesEncodeTest(unittest.TestCase):

def test_encode_binary(self):
# assert encode(0, 2) == '0' # Should '' be valid?
assert encode(1, 2) == '1'
assert encode(2, 2) == '10'
assert encode(3, 2) == '11'
assert encode(4, 2) == '100'
assert encode(5, 2) == '101'
assert encode(6, 2) == '110'
assert encode(7, 2) == '111'
assert encode(8, 2) == '1000'
assert encode(9, 2) == '1001'
assert encode(10, 2) == '1010'
assert encode(11, 2) == '1011'
assert encode(12, 2) == '1100'
assert encode(13, 2) == '1101'
assert encode(14, 2) == '1110'
assert encode(15, 2) == '1111'

def test_encode_decimal(self):
# assert encode(0, 10) == '0' # Should '' be valid?
assert encode(5, 10) == '5'
assert encode(10, 10) == '10'
assert encode(25, 10) == '25'
assert encode(64, 10) == '64'
assert encode(99, 10) == '99'
assert encode(123, 10) == '123'
assert encode(789, 10) == '789'
assert encode(2345, 10) == '2345'
assert encode(6789, 10) == '6789'
assert encode(13579, 10) == '13579'
assert encode(24680, 10) == '24680'

def test_encode_hexadecimal(self):
assert encode(10, 16) == 'a'
assert encode(15, 16) == 'f'
assert encode(153, 16) == '99'
assert encode(255, 16) == 'ff'
assert encode(2766, 16) == 'ace'
assert encode(3243, 16) == 'cab'
assert encode(48813, 16) == 'bead'
assert encode(64206, 16) == 'face'
assert encode(12648430, 16) == 'c0ffee'
assert encode(16435934, 16) == 'facade'
assert encode(3735928559, 16) == 'deadbeef'
assert encode(4027038225, 16) == 'f007ba11'

def test_encode_1234(self):
assert encode(1234, 2) == '10011010010'
assert encode(1234, 3) == '1200201'
assert encode(1234, 4) == '103102'
assert encode(1234, 5) == '14414'
assert encode(1234, 8) == '2322'
assert encode(1234, 10) == '1234'
assert encode(1234, 16) == '4d2'
assert encode(1234, 32) == '16i'

def test_encode_248975(self):
assert encode(248975, 2) == '111100110010001111'
assert encode(248975, 4) == '330302033'
assert encode(248975, 8) == '746217'
assert encode(248975, 10) == '248975'
assert encode(248975, 16) == '3cc8f'
assert encode(248975, 25) == 'fn90'
assert encode(248975, 32) == '7j4f'
assert encode(248975, 36) == '5c3z'

def test_encode_into_10(self):
assert encode(2, 2) == '10'
assert encode(4, 4) == '10'
assert encode(8, 8) == '10'
assert encode(10, 10) == '10'
assert encode(16, 16) == '10'
assert encode(25, 25) == '10'
assert encode(32, 32) == '10'
assert encode(36, 36) == '10'

def test_encode_into_1010(self):
assert encode(10, 2) == '1010'
assert encode(68, 4) == '1010'
assert encode(520, 8) == '1010'
assert encode(1010, 10) == '1010'
assert encode(4112, 16) == '1010'
assert encode(15650, 25) == '1010'
assert encode(32800, 32) == '1010'
assert encode(46692, 36) == '1010'

def test_encode_into_101101(self):
assert encode(45, 2) == '101101'
assert encode(1105, 4) == '101101'
assert encode(33345, 8) == '101101'
assert encode(101101, 10) == '101101'
assert encode(1052929, 16) == '101101'
assert encode(9781876, 25) == '101101'
assert encode(33588225, 32) == '101101'
assert encode(60514129, 36) == '101101'


class BasesConvertTest(unittest.TestCase):

def test_convert_from_binary(self):
assert convert('1101', 2, 3) == '111'
assert convert('1101', 2, 4) == '31'
assert convert('1101', 2, 8) == '15'
assert convert('1101', 2, 10) == '13'
assert convert('101010', 2, 3) == '1120'
assert convert('101010', 2, 4) == '222'
assert convert('101010', 2, 8) == '52'
assert convert('101010', 2, 10) == '42'
assert convert('101010', 2, 16) == '2a'
assert convert('101010', 2, 25) == '1h'
assert convert('101010', 2, 32) == '1a'
assert convert('101010', 2, 36) == '16'

def test_convert_to_binary(self):
assert convert('111', 3, 2) == '1101'
assert convert('31', 4, 2) == '1101'
assert convert('15', 8, 2) == '1101'
assert convert('13', 10, 2) == '1101'
assert convert('101', 3, 2) == '1010'
assert convert('101', 4, 2) == '10001'
assert convert('101', 8, 2) == '1000001'
assert convert('101', 10, 2) == '1100101'
assert convert('101', 16, 2) == '100000001'
assert convert('101', 25, 2) == '1001110010'
assert convert('101', 32, 2) == '10000000001'
assert convert('101', 36, 2) == '10100010001'

def test_convert_hexadecimal_to_decimal(self):
assert convert('a', 16, 10) == '10'
assert convert('f', 16, 10) == '15'
assert convert('99', 16, 10) == '153'
assert convert('ff', 16, 10) == '255'
assert convert('ace', 16, 10) == '2766'
assert convert('cab', 16, 10) == '3243'
assert convert('bead', 16, 10) == '48813'
assert convert('face', 16, 10) == '64206'
assert convert('c0ffee', 16, 10) == '12648430'
assert convert('facade', 16, 10) == '16435934'
assert convert('deadbeef', 16, 10) == '3735928559'
assert convert('f007ba11', 16, 10) == '4027038225'

def test_convert_decimal_to_hexadecimal(self):
assert convert('10', 10, 16) == 'a'
assert convert('15', 10, 16) == 'f'
assert convert('153', 10, 16) == '99'
assert convert('255', 10, 16) == 'ff'
assert convert('2766', 10, 16) == 'ace'
assert convert('3243', 10, 16) == 'cab'
assert convert('48813', 10, 16) == 'bead'
assert convert('64206', 10, 16) == 'face'
assert convert('12648430', 10, 16) == 'c0ffee'
assert convert('16435934', 10, 16) == 'facade'
assert convert('3735928559', 10, 16) == 'deadbeef'
assert convert('4027038225', 10, 16) == 'f007ba11'

def test_convert_hexadecimal_to_binary(self):
assert convert('a', 16, 2) == '1010'
assert convert('b', 16, 2) == '1011'
assert convert('c', 16, 2) == '1100'
assert convert('d', 16, 2) == '1101'
assert convert('e', 16, 2) == '1110'
assert convert('f', 16, 2) == '1111'
assert convert('c840', 16, 2) == '1100100001000000'
assert convert('d951', 16, 2) == '1101100101010001'
assert convert('ea62', 16, 2) == '1110101001100010'
assert convert('fb73', 16, 2) == '1111101101110011'

def test_convert_binary_to_hexadecimal(self):
assert convert('1010', 2, 16) == 'a'
assert convert('1011', 2, 16) == 'b'
assert convert('1100', 2, 16) == 'c'
assert convert('1101', 2, 16) == 'd'
assert convert('1110', 2, 16) == 'e'
assert convert('1111', 2, 16) == 'f'
assert convert('1100100001000000', 2, 16) == 'c840'
assert convert('1101100101010001', 2, 16) == 'd951'
assert convert('1110101001100010', 2, 16) == 'ea62'
assert convert('1111101101110011', 2, 16) == 'fb73'


if __name__ == '__main__':
unittest.main()









share|improve this question















I encountered this question as I am preparing for my code interview. I was implementing a base function that can decode and encode any bases from base 2 to base 36. I think my decode and encode functions work fine. It can convert digits from binary (base 2 - 36).



My task:




Decode digits from hexadecimal (base 16). Decode given digits in given base to number in base 10.




Also:




Decode digits from any base (2 up to 36).




I created a helper function that handles hexadecimal digit_from_letter, as it checks if the digit is a digit else it's a letter.



import string

def letter_from_num(num):
""" Convert letter from number:
input: int -- integer representation of number (in base 10)
return: strings of letters """
letters ='abcdefghijklmnopqrstuvwxyz'
return letters[num - 10]

def digit_from_letter(letter):
"""
input: any letter
return: int -- number representation of number (in base 10)
handles digits from hexadecimal (base 16)
handles digits from any base (2 up to 36)
math function that calculate the number based on math conversion
this calculate from the 36 letters -97 + 1
"""
num = ord(letter) - 97 + 10
return num

def decode(digits, base):
"""Decode given digits in given base to number in base 10.
digits: str -- string representation of number (in given base)
base: int -- base of given number
return: result is int -- integer representation of number (in base 10)"""
# Handle up to base 36 [0-9a-z]
assert 2 <= base <= 36, 'base is out of range: {}'.format(base)
result = 0
# Loop through the enumeration
# index and digit
# create a helper function that handles hexadecimal digit_from_letter
for index, digit in enumerate(digits):
if digit.isdigit():
digit_to_add = int(digit)
else:
digit_to_add = digit_from_letter(digit)
# add them together on the result with the digital_to_add to the result
result += digit_to_add
if index is not len(digits) - 1:
result *= base
else:
1
# Return the result decimal digit
return result

def encode(number, base):
"""Encode given number in base 10 to digits in given base.
number: int -- integer representation of number (in base 10)
base: int -- base to convert to
return: str -- string representation of number (in given base)"""
# Handle up to base 36 [0-9a-z]
assert 2 <= base <= 36, 'base is out of range: {}'.format(base)
new_base_number = ''
# encode helps me to make sure that we will work
while number != 0:
remainder = number % base
number = number // base
if (remainder >= 10 and base > 10):
remainder = letter_from_num(remainder)
else:
remainder
new_base_number += str(remainder)
# Reverse
new_base_number = new_base_number[::-1]
return new_base_number


def convert(digits, base1, base2):
"""Convert given digits in base1 to digits in base2.
digits: str -- string representation of number (in base1)
base1: int -- base of given number
base2: int -- base to convert to
return: str -- string representation of number (in base2)"""
assert 2 <= base1 <= 36, 'base1 is out of range: {}'.format(base1)
assert 2 <= base2 <= 36, 'base2 is out of range: {}'.format(base2)
# result = convert(digits, base1, base2)
# if
if base1 == 10:
new_base_number = encode(int(decimal_digit), base2)
else:
decimal_digit = decode(digits, base1)
new_base_number = encode(decimal_digit, base2)
# Return
return new_base_number



def main():
"""Read command-line arguments and convert given digits between bases."""
import sys
args = sys.argv[1:] # Ignore script file name
if len(args) == 3:
digits = args[0]
base1 = int(args[1])
base2 = int(args[2])
# Convert given digits between bases
result = convert(digits, base1, base2)
print('{} in base {} is {} in base {}'.format(digits, base1, result, base2))
else:
print('Usage: {} digits base1 base2'.format(sys.argv[0]))
print('Converts digits from base1 to base2')



if __name__ == '__main__':
main()
print(decode('123456', 8))
print(decode('123456', 9))
print(decode('123456', 10))
print(decode('123456', 12))
print(decode('123456', 15))
print(decode('123456', 20))
print(decode('123456', 25))
print(decode('123456', 30))
print(decode('123456', 35))
print(decode('123456', 36))


I think my code is pretty robust because it passes all these unittest cases too.



#!python

from bases import decode, encode, convert
import unittest


class BasesDecodeTest(unittest.TestCase):

def test_decode_binary(self):
assert decode('0', 2) == 0
assert decode('1', 2) == 1
assert decode('10', 2) == 2
assert decode('11', 2) == 3
assert decode('100', 2) == 4
assert decode('101', 2) == 5
assert decode('110', 2) == 6
assert decode('111', 2) == 7
assert decode('1000', 2) == 8
assert decode('1001', 2) == 9
assert decode('1010', 2) == 10
assert decode('1011', 2) == 11
assert decode('1100', 2) == 12
assert decode('1101', 2) == 13
assert decode('1110', 2) == 14
assert decode('1111', 2) == 15

def test_decode_decimal(self):
assert decode('5', 10) == 5
assert decode('9', 10) == 9
assert decode('10', 10) == 10
assert decode('25', 10) == 25
assert decode('64', 10) == 64
assert decode('99', 10) == 99
assert decode('123', 10) == 123
assert decode('789', 10) == 789
assert decode('2345', 10) == 2345
assert decode('6789', 10) == 6789
assert decode('13579', 10) == 13579
assert decode('24680', 10) == 24680

def test_decode_123456(self):
assert decode('123456', 8) ==42798
assert decode('123456', 9) == 74733
assert decode('123456', 10) == 123456
assert decode('123456', 12) == 296130
assert decode('123456', 15) == 871731
assert decode('123456', 20) == 3545706
assert decode('123456', 25) == 10596381
assert decode('123456', 30) == 26004756
assert decode('123456', 35) == 55656831
assert decode('123456', 36) == 63970746

def test_decode_hexadecimal(self):
assert decode('a', 16) == 10
assert decode('f', 16) == 15
assert decode('99', 16) == 153
assert decode('ff', 16) == 255
assert decode('ace', 16) == 2766
assert decode('cab', 16) == 3243
assert decode('bead', 16) == 48813
assert decode('face', 16) == 64206
assert decode('c0ffee', 16) == 12648430
assert decode('facade', 16) == 16435934
assert decode('deadbeef', 16) == 3735928559
assert decode('f007ba11', 16) == 4027038225

def test_decode_10(self):
assert decode('10', 2) == 2
assert decode('10', 4) == 4
assert decode('10', 8) == 8
assert decode('10', 10) == 10
assert decode('10', 16) == 16
assert decode('10', 25) == 25
assert decode('10', 32) == 32
assert decode('10', 36) == 36

def test_decode_1010(self):
assert decode('1010', 2) == 10
assert decode('1010', 4) == 68
assert decode('1010', 8) == 520
assert decode('1010', 10) == 1010
assert decode('1010', 16) == 4112
assert decode('1010', 25) == 15650
assert decode('1010', 32) == 32800
assert decode('1010', 36) == 46692

def test_decode_101101(self):
assert decode('101101', 2) == 45
assert decode('101101', 4) == 1105
assert decode('101101', 8) == 33345
assert decode('101101', 10) == 101101
assert decode('101101', 16) == 1052929
assert decode('101101', 25) == 9781876
assert decode('101101', 32) == 33588225
assert decode('101101', 36) == 60514129


class BasesEncodeTest(unittest.TestCase):

def test_encode_binary(self):
# assert encode(0, 2) == '0' # Should '' be valid?
assert encode(1, 2) == '1'
assert encode(2, 2) == '10'
assert encode(3, 2) == '11'
assert encode(4, 2) == '100'
assert encode(5, 2) == '101'
assert encode(6, 2) == '110'
assert encode(7, 2) == '111'
assert encode(8, 2) == '1000'
assert encode(9, 2) == '1001'
assert encode(10, 2) == '1010'
assert encode(11, 2) == '1011'
assert encode(12, 2) == '1100'
assert encode(13, 2) == '1101'
assert encode(14, 2) == '1110'
assert encode(15, 2) == '1111'

def test_encode_decimal(self):
# assert encode(0, 10) == '0' # Should '' be valid?
assert encode(5, 10) == '5'
assert encode(10, 10) == '10'
assert encode(25, 10) == '25'
assert encode(64, 10) == '64'
assert encode(99, 10) == '99'
assert encode(123, 10) == '123'
assert encode(789, 10) == '789'
assert encode(2345, 10) == '2345'
assert encode(6789, 10) == '6789'
assert encode(13579, 10) == '13579'
assert encode(24680, 10) == '24680'

def test_encode_hexadecimal(self):
assert encode(10, 16) == 'a'
assert encode(15, 16) == 'f'
assert encode(153, 16) == '99'
assert encode(255, 16) == 'ff'
assert encode(2766, 16) == 'ace'
assert encode(3243, 16) == 'cab'
assert encode(48813, 16) == 'bead'
assert encode(64206, 16) == 'face'
assert encode(12648430, 16) == 'c0ffee'
assert encode(16435934, 16) == 'facade'
assert encode(3735928559, 16) == 'deadbeef'
assert encode(4027038225, 16) == 'f007ba11'

def test_encode_1234(self):
assert encode(1234, 2) == '10011010010'
assert encode(1234, 3) == '1200201'
assert encode(1234, 4) == '103102'
assert encode(1234, 5) == '14414'
assert encode(1234, 8) == '2322'
assert encode(1234, 10) == '1234'
assert encode(1234, 16) == '4d2'
assert encode(1234, 32) == '16i'

def test_encode_248975(self):
assert encode(248975, 2) == '111100110010001111'
assert encode(248975, 4) == '330302033'
assert encode(248975, 8) == '746217'
assert encode(248975, 10) == '248975'
assert encode(248975, 16) == '3cc8f'
assert encode(248975, 25) == 'fn90'
assert encode(248975, 32) == '7j4f'
assert encode(248975, 36) == '5c3z'

def test_encode_into_10(self):
assert encode(2, 2) == '10'
assert encode(4, 4) == '10'
assert encode(8, 8) == '10'
assert encode(10, 10) == '10'
assert encode(16, 16) == '10'
assert encode(25, 25) == '10'
assert encode(32, 32) == '10'
assert encode(36, 36) == '10'

def test_encode_into_1010(self):
assert encode(10, 2) == '1010'
assert encode(68, 4) == '1010'
assert encode(520, 8) == '1010'
assert encode(1010, 10) == '1010'
assert encode(4112, 16) == '1010'
assert encode(15650, 25) == '1010'
assert encode(32800, 32) == '1010'
assert encode(46692, 36) == '1010'

def test_encode_into_101101(self):
assert encode(45, 2) == '101101'
assert encode(1105, 4) == '101101'
assert encode(33345, 8) == '101101'
assert encode(101101, 10) == '101101'
assert encode(1052929, 16) == '101101'
assert encode(9781876, 25) == '101101'
assert encode(33588225, 32) == '101101'
assert encode(60514129, 36) == '101101'


class BasesConvertTest(unittest.TestCase):

def test_convert_from_binary(self):
assert convert('1101', 2, 3) == '111'
assert convert('1101', 2, 4) == '31'
assert convert('1101', 2, 8) == '15'
assert convert('1101', 2, 10) == '13'
assert convert('101010', 2, 3) == '1120'
assert convert('101010', 2, 4) == '222'
assert convert('101010', 2, 8) == '52'
assert convert('101010', 2, 10) == '42'
assert convert('101010', 2, 16) == '2a'
assert convert('101010', 2, 25) == '1h'
assert convert('101010', 2, 32) == '1a'
assert convert('101010', 2, 36) == '16'

def test_convert_to_binary(self):
assert convert('111', 3, 2) == '1101'
assert convert('31', 4, 2) == '1101'
assert convert('15', 8, 2) == '1101'
assert convert('13', 10, 2) == '1101'
assert convert('101', 3, 2) == '1010'
assert convert('101', 4, 2) == '10001'
assert convert('101', 8, 2) == '1000001'
assert convert('101', 10, 2) == '1100101'
assert convert('101', 16, 2) == '100000001'
assert convert('101', 25, 2) == '1001110010'
assert convert('101', 32, 2) == '10000000001'
assert convert('101', 36, 2) == '10100010001'

def test_convert_hexadecimal_to_decimal(self):
assert convert('a', 16, 10) == '10'
assert convert('f', 16, 10) == '15'
assert convert('99', 16, 10) == '153'
assert convert('ff', 16, 10) == '255'
assert convert('ace', 16, 10) == '2766'
assert convert('cab', 16, 10) == '3243'
assert convert('bead', 16, 10) == '48813'
assert convert('face', 16, 10) == '64206'
assert convert('c0ffee', 16, 10) == '12648430'
assert convert('facade', 16, 10) == '16435934'
assert convert('deadbeef', 16, 10) == '3735928559'
assert convert('f007ba11', 16, 10) == '4027038225'

def test_convert_decimal_to_hexadecimal(self):
assert convert('10', 10, 16) == 'a'
assert convert('15', 10, 16) == 'f'
assert convert('153', 10, 16) == '99'
assert convert('255', 10, 16) == 'ff'
assert convert('2766', 10, 16) == 'ace'
assert convert('3243', 10, 16) == 'cab'
assert convert('48813', 10, 16) == 'bead'
assert convert('64206', 10, 16) == 'face'
assert convert('12648430', 10, 16) == 'c0ffee'
assert convert('16435934', 10, 16) == 'facade'
assert convert('3735928559', 10, 16) == 'deadbeef'
assert convert('4027038225', 10, 16) == 'f007ba11'

def test_convert_hexadecimal_to_binary(self):
assert convert('a', 16, 2) == '1010'
assert convert('b', 16, 2) == '1011'
assert convert('c', 16, 2) == '1100'
assert convert('d', 16, 2) == '1101'
assert convert('e', 16, 2) == '1110'
assert convert('f', 16, 2) == '1111'
assert convert('c840', 16, 2) == '1100100001000000'
assert convert('d951', 16, 2) == '1101100101010001'
assert convert('ea62', 16, 2) == '1110101001100010'
assert convert('fb73', 16, 2) == '1111101101110011'

def test_convert_binary_to_hexadecimal(self):
assert convert('1010', 2, 16) == 'a'
assert convert('1011', 2, 16) == 'b'
assert convert('1100', 2, 16) == 'c'
assert convert('1101', 2, 16) == 'd'
assert convert('1110', 2, 16) == 'e'
assert convert('1111', 2, 16) == 'f'
assert convert('1100100001000000', 2, 16) == 'c840'
assert convert('1101100101010001', 2, 16) == 'd951'
assert convert('1110101001100010', 2, 16) == 'ea62'
assert convert('1111101101110011', 2, 16) == 'fb73'


if __name__ == '__main__':
unittest.main()






python interview-questions reinventing-the-wheel number-systems






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 6 '17 at 17:42

























asked Nov 4 '17 at 21:49









NinjaG

809426




809426








  • 5




    You do know that the built-in int can already do the job of your decode, right? Try int("abcdefghijklmnopqrstuvwxyz0123456789", 36). Re-inventing existing functionality is fine (especially for interviews or for learning purposes), but you should say that you are. We even have a tag for it (reinventing-the-wheel).
    – Graipher
    Nov 5 '17 at 9:28
















  • 5




    You do know that the built-in int can already do the job of your decode, right? Try int("abcdefghijklmnopqrstuvwxyz0123456789", 36). Re-inventing existing functionality is fine (especially for interviews or for learning purposes), but you should say that you are. We even have a tag for it (reinventing-the-wheel).
    – Graipher
    Nov 5 '17 at 9:28










5




5




You do know that the built-in int can already do the job of your decode, right? Try int("abcdefghijklmnopqrstuvwxyz0123456789", 36). Re-inventing existing functionality is fine (especially for interviews or for learning purposes), but you should say that you are. We even have a tag for it (reinventing-the-wheel).
– Graipher
Nov 5 '17 at 9:28






You do know that the built-in int can already do the job of your decode, right? Try int("abcdefghijklmnopqrstuvwxyz0123456789", 36). Re-inventing existing functionality is fine (especially for interviews or for learning purposes), but you should say that you are. We even have a tag for it (reinventing-the-wheel).
– Graipher
Nov 5 '17 at 9:28












1 Answer
1






active

oldest

votes


















0















  • Much as I like the presence of docstrings for the functions, I miss one for the module.

  • several docstrings mention int (in base 10) - I hold ints to be without base, represented base 2 if any (→ Bitwise Operations) (and to have a default base to use in conversions from/to str)


  • letter_from_num(num)/digit_from_letter(letter):

    in my book, a digit is (an encoding of) a glyph in a string representation of a number:

    I'd choose digit_for_num(num) and num_for_digit(digit)

    (and hide all "decimal digit special casing" here)

    - These functions are not as defensive as decode()/encode()

    - the literal 97 seems uncalled for

  • decode(digits, base):

    - the comment containing helper function that handles hexadecimal seems incorrect

    (& your IDE or you seem to have missed a variable renamed in the next one)

    - after remainder = number % base, I'd be annoyed if
    remainder >= 10 and base <= 10

    - the else:-branch in "the non-final-digit handling" seems pointless

    - it is cleaner and conventional to just start digit handling with result *= base unconditionally, obsoleting the enumerate


  • encode(number, base)

    - helps me to make sure that we will work just before digit handling is cryptic, at best

    - assigning new_base_number = new_base_number[::-1]to just return it looks clumsy


  • convert(digits, base1, base2)

    - none of the internal comments looks helpful

    - why special-case base1 == 10?

    - decimal_digit looks a misnomer - value? number, integer?


I miss the (trivial) Decode digits from hexadecimal (base 16). part of the task quoted in the code with embedded documentation presented.






share|improve this answer























    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f179634%2fbase-conversion-decode-and-encode-base-to-integer%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0















    • Much as I like the presence of docstrings for the functions, I miss one for the module.

    • several docstrings mention int (in base 10) - I hold ints to be without base, represented base 2 if any (→ Bitwise Operations) (and to have a default base to use in conversions from/to str)


    • letter_from_num(num)/digit_from_letter(letter):

      in my book, a digit is (an encoding of) a glyph in a string representation of a number:

      I'd choose digit_for_num(num) and num_for_digit(digit)

      (and hide all "decimal digit special casing" here)

      - These functions are not as defensive as decode()/encode()

      - the literal 97 seems uncalled for

    • decode(digits, base):

      - the comment containing helper function that handles hexadecimal seems incorrect

      (& your IDE or you seem to have missed a variable renamed in the next one)

      - after remainder = number % base, I'd be annoyed if
      remainder >= 10 and base <= 10

      - the else:-branch in "the non-final-digit handling" seems pointless

      - it is cleaner and conventional to just start digit handling with result *= base unconditionally, obsoleting the enumerate


    • encode(number, base)

      - helps me to make sure that we will work just before digit handling is cryptic, at best

      - assigning new_base_number = new_base_number[::-1]to just return it looks clumsy


    • convert(digits, base1, base2)

      - none of the internal comments looks helpful

      - why special-case base1 == 10?

      - decimal_digit looks a misnomer - value? number, integer?


    I miss the (trivial) Decode digits from hexadecimal (base 16). part of the task quoted in the code with embedded documentation presented.






    share|improve this answer




























      0















      • Much as I like the presence of docstrings for the functions, I miss one for the module.

      • several docstrings mention int (in base 10) - I hold ints to be without base, represented base 2 if any (→ Bitwise Operations) (and to have a default base to use in conversions from/to str)


      • letter_from_num(num)/digit_from_letter(letter):

        in my book, a digit is (an encoding of) a glyph in a string representation of a number:

        I'd choose digit_for_num(num) and num_for_digit(digit)

        (and hide all "decimal digit special casing" here)

        - These functions are not as defensive as decode()/encode()

        - the literal 97 seems uncalled for

      • decode(digits, base):

        - the comment containing helper function that handles hexadecimal seems incorrect

        (& your IDE or you seem to have missed a variable renamed in the next one)

        - after remainder = number % base, I'd be annoyed if
        remainder >= 10 and base <= 10

        - the else:-branch in "the non-final-digit handling" seems pointless

        - it is cleaner and conventional to just start digit handling with result *= base unconditionally, obsoleting the enumerate


      • encode(number, base)

        - helps me to make sure that we will work just before digit handling is cryptic, at best

        - assigning new_base_number = new_base_number[::-1]to just return it looks clumsy


      • convert(digits, base1, base2)

        - none of the internal comments looks helpful

        - why special-case base1 == 10?

        - decimal_digit looks a misnomer - value? number, integer?


      I miss the (trivial) Decode digits from hexadecimal (base 16). part of the task quoted in the code with embedded documentation presented.






      share|improve this answer


























        0












        0








        0







        • Much as I like the presence of docstrings for the functions, I miss one for the module.

        • several docstrings mention int (in base 10) - I hold ints to be without base, represented base 2 if any (→ Bitwise Operations) (and to have a default base to use in conversions from/to str)


        • letter_from_num(num)/digit_from_letter(letter):

          in my book, a digit is (an encoding of) a glyph in a string representation of a number:

          I'd choose digit_for_num(num) and num_for_digit(digit)

          (and hide all "decimal digit special casing" here)

          - These functions are not as defensive as decode()/encode()

          - the literal 97 seems uncalled for

        • decode(digits, base):

          - the comment containing helper function that handles hexadecimal seems incorrect

          (& your IDE or you seem to have missed a variable renamed in the next one)

          - after remainder = number % base, I'd be annoyed if
          remainder >= 10 and base <= 10

          - the else:-branch in "the non-final-digit handling" seems pointless

          - it is cleaner and conventional to just start digit handling with result *= base unconditionally, obsoleting the enumerate


        • encode(number, base)

          - helps me to make sure that we will work just before digit handling is cryptic, at best

          - assigning new_base_number = new_base_number[::-1]to just return it looks clumsy


        • convert(digits, base1, base2)

          - none of the internal comments looks helpful

          - why special-case base1 == 10?

          - decimal_digit looks a misnomer - value? number, integer?


        I miss the (trivial) Decode digits from hexadecimal (base 16). part of the task quoted in the code with embedded documentation presented.






        share|improve this answer















        • Much as I like the presence of docstrings for the functions, I miss one for the module.

        • several docstrings mention int (in base 10) - I hold ints to be without base, represented base 2 if any (→ Bitwise Operations) (and to have a default base to use in conversions from/to str)


        • letter_from_num(num)/digit_from_letter(letter):

          in my book, a digit is (an encoding of) a glyph in a string representation of a number:

          I'd choose digit_for_num(num) and num_for_digit(digit)

          (and hide all "decimal digit special casing" here)

          - These functions are not as defensive as decode()/encode()

          - the literal 97 seems uncalled for

        • decode(digits, base):

          - the comment containing helper function that handles hexadecimal seems incorrect

          (& your IDE or you seem to have missed a variable renamed in the next one)

          - after remainder = number % base, I'd be annoyed if
          remainder >= 10 and base <= 10

          - the else:-branch in "the non-final-digit handling" seems pointless

          - it is cleaner and conventional to just start digit handling with result *= base unconditionally, obsoleting the enumerate


        • encode(number, base)

          - helps me to make sure that we will work just before digit handling is cryptic, at best

          - assigning new_base_number = new_base_number[::-1]to just return it looks clumsy


        • convert(digits, base1, base2)

          - none of the internal comments looks helpful

          - why special-case base1 == 10?

          - decimal_digit looks a misnomer - value? number, integer?


        I miss the (trivial) Decode digits from hexadecimal (base 16). part of the task quoted in the code with embedded documentation presented.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 4 at 4:03

























        answered Jan 3 at 23:13









        greybeard

        1,3491621




        1,3491621






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f179634%2fbase-conversion-decode-and-encode-base-to-integer%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Сан-Квентин

            Алькесар

            Josef Freinademetz