Say I have a string = '123' but I want to convert it into 123 without using the int() function. How would I go upon doing this using recursion?
The idea I have so far is to put the string into an array as such ['1','2','3'] and then convert them based on ASCII representations.
for i in string:
myArr.append (ord(i) - ord('0'))
So now I'd have a list looking like [1,2,3]. What should I do next to recursively get 123?
I have an idea of using the place values and add them together (ie. 100 + 20 + 3 = 123), but I don't know how to do this. Any ideas would be helpful !
I guess this is an academic exercise, because it's a rather contrived thing to ask. Here's how, assuming that s represents an integer number greater than or equal to zero:
def strToInt(s, acc):
if not s:
return acc
return strToInt(s[1:], 10 * acc + ord(s[0]) - 48)
Or even shorter:
def strToInt(s, acc):
return strToInt(s[1:], 10 * acc + ord(s[0]) - 48) if s else acc
The trick is to accumulate the result of the conversion in an extra parameter, this has the nice side effect of yielding a tail-recursive solution (not that it matters much in Python, but still…). Also notice how we use ord() to get the numeric value of a character representing a digit, and by simply subtracting 48 we get to the actual digit's value. Test it, it works as expected:
strToInt('123', 0) # the accumulator always starts in zero
=> 123
This wouldn't be recursive (I don't think you understand what that means), but:
for char in string:
array.append(ord(char) - ord('0'))
array.reverse()
num = 0
for index, val in enumerate(array):
num += val * (10 ** index)
EDIT: Ah, I see this is for an exercise. Yeah, it's a ridiculous problem to solve via recursion, but one of the other answers does it.
Another possibility:
def strToInt(s):
if s:
return (ord(s[-1]) - ord('0')) + 10 * strToInt(s[:-1])
else:
return 0
The first thing that comes to mind is the famous C method atoi().
Python had a similar method, also called atoi(), but it was deprecated, with the instruction to use int().
Therefore, despite your comment, I would recommend using int(). Python documentation encourages you to use it, so do so without fear.
int() documentation for Python 2.7
int() documentation for Python 3.3
Related
Based on this answer (among others) it seems like f-strings is [one of] the preferred ways to convert to hexadecimal representation.
While one can specify an explicit target length, up to which to pad with leading zeroes, given a goal of an output with an even number of digits, and inputs with an arbitrary # of bits, I can imagine:
pre-processing to determine the number of bits of the input, to feed an input-specific value in to the fstring, or
post-processing a-la out = "0"+f"{val:x}" if len(f"{val:x}") % 2 else f"{val:02x}" (or even using .zfill())
The latter seems like it might be more efficient than the former - is there a built-in way to do this with fstrings, or a better alternative?
Examples of input + expected output:
[0x]1 -> [0x]01
[0x]22 -> [0x]22
[0x]333 -> [0x]0333
[0x]4444 -> [0x]4444
and so on.
Here's a postprocessing alternative that uses assignment expressions (Python 3.8+):
print((len(hx:=f"{val:x}") % 2) * '0' + hx)
If you still want a one-liner without assignment expressions you have to evaluate your f-string twice:
print((len(f"{val:x}") % 2) * '0' + f"{val:x}")
As a two-liner
hx = f"{val:x}"
print((len(hx) % 2) * '0' + hx)
And one more version:
print(f"{'0'[:len(hex(val))%2]}{val:x}")
I don't think there's anything built in to f-string formatting that will do this. You probably have to figure out what the "natural" width would be then round that up to the next even number.
Something like this:
def hf(n):
width = len(hex(n)) - 2 # account for leading 0x
width += width % 2 # round up
return f'{n:0{width}x}'
print(hf(1))
print(hf(15))
print(hf(16))
print(hf(255))
print(hf(256))
Output:
01
0f
10
ff
0100
You can use a variable in the pad-length part of the f-string. For example:
n = 4
val = 257
print(f"{val:0{n}x}") # 0101
Now, to figure out how many hex characters are in an integer, you just need to find how many bits are in the integer:
hex_count, rem = divmod(max(1, val.bit_length()), 4)
hex_count += (rem > 0)
(max(1, val.bit_length()) handles the case where val == 0, which has a bit length of 0)
So let's get the next even number after hex_count:
pad_length = hex_count + (hex_count % 2)
print(f"{val:0{pad_length}x}") # 0101
I'm not sure if this is any better than simply converting it to a hex string and then figuring out how much padding is needed, but I can't think of a readable way to do this all in an f-string. An unreadable way would be by combining all of the above into a single line, but IMO readable code is better than unreadable one-liners. I don't think there's a way to specify what you want as a simple f-string.
Note that negative numbers are formatted to an even number of digits, plus the - sign.
So I answered one of the questions on Coding Bat that asked to return half of a string n number of times by defining a variable that takes half the length of the original string and using that variable in slicing the string.
Coding bat accepted the result, but when I try to recreate the problem on Jupyter Notebook it only accepts "integers or None or index method".
What am I doing wrong?
Im a beginner in Python and just want to make sure that I'm learning the correct format.
def first_half(str):
newword = len(str) / 2
return '{}'.format(str[:newword])
for first_half('Milkshakes') I expect to get 'Milk'.
However, the error im getting is:
TypeError: slice indices must be integers or None or have an __index__ method
This is because len(str) / 2 gives you a float value 5.0 and you cannot use a float as a argument to string slice, convert the argument to an int by doing int(len(str) / 2), which gives you 5, and it should work. Note that the above only holds true for Python 3 the original code you have still works for Python 2 where you don't need the float to int conversion
Also str is a python builtin, so it's bad practice to use it as a variable.
In addition, you want the first half of Milkshakes is Milks, and not Milk
def first_half(s):
#Parse float to int
newword = int(len(s) / 2)
return '{}'.format(s[:newword])
print(first_half('Milkshakes'))
#Milks
To make a generic solution, as some of the commentors have suggested, you can use integer division //, which works for both Python 2 and Python 3
def first_half(s):
#Integer division
newword = len(s) // 2
return '{}'.format(s[:newword])
print(first_half('Milkshakes'))
I am trying to write a recursive method as follows, but I am getting SyntaxError: invalid syntax, I wonder what I am doing wrong
Given a non-negative integer num, repeatedly add all its digits until
the result has only one digit.
For example:
Given num = 38, the process is like: 3 + 8 = 11, 1 + 1 = 2. Since 2
has only one digit, return it.
class Solution(object):
def addDigits(self, num):
"""
:type num: int
:rtype: int
"""
return self.addDigits(x=sum(i for i in str(num)) if x%9<10:
Note:
I am learning recursion in python, therefore rather than knowing how to solve problem, I would love to learn what I am doing wrong in my implementation.
Updated to match the new question description:
def add_digits(x):
return (x - 1) % 9 + 1 if x else 0
If you apply the brute force version of this solution (the one you were originally attempting) then you will see the output is actually the sequence listed here: https://oeis.org/A010888.
Once we know that this is a repeating sequence we can look for patterns in the sequence, and in this case we realize that the function in this answer provides a guaranteed solution in O(1) time and space.
You can actually see the relationship to n % 9 by seeing this sequence here: https://oeis.org/A010878
It prints diga and digb but doesnt work with c! Any help? It's supposed to be a Denary to Binary converter but only 1-64, once i've cracked the code will increase this! Thanks so much
denaryno=int(input("Write a number from 1-64 "))
if 64%denaryno > 0:
diga=0
remaindera=(64%denaryno)
if 32/denaryno<1:
digb=1
remainderb=(denaryno%32)
else:
digb =0
if 16/remainderb<1:
digc=1
remainderc=(denaryno%16)
else:
digc=0
if 8/remainderc<1:
digd=1
remainderd=(denaryno%8)
else:
digd=0
if 4/remainderd<1:
dige=1
remaindere=(denary%4)
else:
dige=0
if 2/remaindere<1:
digf=1
remainderf=(denary%2)
else:
digf=0
if 1/remainderf<1:
digg=1
remainderg=(denary%1)
else:
digg=0
print (str(diga)+str(digb))
You only set digc in one of the top if/else statement. If 32/denaryno<1 is True, you don't set digc at all.
Set digc at the top of the function (to 0 or whatever else you want it to be). This applies to all the digit variables, digd, dige, etc.
What you really should do, instead, is use a list of digits, and append either a 0 or a 1 to that list every time you divide the number by a factor.
You may want to take a look at the divmod() function; it returns both the quotient and the remainder. You could also do with some looping here to slash the number of if statements needed here:
number = int(input("Write a number from 1-64 "))
digits = []
factor = 64
while number:
quotient, number = divmod(number, factor)
digits.append(quotient)
factor //= 2
print(''.join(map(str, digits)))
Wow that was a lot of work, you don't have to do all that.
def bin_convert(x, count=8):
return "".join(map(lambda y:str((x>>y)&1), range(count-1, -1, -1)))
here are the functions comprising this one from easy->important
str() returns a string
range() is a way to get a list from 1 number to another. Written like this range(count-1, -1, -1) counts backwards.
"".join() is a way to take an iterable and put the pieces together.
map() is a way to take a function and apply it to an iterable.
lambda is a way to write a function in 1 line. I was being lazy and could have written another def func_name(y) and it would have worked just as well.
>> is a way to shift bits. (which I believe understanding this one is the key component to understanding your problem)
I have a ridiculous code segment in one of my programs right now:
str(len(str(len(var_text)**255)))
Is there an easy way to shorten that? 'Cause, frankly, that's ridiculous.
A option to convert a number >500 digits to scientific notation would also be helpful
(that's what I'm trying to do)
Full code:
print("Useless code rating:" , str(len(var_text)**255)[1] + "e" + str(len(str(len(var_text)**255))))
TL;DR: y = 2.408 * len(var_text)
Lets assume that your passkey is a string of characters with 256 characters available (0-255). Then just as a 16bit number holds 65536 numbers (2**16) the permutations of a string of equal length would be
n_perms = 256**len(passkey)
If you want the number of (decimal) digits in n_perms, consider the logarithm:
>>> from math import log10
>>> log10(1000)
3.0
>>> log10(9999)
3.9999565683801923
>>>
So we have length = floor(log10(n_perms)) + 1. In python, int rounds down anyway, so I'd say you want
n_perms = 256**len(var_text)
length = int(log10(n_perms)) + 1
I'd argue that 'shortening' ugly code isn't always the best way - you want it to be clear what you're doing.
Edit: On further consideration I realised that choosing base-10 to find the length of your permutations is really arbitrary anyway - so why not choose base-256!
length = log256(256**len(var_text)
length = len(var_text) # the log and exp cancel!
You are effectively just finding the length of your passkey in a different base...
Edit 2: Stand back, I'm going to attempt Mathematics!
if x = len(var_text), we want y such that
y = log10(256**x)
10**y = 256**x
10**y = (10**log10(256))**x
10**y = (10**(log10(256)x))
y = log10(256) * x
So, how's this for short:
length = log10(256) * len(var_text) # or about (2.408 * x)
This looks like it's producing a string version of the number of digits in the 255th power of the length of a string. Is that right? I'd be curious what that's used for.
You could compute the number differently, but it's not shorter and I'm not sure it's prettier:
str(int(math.ceil(math.log10(len(var_text))*255)))
or:
"%d" % math.ceil(math.log10(len(v))*255)
Are you trying to determine the number of possible strings having the same length as var_text? If so, you have your base and exponent reversed. You want to use 255**len(var_text) instead of len(var_text)**255.
But, I have to ask ... how long do these passkeys get to be, and what are you using them for?
And, why not just use the length of the passkey as an indicator of its length?
Firstly, if your main problem is manipulating huge floating point expressions, use the bigfloat package:
>>> import bigfloat
>>> bigfloat.BigFloat('1e1000')
BigFloat.exact('1.0000000000000001e+1000', precision=53)
As for the details in your question: len(str(num)) is approximately equal to log(num, 10) + 1. This is not significantly shorter, but it's certainly a better way of expressing it in code (for the benefit of anyone who doesn't know that off the top of their head). You can then simplify it with log laws:
len(str(x**y))
= log(x**y, 10) + 1
= y * log(x, 10) + 1
So maybe you'll find:
"%i" % (log(len(var_text),10)*255 + 1)
... is better? It's not significantly shorter, but it's a much clearer mathematical relationship between input and output.