Python code simplification? One line, add all in list - python

I'm making my way through project Euler and I'm trying to write the most concise code I can. I know it's possible, so how could I simplify the following code. Preferably, I would want it to be one line and not use the int->string->int conversion.
Question: What is the sum of the digits of the number 21000?
My answer:
>>> i=0
>>> for item in [int(n) for n in str(2**1000)];i+=item

sum(int(n) for n in str(2**1000))

Not a one-liner, but a cleaner-looking generator solution, also avoiding the int->string->int conversion:
def asDigits(n):
while n:
n,d = divmod(n,10)
yield d
print sum(asDigits(2**1000))
Gives 1366.
Interestingly, the sum of the digits in 2**10000 is 13561, whose digits add up to the same value as 1366.
Of course, if expressed in binary, the sum of the digits in 2**1000 is 1. (I even did it in my head!)

Single int to str conversion to get length:
int(sum(map(lambda x:2**1000/x % 10, (10**x for x in xrange(len(str(2**1000)))))))

Related

Finding the product of first Million natural numbers in Python

I have just started with Python programming language. I tried to write a function which takes input either a list or multiple integers to find their product. I am trying to find the product of first million natural numbers but its displaying an MemoryError.
def product(*arg):
answer=1
if type(arg) == tuple:
arg=str(arg)
arg=arg.lstrip('[(')
arg=arg.rstrip('],)')
arg=arg.split(',')
for i in arg:
answer*=int(i)
return answer
else:
for i in arg:
answer*=int(i)
return answer
j=range(1,1000000,1)
j=list(j)
print(product(j))
Steps:
I convert the range object into list object if i am to pass a list as
argument
Now, within the function, i try to split the tuple by converting it
string.
I convert the resultant string into a list and then loop over the
elements to find the product
Q1: How to avoid the memory error as i try to find the product of first Million natural numbers?
Q2 How to improve this code?
You can use a Generator in Python.
def generate_product():
r = 1
for i in range(1,1000000):
r *= i + 1
yield r
list(generate_product())[0]
It is more memory efficient and better in terms of performance.
To calculate the product of all numbers from 1 to 1 million use a simple loop:
r = 1
for l in range(1,1000000):
r*=(i+1)
print(res)
But keep in mind that the result will be a pretty big number.
That means that your calculation might take long and the resulting number will need a lot memory.
EDIT Then i missread your question a little. This is a function that multiplies the elements in a list:
def multiply_list_elements(_list):
result = 1
for element in _list:
result*=element
return result
multiply_list_elements([1,2,3,4])
>>> 24
The memory error probably came from the huge number as #ZabirAlNazi calculated so nicely.
All of the solution is fine, but one point to make - your question is equivalent to find the factorial of 1 million.
The number of digits of n! = log10(1) + log10(2) + ... log10(n)
import math
num_dig = 1
for i in range(1,1000000):
num_dig += math.log10(i)
print(num_dig)
So, the number of digits in your answer is 5565703 (approx.).
That's only the final n, if you also want the intermediate results it will require squared memory O(m^2).
import math
ans = 1
for i in range(2,1000001):
ans *= i
print(ans)
N.B: You can approximate with logarithms and Stirling numbers with faster run-time.
A very simple solution would be:
def prod_of():
p=1
for i in range(1,1000000):
p* = i
print(p)

How does the below code work for sum of integers?

I have the question where i need to find the sum of elements in the given numArray for .
But i am unable to get the desired output i want.
numArray = map(int, input().split())
sum_integer = 0
#write your logic to add these 4 numbers here
print(sum_integer) # Print the sum
My solution for that is
for i in range(len(numArray):
sum_integer=sum_integer+numArray[i]
What is wrong with my solution? And i cannot change the way the input is taken.
Your problem is that map(int, input().split()) returns a map object which is an iterator, not a list. To illustrate, your code would work if you converted it to a list.
numArray = list(map(int, input().split()))
As the comments have point out, there are other, better ways to go about it. Changing the for loop to
for i in numArray:
sum_integer += i
is a better solution, and doesn't force you to enter exactly 4 numbers. The other suggestion in the comments, to simply use
print(sum(map(int, input().split())))
which does all the steps in one line is far more concise.

make binary number its 'opposite' in python

trying to take a list of binary numbers, and display their 'opposites', im putting this word in quotes because I'm not sure if it's the best way to describe what I mean.
board=[1,10,101]
I want to make a function that will show the complement of opposite of these numbers like this:
newboard=[0,01,010]
basically swapping the 0 for a 1 and the 1 for a 0. Since they are integers I cant iterate through each binary number and manually change the value, I've tried using two's compliment but that doesn't semantically do what I'm trying to do it seems. Does anyone know a function for how to do this, or what this process would be called? thanks!
Can you represent your binary numbers as strings? Then you could simply do the following:
opposite = { '0':'1', '1':'0'}
board=['1', '10', '101']
newboard = [''.join([opposite[c] for c in n]) for n in board]
You can't really store [0, 01, 010] in a list as it just becomes [0, 1, 10] you can use strings though
def reverse_binary(input):
reversed = []
for x in [list(str(x)) for x in input]:
reversed.append(''.join(['%s' % (int(x) ^ 1) for x in x]))
return reversed
if __name__ == '__main__':
print(reverse_binary([1, 10, 101]))
I believe what you are referring to is just called complementing numbers; you are trying to flipping the digits of binary numbers. The natural thing to do is to use the XOR operator.
Consider the following piece of code:
get_bin = lambda x: format(x, 'b')
def Complement_binary(x):
complemented = []
for num in x:
i = 1
while i <= num:
i = i << 1
complemented.append(get_bin((i - 1) ^ num))
return complemented
The Complement_binary function receives a list of numbers and returns a list of numbers in binary representation in strings (get_bin converts the numbers to binary numbers in strings). If you don't want strings, you may remove the get_bin function in complemented.append(get_bin((i - 1) ^ num)).
Source for get_bin function: https://stackoverflow.com/a/21732313/6833761 by #Martin Thoma
You can swap all the ones for zeros and all the zeros for ones inside every string. To do this simple iterate over the list, and for each value, create a new entry swapping 1 and 0. In order to preform the swap, replace '1' with a value thats never used (such as 'U'), assign '0' to '1' and assign the temp value 'U' to '0'.
newboard = [a.replace('1','U').replace('0','1').replace('U','0') for a in board]

Nest n loops for any n in Python

So, let's say I have an arbitrarily long list of numbers. I'd like to get a list of every number in that list multiplied by every number in that list. I'd do that by nesting for loops like this:
for x in numbers:
for y in numbers:
print(x*y)
Now if I'd like to multiply every number in that list times every number in that list times every number in that list again, I'd do this:
for x in numbers:
for y in numbers:
for z in numbers:
print(x*y*z)
My issue is that I'm searching a graph for a subgraph, and I need to allow for arbitrarily large subgraphs. To do this I have to construct every subgraph with n edges from the edges in the main graph - and I have to allow for arbitrary values of n. How?
itertools.product with an iterative product computing function (I favor reduce(mul, ...)). If you need n-way products (in both senses of the word "product"):
from functools import reduce
from operator import mul
for numset in itertools.product(numbers, repeat=n):
print(reduce(mul, numset))
The above is simple, but it will needlessly recompute partial products when the set of values is large and n >= 3. A recursive function could be used to avoid that:
def compute_products(numbers, repeat):
if repeat == 1:
yield from numbers
return
numbers = tuple(numbers) # Only needed if you want to handle iterator/generator inputs
for prod in compute_products(numbers, repeat-1):
yield from (prod * x for x in numbers)
for prod in compute_products(numbers, n):
print(prod)
I think a recursive function of some kind would probably help you. This is just untested pseudocode typed into the Stack Overflow editor, so beware of using this verbatim, but something like this:
def one_dimension(numbers, n):
if (n < 1):
return
for num in numbers:
for next_num in one_dimension(numbers, n-1):
yield num*next_num
The basic idea is that each "level" of the function calls the next one, and then deals with what the next one produces. I don't know how familiar you are with Python's yield keyword, but if you know what it does, then you should be able to adapt the code above.
Update: Or just use itertools.product like ShadowRanger suggested in his answer; that's probably a better solution to your problem.

Python recursion exercises

"Write a function bin_rep(n) that returns a string with the binary representation of n.
Extend bin_rep(n) to create base_rep(n, k) to give a string representing non-netavie integer n in base k, where 2 <= k <= 10. In base k, the only digits allowed are {0, ..., k-1}.
For a list of distinct integers, L, define switches(L) as the number of pairs in L that are not in increasing order. For example, switches([6, 1, 4]) returns 2, since (6, 1) and (6, 4) are out of order."
Above is the extra credit exercise in lab class. I can't understand how to write those codes at all. I do have the bin_rep(n) function from class notes, but that is about it. Please help. This exercise is not marked at all, but I would like to know how it can be written. Thanks.
def bin_rep(n):
if n == 0:
return ['']
else:
short_strings = bin_rep(n - 1)
strings = []
for s in short_strings:
strings.append('0' + s)
for s in short_strings:
strings.append('1' + s)
return strings
Rather than give you the code, I'll explain how to solve this, so you can write it yourself.
First, note that, contrary to your description, bin_rep does not give the binary representation of the number n; instead, it gives a list of all of the binary strings of up to n digits.
So, assuming you want to do the same thing—that is, give a list of all the base-k strings of up to n digits—you have to identify where the "base 2-ness" comes in.
Look at this code:
for s in short_strings:
strings.append('0' + s)
for s in short_strings:
strings.append('1' + s)
That does something for the digit 0, and then for the digit 1. Those are the two digits of base 2. So, to make this work for base 3 instead, it would be:
for s in short_strings:
strings.append('0' + s)
for s in short_strings:
strings.append('1' + s)
for s in short_strings:
strings.append('2' + s)
But for arbitrary base k, you have to do this for every digit from 0 up to (but not including) k. So, you're going to write some loop that goes through all the numbers in that (half-open) range, and then, instead of repeating this two-liner, just use it once, as a nested loop inside that loop over the digits.
Also, of course, instead of hardcoding the string '0', you're going to need to write the string representation of the digit. (You can't add a number to a string; you have to convert the number to its string representation, and then add that to the string.)
Also keep in mind that you can't just call base_rep(n - 1), because base_rep takes two arguments. What should the second argument be?

Categories

Resources