python recursively convert decimal to hex - python

How would you recursively or iteratively change a decimal to hexadecimal?
I wrote a sample program that does not really work:
def ChangeHex(n):
if (n < 0):
print(0)
elif (n<=1):
print(n)
else:
ChangeHex(n / 16)
if (n == 15):
print("F")
if (n == 14):
print("E")
if (n == 13):
print("D")
if (n == 12):
print("C")
if (n == 11):
print("B")
if (n == 10):
print("A")
n % 16
How would I make it work properly? I know there is a built in function but I want to do it this way.

# Converts a decimal number to hexadecimal.
# Executes a zero-fill for up to six digits.
# This is used for correct conversion back
# to the instruction format. See zero_fill().
# #param dec Decimal representation of instruction
# #return Zero-filled hexadecimal instruction.
def convert(dec):
# BEGIN convert()
hex = "%X" % dec
return zero_fill(hex, 6)
# END convert()
# Prepends zeros until the specified
# length is reached. Works recursively.
# #param n Number to fill
# #param length Length to reach
# #return Zero-filled number
def zero_fill(n, length):
# BEGIN zero_fill()
# Check if length requirement is met
if len(n) != length:
# Requirement not met, run function again with
# n having one prepended zero.
return zero_fill('0'+n, length)
else:
# Requirement met, return n.
return n
# END zero_fill()

The main reason your program is not "working" is because you're misusing functions and immutable objects. Numbers objects are immutable, which means that you can't change the value of a number object in Python, you need to return a new number. And when you're doing ChangeHex(n), you passing the value of n (i.e. the number object) to the function - it doesn't know that there is a variable that was associated with this number. And thus, when you change a local variable like n, the the variable in the caller doesn't change.
You'd like the function to return a new value, not to try to change the one that's passed (which is not really possible). Look up the return statement, and use the value of ChangeHex(n). Hints:
result += ChangeHex(n)
return result
Probably you want to return what you're printing, but I can't really tell.
The same applies to operations. Since the numbers are immutable, an operations on numbers can't change the number, and you need to assign the number to a variable. n % 16 does nothing, you need assignment, like n = n % 16 or n %= 16.

Related

Recursive decimal to binary converter in python

def toBinary(decimal, binaryList):
if decimal <= 1:
return binaryList
else:
decimal = decimal //2
return toBinary(decimal, binaryList)
binaryList.append(decimal %2)
The functions returns empty brackets instead of printing the binary number as a list.
Your code is on the right track but has issues. First is what #KlausD comments, no line directly after a return gets executed. So the order of statements is at issue. Next, the variable binaryList doesn't get initialized in your provided code fragment. It could get initialized by the caller:
array = toBinary(13, []):
which works, but the caller might find it strange. We could intialize it using a default:
def toBinary(13, binaryList=[]):
But as a container type, that would constitute a dangerous default which we want to steer clear of. We could safely initialize it to None as a default and reinitialize it later in the code:
def toBinary(decimal, binaryList=None):
# ...
if binaryList is None:
binaryList = []
Which is safe and hides this argument from the caller. Next, by dividing, we're analyzing our decimal digits from right to left, so we need to build up our binary number in the same direction, thus append():
binaryList.append(decimal % 2)
is a problem as it builds up the binary result from left to right. We could end with a revese() but it's probably better to use binaryList.insert(0, ...) to build in the proper direction. Finally, this is a special case:
array = toBinary(0)
as we're going to use a zero argument to trigger end of recursion but how it affects our result (i.e. not at all) is different than if we're passed zero from the get-go (i.e. return a [0]). Here's my rework of your code that addresses all of these issues:
def toBinary(decimal, binaryList=None):
if decimal == 0:
return binaryList or [0]
if binaryList is None:
binaryList = []
binaryList.insert(0, decimal % 2)
return toBinary(decimal // 2, binaryList)
print(toBinary(13))
OUTPUT
> python3 test.py
[1, 1, 0, 1]
>
It is better not to return binary list.
def toBinary(decimal, binaryList):
if decimal <= 0:
return
else:
toBinary(decimal//2, binaryList)
binaryList.append(decimal %2)
This code also converts to Binary. It can also convert into other bases. Just change the parameter base, to the base you want.
import string
def to_base(value, base=2): # converts decimal to base n
string_slice = string.printable[0:base]
data_dict = {}
for each_character, each_number in zip(string_slice, range(base)):
data_dict.update({each_character: each_number})
data = []
temporary_var = value
data.append(temporary_var)
while True:
temporary_var = temporary_var // base
data.append(temporary_var)
if temporary_var < base:
break
else:
continue
result = ''
for each_data in data:
result += list(data_dict.keys())[each_data % base]
result = result[::-1]
return result by
My code may not be perfect. Feel free to suggest improvements.
print(to_base(5, base=2)) # Outputs : 101. Because 101 is 5 in binary
print(to_base(17, base=16)) # Outputs : 11. Because 11 is 17 in hexadecimal

Pass several arguments to function from map()

For example, if I want to detect all odd numbers in an array and set them to zero, I can use:
def setToZeroIfOdd(n):
if n % 2 == 0:
pass
else:
return 0
numbers = range(1,1000)
numbers = map(setToZeroIfOdd, numbers)
which works like a charm.
But when I try something like
def setToZeroIfDivisibleBy(n, divisor):
if n % divisor == 0:
return 0
else:
pass
numbers = map(setToZeroIfDivisibleBy(divisor=3), numbers)
it expects two arguments. Likewise,
numbers = map(setToZeroIfDivisibleBy, numbers, divisor=3)
does not work. How can I pass that divisor argument from within map()?
You can use functools.partial to make partial functions
from functools import partial
def setToZeroIfDivisibleBy(n, divisor):
if n % divisor == 0:
return 0
else:
pass
numbers = range(1,1000)
numbers = map(partial(setToZeroIfDivisibleBy, divisor=3), numbers)
Try using lambda function
numbers = map(lambda n: setToZeroIfDivisibleBy(n, divisor=3), numbers)
And rather than pass did you mean return n?
You make a function which returns a function:
def setToZeroIfDivisibleBy(divisor):
def callback(n):
if n % divisor == 0:
return 0
else:
pass
return callback
numbers = map(setToZeroIfDivisibleBy(3), numbers)
BTW, you can entirely omit empty branches like else: pass; it doesn't do anything. Since it results in a None, I don't think that's what you want either. You probably want return n there instead.
Another approach, instead of using partial, is to supply an infinite (or at least, long enough) sequence of 2nd arguments for the two-argument function:
from itertools import repeat
numbers = map(setToZeroIfDivisibleBy, numbers, repeat(3))
In Python 2, map will append None as necessary to the shorter of the two sequences to make them the same length. Assuming that will cause problems (either because your function cannot handle None as an input value or you end up with an infinite loop), you can either use itertools.imap, which stops after exhausting the shorter sequence:
from itertools import imap, repeat
numbers = list(imap(setToZeroIfDivisibleBy, numbers, repeat(3)))
or pass the length of numbers as a second argument to repeat so that the two sequences are the same length.
from itertools import repeat
numbers = map(setToZeroIfDivisibleBy, numbers, repeat(3, len(numbers)))

Delete elements of an integer recursively

My parameter, n is a phone number as an integer.
Using recursion I want to return the first three numbers in the integer.
I've turned the integer into a list of individual number characters and I'm attempting to delete the last number over and over again until I'm left with the last three, but I'm stuck on how to repeat it.
def areaCodes(n):
n = str(n)
n = list(n)
del n[-1]
#n = reduce(opperator.add, n)
n = ''.join(n)
n = int(n)
return n
I know I'm supposed to repeat the name in the return somehow, but because n isn't an integer that I can use to repeat. What do I do?
How about something like this?
def areaCodes(n):
# if n is less than 1000, what does it mean about the number of digits?
if n < 1000:
return # fill...
# otherwise, if n is greater than 1000, how can we alter n to remove the last
# digit? (hint: there's an operation similar to division called f...r division)
return areaCodes( # operate on n somehow...)
I assume that this is an exercise where recursion is necessary. If so, try this (there are better ways to accomplish your end goal, but I tried to modify your existing code as little as possible):
def areaCodes(n):
n_lst = list(str(n))
del n_lst[-1]
n_str = ''.join(n_lst)
n_int = int(n_str)
if len(n_lst) > 3:
return areaCodes(n_int)
return n_int
This will call the function again if the length of the number is greater than three, and return the number otherwise. Basically, the only part you were missing in your original function was the following, which is the recursive part:
if len(n_lst) > 3:
return areaCodes(n_int)
Remember that for a function to be recursive, it will have two main attributes:
It will at some point call itself. (this is what makes it 'repeat')
It will have some stopping condition (or base case).
You mentioned #1 when you wrote that you're supposed to use "the name in the return," so that's great! You just need to write that in your code:
return areaCodes(n), Where n is the updated phone number with a digit removed.
As you can see, each recursive call should do some work towards the solution, and should pass its mini-solution to the next recursive call.
Along with #2 above, you need to specify a base case, where the recursion will cease. So, since you're taking away a digit each time you call your function, you should include some kind of check to see if the current input is the length you want yet.
If it is the right length, you're done, and you should return the current number (not another recursive call).
Otherwise, you aren't done with the recursion yet.
import sys
def areaCodes(n):
#Create a list
myList = list(str(n))
#Delete last element
del myList[-1]
#Combine your elements into string list
myListStr = ''.join(myList)
#Type cast to int
myListInt = int(myListSte)
#Check whether your list satisfies your condition
if len(myList) > 3:
#Recusivley call the function again
return areaCodes(myListInt)
#Return your list when recursion completes
return myListInt
n = 12345
print areaCodes(n)

SpecialStrings prob from topcoder srm 634 div 2

I python seems work with not big length of input string, but it failed with pretty long string. Here is the problem statement:
A string S is called special if it satisfies the following two properties:
Each character in S is either '0' or '1'.
Whenever S = UV where both U and V are nonempty strings, U is strictly smaller than V in lexicographic order.
For example, the string S = "00101" is special because we have "0" < "0101", "00" < "101", "001" < "01", and "0010" < "1".
You are given a string current that is guaranteed to be special. Let N be the length of current. Consider the lexicographically sorted list of all special strings of length N. Compute and return the string that comes immediately after current in this list. If current happens to be the last string in the list, return an empty string instead.
Here is my python code:
class SpecialStrings(object):
def findNext(self, current):
if current == '0':
return '1'
N = len(current)
iter_times = 2 ** N - int(current, 2) - 1
temp_current = current
for i in range(iter_times):
temp_s = self.get_next_string(temp_current)
if self.is_special(temp_s):
return temp_s
if temp_s[0] == '1':
return ''
temp_current = temp_s
return ''
def get_next_string(self, s):
next_string = bin(int(s, 2) + 1)
next_string = next_string[2:]
if len(next_string) < len(s):
temp_zero = '0' * (len(s) - len(next_string))
next_string = temp_zero + next_string
return next_string
def is_special(self, s):
for i in range(1, len(s)):
left = s[:i]
right = s[i:]
if left >= right:
return False
return True
I received abnormal termination with inputs "0111111111111111111111111111" and "001111111111111111111111111111111111111111". When I tried to test it locally with either of them, my computer memory was exhausted......
What is the problem in here? Is it because my algorithm is not efficient? How to solve it?
Thank you very much!!!!!
You're probably using Python2. In Py2, range() (your 8th line) returns a list. E.g. range(3) returns [0, 1, 2]. So range(iter_times) creates a large list that use up memory. The simple workaround: use xrange instead. Refer
But with xrange, you may soon get another error:
OverflowError: Python int too large to convert to C long
Because the argument passed to xrange should not exceed max signed long. E.g. in my machine xrange(0x7fffffff) is OK, while xrange(0x80000000) can trigger the error. Refer
Workaround: in your 8th line, use while True: instead. Because if the codes work as expected, the loop should anyway return result or empty string before hitting the end of for loop. So no need to use for loop.
The next trouble, when you use 'while True', input '0111111111111111111111111111' should work fine, but '001111111111111111111111111111111111111111' will keep calculating. That's the algorithm matter. You used brute force, long computation time is expected for large input. You may need to find pattern of special strings to improve the algorithm.

python: float number like integer

I try convert a float to int when the number don't have decimals.
I make this
from math import modf
def float_like_int(n):
if abs(modf(n)[0]) < 1e-6:
return int(n)
return n
print float_like_int(10.1)
print float_like_int(10.00001)
print float_like_int(10.000001)
print float_like_int(10.0)
exist a standard function or a more general way ? (without 1e-6)
I think the following is a bit more readable than your version:
def float_like_int(n):
if round(n, 6) == round(n):
return int(round(n))
return n
Note that this does have a slightly different meaning than your function, since it would also round something like 9.9999999 to 10.
Those approach that you are using trys to make a number integer if a fractional part is less than 1e-6 (0.000001 ). This means if you have a number 4.000001, (which is float actually) your function will throw away fractional part. You can change 1e-6 to another value and those numbers, which meet your criteria will be converted to int.
Here is my code without any extra modules imported. This code will not throw away any fractional part.
def Func(a):
if (a * 10) % 10 == 0:
return int(a)
else:
return a
f = 4.03
print Func(23.45)
print Func(f)
print Func(2.3)
Maybe something like this is more natural?
def float_like_int(n):
if int(n) == float(n):
return int(n)
else:
return float(n)
You can use this function :
def isWhole(x):
if(x%1 == 0):
return True
else:
return False

Categories

Resources