IQ test function in Python not working as intended - python

I'm having trouble with this code below.
My task is to create a function, that among the given numbers finds one that is different in evenness, and returns a position of that number. The numbers are given as a string. So far I have managed to convert the string into an integer list, then using for loop to iterate through each number.
The problem I'm encountering is that I've managed to return only the position of an odd number among the even numbers, and I can't continue on with the code for vice versa action, because it only returns the position of the odd number.
Here is the code:
def iq_test(numbers):
# Splitting the "numbers" string
num_split = numbers.split()
# converting the splitted strings into int
num_map = map(int, num_split)
# converting the object into list
list_num = list(num_map)
for n in list_num:
if not n%2 == 0:
return list_num.index(n) + 1

Your problem is, that you are assuming, that you are searching for the first even number. What you have to do, is to first decide, what you are searching for. You could for example simply first count the number of even numbers. If it is one, then you are looking for an even number, otherwise, you are looking for an odd. As you don't care for the actual numbers, I would map all of them to their value mod 2 as so:
num_map = list(map(lambda x: int(x) % 2, num_split))
Then, the rest is simple. For example like this:
def iq_test(numbers):
# Splitting the "numbers" string
num_split = numbers.split()
# converting the splitted strings into even (0) or odd (1)
num_map = list(map(lambda x: int(x) % 2, num_split))
# return the correct position based on if even or odd is in search
evens = num_map.count(0)
if evens == 1:
return num_map.index(0) + 1
else:
return num_map.index(1) + 1

I came up with a similar and a little bit shorter solution
def iq_test(numbers):
# first check what im looking for "even" or "odd", map a lambda function that basically does it for me, using the numbers argument as a list type and afterwards cast it into a list so i can iterate later on
num_map = list(map(lambda x: 'e' if int(x) % 2 == 0 else 'o', numbers.split()))
# search for even numbers numbers
if num_map.count('e') == 1:
return num_map.index('e') + 1
# search for odd numbers numbers
return num_map.index('o') + 1

def iq_test(numbers):
# Splitting the "numbers" string
num_split = numbers.split()
# converting the splitted strings into int
num_map = map(int, num_split)
# converting the object into list
list_num = list(num_map)
for n in list_num:
if not n%2 == 0:
return list_num.index(n) + 1

Related

Convert x digit number into two digit number

I am currently having x number in a list, and I am trying to convert inconsistent data that may be in 1 digit, 5 digit or 2 digit.
How can I convert all into 2 digit number?
Example:
def List_Convert_2_Digit(z):
for i in range(len(z)):
while(z[i]<100 or z[i]>10):
if(z[i]<100):
z[i]=z[i]/10
else:
z[i]=z[i]*10
return z
list_a = [5.2,1600,520,3600,13,55,4000]
result_list= List_Convert_2_Digit(list_a)
Result should yields: [52,16,52,36,13,55,40]
But the above code does not work and it's running forever.
I've tried mod, but it is not what I am looking for.
It looks like you just want to take the first two characters from each, and if there is a separator (dot in your case) ignore it.
In that case you can do this:
two_digit_list = [int(str(x).replace('.', '')[:2]) for x in List]
If other non numeric characters than a dot are going to appear your would have to deal with those as well of course :)
What this does is just converts the numbers to a string, removes dots and then grabs the first two characters and converts it back to an int.
EDIT: Since I saw you replied to someone above that single digit numbers should have 0 added to the end you can do this instead to cover that case:
two_digit_list = [int(str(x).replace('.', '')[:2]) if len(str(x).replace('.', '')) > 1 else int(f"{x}0") for x in List]
At that point it's a bit too long to be a pretty list comprehension so you could always just break it up into a for loop if it's unclear, might be a good exercise if nothing else :)
This is a simple solve to this.
yield_list = []
number_list = [5.2,1600,520,3600,13,55,4000]
for number in number_list:
string = str(number)
string =string.replace('.', '')
yield_list.append(string[:2])
yield_list
There is an error in your logic; your < and > are flipped. This code works:
def List_Convert_2_Digit(z):
for i in range(len(z)):
while(z[i]>100 or z[i]<10):
if(z[i]>100):
z[i]=z[i]/10
else:
z[i]=z[i]*10
return z
Solution that increases/decreases the numbers magnitude until we can get the left two digits:
def two_digit_list(lst):
rv = []
for item in lst:
if item < 10:
item *= 10
while item > 99:
item //= 10
rv.append(int(item))
return rv

Python- Expanded form of a number raised to the power of ten

I'm pretty new to coding and I am trying to write a python script where a user enters an integer and it displays that integer in expanded form raised to the power of 10's.
Example: A user enters 643541 and the script outputs 643541 = (6x10^5 )+(4x10^4)+(3x10^3)+(5x10^2)+(4x10^1)+(1x10^0)
This is my code
A = [7000, 400, 70,1]
cond = True
y = 0
i = 0
sizeArray = len(A)
for i in range(0, sizeArray-1):
while cond == True:
if A[i]%10 == 0:
A[i] = A[i]/10
y += 1
else:
cond = False
print(y)
I tried working with a sample array to test the number of zero's but I don't know how i will be able to output the result as above.
How can I accomplish this?
You can transform your input integer 643541 to an array of digits [6,4,3,5,4,1]. Then maintain a variable for the exponent. It will be decremented for each digit in the array
def function(num):
digits = str(num) # convert number to string
output = []
for i, digit in enumerate(digits):
output.append("(" + digit + "x10^" + str(len(digits)-i-1) + ")")
return " + ".join(output)
Here len(digits)-i-1 plays the role of the variable that maintains exponent value
Every question like this deserves a solution using a list comprehension:
>>> n = 123456
>>> '+'.join([ '({1}x10^{0})'.format(*t) for t in enumerate(str(n)[::-1]) ][::-1])
'(1x10^5)+(2x10^4)+(3x10^3)+(4x10^2)+(5x10^1)+(6x10^0)'
Explanation:
str(n)[::-1] converts the number to a string and then reverses the string, giving the digits of the number, as strings, from least-significant to most-significant.
enumerate returns pairs t = (i, d) where i is the index and d is the digit. Since the sequence is from least-significant to most-significant, the index equals the corresponding exponent of 10.
*t unpacks (i, d) for {0} and {1} in the format string, so the result is like ({d}x10^{i}).
The [::-1] applied to the list comprehension reverses the results back into the right order.
'+'.join joins those results together into a single string, with the + symbol between the parts.

Is there any other way to replace consecutive repeating digits with 0 in an integer without converting it to string? [duplicate]

This question already has answers here:
Handling very large numbers in Python
(6 answers)
Closed 3 years ago.
We are given an integer which can be large as 10 to the power of 18 and we have to replace all consecutive repeating digits with zero.
I have tried by converting the integer to string but it takes a lot of time in doing type conversion from integer to string. Is there any way to do the function without converting it to string. My code by converting the integer to string -:
def replace(l):
l1 = str(l)
s = l1[0]
temp = s[0]
for i in range(1, len(l1)):
if l1[i] == temp:
s += '0'
else:
s += l1[i]
temp = l1[i]
l = int(s)
return l
Example-: Let integer be 1222433444
Expected output -: 1200430400
What takes time is concattenating string to string to string to string. Every time you concat something to a string the old one is discarded and a new one is created - this takes computation time. Strings in python are immuteable.
Use a list instead and create the final string only once:
def replace(l):
l1 = list(str(l)) # use a list
v = l1[0] # first char is our start v
for idx,value in enumerate(l1[1:],1): # we do all the others starting at index 1
if l1[idx] == v:
l1[idx] = '0' # replace list element
else:
v = l1[idx] # or replace v if different
l = int(''.join(l1)) # only create one string & convert to int
return l
print(replace(1222433444)) # input
print(1200430400) # your expected
Output:
1200430400
1200430400
While using a string properly is probably the best solution, you can iterate over the digits directly, without performing a conversion to string at all. There are a couple of ways of doing this. The simplest is probably to start with the largest digit:
from math import floor, log10
def replace(n):
digit_count = floor(log10(n))
prev = 0
result = 0
power = 10**digit_count
for i in range(digit_count, -1, -1):
digit = (n // power) % 10
result *= 10
if digit != prev:
result += digit
prev = digit
power //= 10

Find complement of number in Python

I am trying to find the complement of a number in Python. I know there are other solutions but I am trying to make my own.
My first try:
def findComplement(self, num):
"""
:type num: int
:rtype: int
"""
numb = str(num)
i = 0
while(i<=len(numb)):
if numb[i] == "0":
numb[i] = "1"
else:
numb[i] = "0"
i=i+1
return int(numb)
But strings are immutable so it gave an error,
My second try:
def findComplement(self, num):
"""
:type num: int
:rtype: int
"""
numb = str(num)
numb2 = []
k =0
for j in numb:
numb2[k] = j #error on this line
k=k+1
i = 0
while(i<=len(numb2)):
if numb2[i] == "0":
numb2[i] = "1"
else:
numb2[i] = "0"
i=i+1
return int(numb2)
Error in program 2:
Line 11: IndexError: list assignment index out of range
Since other answers cover your main problem, you can also just use a dictionary for mapping 1 to 0, and vice versa:
>>> d = {'0': '1', '1': '0'}
>>> s = '0101'
>>> ''.join(d[x] for x in s)
'1010'
So I wanted find the binary complement of a number myself
but was unstatisfied with how the mask is generated and other things, cause they involved using the string representation of the binray number.
So I dug a little deeper and came across this reddit post
where they generated the mask via bitwise shifts.
And I also found out that you can get the bit count of an integer
with int.bit_lenght(<your_number>),
instead of using len(bin(<your-number>)[2:]).
Only problem is: that it returns 0 for the number 0.
So you have to account for that.
Tho I have no clue what method is more performant
and whether it is worth it compared to string manipulation.
But in the end that was my final solution
that I found was pretty neat cause it doesn't involve strings.
def bin_complement(num, on_two=False, bit_count=0):
"""
num(int) dezimal number
on_two(bool) complement on 2 else on 1
bit_count = number of bits for the mask, defaults to bits in num
returns(int) complementary number
"""
bit_count = max(bit_count, num.bit_length(), 1)
mask = 2 ** bit_count - 1
complement = num ^ mask
if on_two:
complement += 1
return complement
Edit: 2**bit_count - 1 is a faster way for doing
for _ in range(bit_count):
mask <<= 1
mask |= 1
Edit2: If you want to take the complement of fixed length bit number.
E.G: C_1(0001) -> 0001 xor 1111 = 1110
and not just 0000.
You can now set a bit_count value for the mask
so the complement works correct.
You have a few problems.
First you are not converting your input to a binary string properly. This can be done by numb = bin(num)[2:] instead of num = str(num).
Second, you are trying to index into your empty numb2 list. Actually there is no need to create a separate numb2 list, you can just operate directly on your numb string, as in your first attempt. For example:
for i in range(len(numb)):
if numb[i] == "0":
numb[i] = "1"
else:
numb[i] = "0"
Finally, to convert your binary string back to an int you should do int(numb, 2) not int(numb).
numb2 is an empty list. It does not have any elements to be addressed (and updated). What you need is a bytearray, rather than a list (or a string):
def findComplement(self, num):
"""
:type num: int
:rtype: int
"""
numb = bytearray(str(num), 'utf-8')
i = 0
while(i<len(numb)):
if numb[i] == ord("0"):
numb[i] = ord("1")
else:
numb[i] = ord("0")
i=i+1
return int(numb)
As can be seen, this requires some minor other changes, as the stored data in a bytearray is a byte (0-255) rather than a char. The solution is to use the ord function, to get the byte number from "0" and "1". In addition there is a small issue (off by one) in your whileexpression. Since the indexing and your count start at zero i should be strictly smaller than the length of the string.
I would also like to add that there are simper ways to achive the complement of 0 and/or 1, though.
Let's say we have to find complement of 101 if we xor the input with the mask 111 then we will get 010 which is complement.
def findComplement(self, num: int) -> int:
mask_len=len(bin(num))-2
mask=int("1"*mask_len,2)
return mask^num
For those looking for a one-liner, here is one:
int(bin(value)[2:].zfill(numbits).translate(str.maketrans('01', '10')), 2)
The above computes a numbits-bit ones' complement for value.
Since str.maketrans('01', '10') is a constant (dictionary), one can compute it ahead of time:
dMatrix = str.maketrans('01', '10') # which is {48: 49, 49: 48}
int(bin(value)[2:].zfill(numbits).translate(dMatrix), 2)
Converting this one-liner to a function is straightforward:
def onescomplement(value, numbits):
return int(bin(value)[2:].zfill(numbits).translate(str.maketrans('01', '10')), 2)
HTH
Don't you just mean the ~ operator, e.g:
def findComplement(self, num):
return ~num

Find the biggest digit in number

So, I have to input a number and find the biggest digit in that number, so if the number is 2314 I want to get 4, my code so far:
a = input()
for x in a:
i = int(x)
If your input is a number, you will want to first convert your input to a string and then convert each character back into an integer and take the max. You can easily use a generator expression to convert all characters to integers using int and then apply max.
maximum = max(int(x) for x in str(a))
For the sake of an example:
maximum = max(int(x) for x in str(415023)) # 5
If on the other hand, your input is a string, then just skip the conversion to a string.
maximum = max(int(x) for x in a)
A More Robust Solution
All of these examples assume that you don't have any decimal points or negative signs in your number. If you do then you can explicitly ignore those.
maximum = max(int(x) for x in str(a) if x not in '.-')
As an example:
a = -15.93
maximum = max(int(x) for x in str(a) if x not in '.-') # 9
Convert to a string, then get the max
a = 2314
max(str(a))
# output 4
Since this is a homework, here is another simple answer. Since you are a beginner, didn't use max().
a = input("number: ")
print (sorted(list(a))[-1])
Converted the input to a list first, then sorted it. Last number is the max. That [-1] is the last index of the list.
A reduce in python2 might also work.
maximum = reduce(lambda acc, n: acc if acc > int(n) else int(n), "123131891", 0)

Categories