combining strings of n length in a list python - python

Whenever I use permutations, I have to create a list of the permutations because it returns a 'itertools.permutations object at 0x0190A5D0'. Then after I create the list, I have to combine the strings in each list so that I have the permutation I wanted originally. If it is a number, then I have to make them all integers again.
Two part question:
1) Is there an easier way to do a permutation and create the list of numbers?
2) Below I've created a permutation of a number with 5 digits. However, where I have '12345', I want the user to input their own number. Thus the formatting string b=['s%s%s...] will have to be n %s and n x. Anyone know how to do this?
(FYI my program is trying to find the next largest number with the same digits given a user's input so 12345 next largest is 12354)
Both questions were answered below please see both responses. Thanks!!!
def nexthighest():
from itertools import permutations
numb = str(12345)
a = list(permutations(numb))
b = ['%s%s%s%s%s' % xxxxx for xxxxx in a] #<-- this is where the n length problem occurs
c = list(map(int,b))
for i in c:
if i >12345:
print(i)
break

You don't need to build all those lists. Just loop over the return value from permutations, joining and parsing as an integer each permutation as it comes by:
def nexthigher(n):
for p in permutations(sorted(str(n))):
i = int("".join(p))
if i > n:
return i

I can answer part two for you:
b = ["".join(x) for x in a]

Related

Is it possible to use all while loop inside an array?

We can use for loop inside an array,
for example: arr = [i for i in range(10)]
I want to add all the digits of an number into array; can we use the same methodology and implement using while loop?
What you have shown is a list comprehension, not a loop inside an array.
There is no such thing that involves the while keyword.
It's possible to define a generator with a while loop and then use that generator in a list comprehension.
For example, this generates all digits of a non-negative integer (in reverse order):
def digits(n):
while True:
n, d = divmod(n, 10)
yield d
if n == 0:
break
arr = [i for i in digits(123)] # [3, 2, 1]
i want to add all the digits of an number into array can we sue the same methodology and implement using while loop?
No, you cannot do a similar thing with a while loop. The syntax [i for i in range(10)] is called a "list comprehension". If you google these words, you will find more information about how they work.
For the digits of a number, I suggest turning it into a string:
number = 12345
digits = str(number)
Now you can use digits like an array of digit characters:
print(digits[2]) # output: 3
for d in digits:
print(d)
If you want a list of digits as integers rather than characters:
digits = [int(c) for c in str(number)]

Finding the lowest number that does not occur at the end of a string, in a tuple in a list

I have a list of tuples, each has a single string as element 0, in these strings I want to get out the final number, and then find the lowest (positive) number that is not in this list.
How do you do this?
E.g. for the list tups:
tups=[('.p1.r1.c2',),('.p1.r1.c4',),('.p1.r1.c16',)]
the final numbers are 2, 4 and 16, so the lowest unused number is 1.
my attempt was this:
tups2= [tup[0] for tup in tups] # convert tuples in lists to the strings with information we are interested in
tups3 = [tup .rfind("c") for tup in tups2] # find the bit we care about
I wasn't sure how to finish it, or if it was fast/smart way to proceed
Where are you blocked? You can achieve that in basically two steps:
Step 1: Create the list of numbers
One way of doing this (inspired from there):
numbers = [int(s[0][len(s[0].rstrip('0123456789')):]) for s in tups]
In your example, numbers is [2, 4, 16].
Step 2: Find the lowest positive number that is not in this list
x = 1
while x in numbers:
x += 1
You didn't really specify your problem but I'm guessing that getting the lowest unused number is the issue.
the solutions above is great but it just gets the lowest number in the list and not the lowest unused one.
I tried to make a list of all the unused numbers then getting the minimum value of it.
I hope that would help
tups=[('15.p1.r1.c2',),('.poj1.r1.c4',),('.p2.r4.c160',)]
numbers = []
unused_numbers = []
for tup in tups:
words = tup[0].strip(".").split('.')
digits_list = [''.join(x for x in i if x.isdigit()) for i in words]
unused_numbers.extend(digits_list[:-1])
numbers.append(digits_list[-1])
print(numbers)
print(min(unused_numbers))
I used the same method Thibault D used to get a list of numbers:
tups=[('.p1.r1.c2',),('.p1.r1.c4',),('.p1.r1.c16',)]
num = [int(i[0][len(i[0].rstrip('0123456789')):]) for i in tups]
However, I used an easier method to get the minimum number:
min(num) - 1
This basically gets the lowest number in the list, and then subtracts 1 from it.

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)

Generate list of 5 non-repeating integers

I'm new to Python and I am trying to generate a list of 4 random numbers with integers between 1 and 9. The list must contain no repeating integers.
The issue I am having is that the program doesn't output exactly 4 numbers everytime. Sometimes it generates 3 numbers or 2 numbers and I can't figure out how to fix it.
My code:
import random
lst = []
for i in range(5):
r = random.randint(1,9)
if r not in lst: lst.append(r)
print(lst)
Is there a way to do it without the random.sample? This code is part of a larger assignment for school and my teacher doesn't want us using the random.sample or random.shuffle functions.
Your code generates 5 random numbers, but they are not necessarily unique. If a 2 is generated and you already have 2 in list you don't append it, while you should really be generating an alternative digit that hasn't been used yet.
You could use a while loop to test if you already have enough numbers:
result = [] # best not to use list as a variable name!
while len(result) < 5:
digit = random.randint(1, 9)
if digit not in result:
result.append(digit)
but that's all more work than really needed, and could in theory take forever (as millions of repeats of the same 4 initial numbers is still considered random). The standard library has a better method for just this task.
Instead, you can use random.sample() to take 5 unique numbers from a range() object:
result = random.sample(range(1, 10), 5)
This is guaranteed to produce 5 values taken from the range, without duplicate digits, and it does so in 5 steps.
Use random.sample:
import random
random.sample(range(1, 10), 4)
This generates a list of four random values between 1 to 9 with no duplicates.
Your issue is, you're iterating 5 times, with a random range of 1-9. That means you have somewhere in the neighborhood of a 50/50 chance of getting a repeat integer, which your conditional prevents from being appended to your list.
This will serve you better:
def newRunLst():
lst = []
while len(lst) < 4:
r = random.randint(1,9)
if r not in lst: lst.append(r)
print lst
if random list needed is not too small (compared to the total list) then can
generate an indexed DataFrame of random numbers
sort it and
select from the top ... like
(pd.DataFrame([(i,np.random.rand()) for i in range(10)]).sort_values(by=1))[0][:5].sort_index()

How to use nested loops in order take integers and produce strings

I need to create a function that receives a positive integer number (n) and returns a string, using nested loops.
For example:
when n = 3 the returned string should be:
"1+2+3+..1+2+3+..1+2+3+.."
when n = 5 the returned string should be:
1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..
As an example, the following code fragment:
n = 5
res = addnestedloops(n)
print (res)
should produce the output:
1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..1+2+3+4+5+..
Can't seem to find out how to return the string in which it counts upwards until the inputted number...
def themethod(n):
var toprint="";
var tmp;
if(n>0)tmp="1";
for(var i=2;i<=n;i++):
tmp+= "+".i;
for(var i=0;i<n;i++):
toprint += tmp;
print toprint;
I think what you are looking for is head-recursion in python
Here is the code which will let you achieve this
def recursive(n):
if n == 1:
return 1
else:
return str(recursive(n-1)) + "+"+str(n)
A nested loop is just a loop within a loop. If I understand you correctly, you need n strings concatenated, each containing n numbers.
I have a feeling this is a school assignment, so I wont give you the full answer, but I believe the nested loop construction you need is
for i in range(n):
for j in range(n):
# Construct the sub string here and append it to a result variable
Remember that the range function output is zero based, so range(3) produces 0, 1 and 2.
I don't however see why you need a nested loop, other than it should be a part of the assignment. You could just construct the sub string and repeat it n times with substring * n. For example 'hello' * 3 results in 'hellohellohello'.
Oh, and just to give you a bit more to think about, the one-liner solution for your problem is
('+'.join('{0:d}'.format(i+1) for i in range(n)) + '+..') * n

Categories

Resources