Python: Doubles in a random generator - python

I am try to create a generator that will look for n random integers in the range of 1 to m. The code below does exactly that however it will sometimes return a double of a number previously printed. Does anyone know how I can edit that? Another thing but it is more design-wise is, how can I order my print out so that the numbers are in order?
import random
def hwset(m,n):
i=0
for i in range(0,n):
print random.randrange(1,m+1,1)

If you wanted to produce a sample of n numbers out of all integers between 1 and m, use the random.sample() function with an xrange() object (use range() if you are on Python 3):
def hwset(m, n):
return random.sample(xrange(1, m + 1), n)
If you wanted those numbers to be sorted, just sort the result:
sorted_hwset = sorted(hwset(m, n))
Demo:
>>> import random
>>> def hwset(m, n):
... return random.sample(xrange(1, m + 1), n)
...
>>> hwset(100, 5)
[25, 58, 2, 29, 57]
>>> hwset(100, 5)
[84, 55, 80, 65, 47]
>>> sorted(hwset(100, 5))
[1, 25, 77, 81, 92]
>>> sorted(hwset(100, 5))
[34, 46, 59, 66, 76]

Related

Trying to swap the first and last elements of a list in Python, but it works only for a predefined list. Not for a list of randomly generated numbers

I was trying to create a python program which swaps the first and last elements of a list. I passed a pre-created list into the algorithm and it worked perfectly. Here's my code:
def swapFirstAndLast(list_to_be_swapped):
size = len(list_to_be_swapped)
list_to_be_swapped[0],list_to_be_swapped[size-1] = list_to_be_swapped[size-1],list_to_be_swapped[0]
return list_to_be_swapped
l = [12,33,42,76,46,97]
swapFirstAndLast(l)
print(l)
Output:
[97, 33, 42, 76, 46, 12]
Then I tried to create functions; one function to create a list of randomly generated numbers, and the second function to perform the swapping operation. Although everything makes sense to me, it is not performing the swapping operation now. This is the code I came up with:
import random
def generateList(size):
list1 = []
for i in range(size):
list1.append(random.randint(0,99))
return list1
def swapFirstAndLast(list_to_be_swapped):
size = len(list_to_be_swapped)
list_to_be_swapped[0],list_to_be_swapped[size-1] = list_to_be_swapped[size-1],list_to_be_swapped[0]
return list_to_be_swapped
l = generateList(5)
l1 = swapFirstAndLast(l)
print(l,l1)
Output:
[49, 78, 63, 82, 72] [49, 78, 63, 82, 72]
As you can see, it does not perform the swapping operation now. I am not able to understand where I am going wrong.
You are swapping the first and the last element of the initial list (i.e., l) too! Please look at this slightly modified example:
import random
def generateList(size):
list1 = []
for i in range(size):
list1.append(random.randint(0,99))
return list1
def swapFirstAndLast(list_to_be_swapped):
size = len(list_to_be_swapped)
list_to_be_swapped[0],list_to_be_swapped[size-1] = list_to_be_swapped[size-1],list_to_be_swapped[0]
return list_to_be_swapped
l = generateList(5)
print(l)
l1 = swapFirstAndLast(l)
print(l, l1)
Output:
[54, 14, 3, 38, 87]
[87, 14, 3, 38, 54] [87, 14, 3, 38, 54]
As you can see, the list l has been changed.
The thing here is that you are not creating a new list, but you're modifying the existing one. It doesn't matter if it has a different name within the function.
If you want to retain the original list l, and also return a separate swapped list l1, you have to create a new list! Here is how you can do it:
import random
def generateList(size):
return [random.randint(0, 99) for _ in range(size)]
def swapFirstAndLast(list_to_be_swapped):
new_list = list_to_be_swapped.copy()
new_list[0], new_list[-1] = new_list[-1], new_list[0]
return new_list
l = generateList(5)
print(l)
l1 = swapFirstAndLast(l)
print(l, l1)
Output:
[38, 59, 86, 26, 19]
[38, 59, 86, 26, 19] [19, 59, 86, 26, 38]
your program works ! your function just modifies the list directly, you can see it better if you do this :
l = generateList(5)
print(l)
l1 = swapFirstAndLast(l)
print(l1)
It turns out that you have already swapped the list (i.e. l) it's just when your print (l,l1) that it looks like you haven't swapped it because it's printing the swapped version of (l). put the print(l) line above ( l1 = swapFirstAndLast(l) ) to see it!
the swapping can be done by using index:
def swapFirstAndLast(lst):
lst[0], lst[-1] = lst[-1], lst[0]
return lst
lst = [12,33,42,76,46,97]
print(swapFirstAndLast(lst))
result is: [97, 33, 42, 76, 46, 12]

How can i divide list?

from random import *
lotto_num = []
for j in range(7) :
for i in range(1, 8) :
number = randint(1, 46)
while number in lotto_num:
number = randint(1, 46)
lotto_num.append(number)
lotto_num.sort()
print("{0}".format(lotto_num))
This code makes lottery number
so, I want to get lists like
[1,2,3,4,5,6,7]
[2,3,4,5,6,7,8]
[3,4,5,6,7,8,9]
...
but my code only has shown like this
[1,2,3,4,5,6,7,8,9,10.......] ## <- just add number without make new lists!
how i can fix this?
You continually append to lotto_num without resetting it. So it needs to be reset after each print in order to make a new number.
Just move your lotto_num definition to inside the first for loop:
from random import *
for j in range(7) :
lotto_num = []
for i in range(1, 8) :
number = randint(1, 46)
while number in lotto_num:
number = randint(1, 46)
lotto_num.append(number)
lotto_num.sort()
print("{0}".format(lotto_num))
Output:
[7, 17, 29, 32, 34, 44, 45]
[9, 16, 22, 34, 36, 41, 43]
[5, 10, 14, 22, 23, 34, 46]
[2, 11, 18, 27, 32, 35, 37]
[8, 9, 25, 26, 37, 39, 40]
[3, 5, 8, 14, 19, 22, 33]
[4, 5, 14, 17, 18, 30, 34]
First of all, it is recommended to import specific functions instead of whole package. Since we need only randint we can import:
from random import randint
Than your problem can be re-worded as generating n lists of given length l, filled by random numbers from range 1-46.
from random import randint
# number of lotto
n = 5
# length of each lotto
l = 7
# result
lotto_numbers = []
# I am using _ since we do not need that value
for _ in range(n):
lotto = []
for _ in range(l):
number = randint(1, 46)
while number in lotto:
number = randint(1, 46)
lotto.append(number)
lotto.sort()
lotto_numbers.append(lotto)
print(lotto_numbers)
Later you can print generated lotto (or save them into file), that is better approach than printing each lotto right after generation.
...
for lotto in lotto_numbers:
print(lotto)
Probably the cleanest Pythonic solution which uses random.sample to simulate n times drawing random non-repeated numbers from range 1-46 follows:
from random import sample
# number of lotto
n = 5
# length of each lotto
l = 7
lotto_numbers = [sorted(sample(range(1, 46), l)) for _ in range(n)]
print(lotto_numbers)
from random import *
array=[]
for j in range(7) :
lotto_num = []
for i in range(1, 8) :
number = randint(1, 46)
while number in lotto_num:
number = randint(1, 46)
lotto_num.append(number)
lotto_num.sort()
array.append(lotto_num)
print("{0}".format(lotto_num))

Please elaborate the below program

In variable noprimes what is the use of declaring second i in j loop? Is it taking values from first i loop or referencing i values?
>>> noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)]
>>> primes = [x for x in range(2, 50) if x not in noprimes]
>>> print primes
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
Think of it as a double for loop. It might be easier to understand if you read it like this:
[j for j in range(i*2, 50, i) for i in range(2, 8)] # **Not valid Python!**
or this:
noprimes = []
for i in range(2, 8):
for j in range(2 * i, 50, i):
noprimes.append(j)
In the first outer loop iteration, i is 2 and therefore j runs the range(4, 50, 2) range. As a result, the numbers (js) it produces are the following:
j = [4, 6, ..., 48]
In the next iteration, i = 3 and the new js are:
j = [6, 9, ..., 48]
And so on until i = 7. Finally, you put all these js together creating the noprimes list.
This is simply an implementation of Eratosthenes Sieve. It collects all the multiples of (numbers up to 7) up to 50 and everything that is not included in there is a prime.

what is most pythonic way to find a element in a list that is different with other elements?

Suppose we have a list with unknown size and there is an element in the list that is different with other elements but we don't know the index of the element. the list only contains numerics and is fetched from a remote server and the length of the list and the index of the different element is changed every time. what is the most pythonic way to find that different element?
I tried this but I'm not sure if it's the best solution.
a = 1
different_element = None
my_list = fetch_list()
b = my_list[0] - a
for elem in my_list[1::]:
if elem - a != b:
different_element = elem
print(different_element)
This is a great use for numpy
Given some random uniform list with a single uniquely different number in it:
>>> li=[1]*100+[200]+[1]*250
If the uniform value is known (in this case 1 and the unknown value is 200) you can use np.where on an array to get that value:
>>> import numpy as np
>>> a=np.array(li)
>>> a[a!=1]
array([200])
If the uniform values are not known, you can use np.uniques to get the counts of uniques:
>>> np.unique(a, return_counts=True)
(array([ 1, 200]), array([350, 1]))
For a pure Python solution, use a generator with next to get the first value that is different than all the others:
>>> next(e for i, e in enumerate(li) if li[i]!=1)
200
Or, you can use dropwhile from itertools:
>>> from itertools import dropwhile
>>> next(dropwhile(lambda e: e==1, li))
200
If you do not know what the uniform value is, use a Counter on a slice big enough to get it:
>>> uniform=Counter(li[0:3]).most_common()[0][0]
>>> uniform
1
>>> next(e for i, e in enumerate(li) if li[i]!=uniform)
200
In these cases, next will short-circuit at the first value that satisfies the condition.
Would this work for you?
In [6]: my_list = [1,1,1,2,1,1,1]
In [7]: different = [ii for ii in set(my_list) if my_list.count(ii) == 1]
In [8]: different
Out[8]: [2]
You can use Counter from collections package
from collections import Counter
a = [1,2,3,4,3,4,1]
b = Counter(a) # Counter({1: 2, 2: 1, 3: 2, 4: 2})
elem = list(b.keys())[list(b.values()).index(1)] # getting elem which is key with value that equals 1
print(a.index(elem))
Another possible solution that just differently compute elem
a = [1,2,3,4,3,4,1]
b = Counter(a) # Counter({1: 2, 2: 1, 3: 2, 4: 2})
elem = (k for k, v in b.items() if v == 1)
print(a.index(next(elem)))
UPDATE
Time consumption:
As #Jblasco mentioned, Jblasco's method is not really efficient one, and i was curious to measure it.
So the initial data is array with 200-400 elements, with only one unique value. The code that generate that array is. At the end of snipped there is 100 first elements that prove that it has one unique
import random
from itertools import chain
f = lambda x: [x]*random.randint(2,4)
a=list(chain.from_iterable(f(random.randint(0,100)) for _ in range(100)))
a[random.randint(1, 100)] = 101
print(a[:100])
# [5, 5, 5, 84, 84, 84, 46, 46, 46, 46, 6, 6, 6, 68, 68, 68, 68, 38,
# 38, 38, 44, 44, 61, 61, 15, 15, 15, 15, 36, 36, 36, 36, 73, 73, 73,
# 28, 28, 28, 28, 6, 6, 93, 93, 74, 74, 74, 74, 12, 12, 72, 72, 22,
# 22, 22, 22, 78, 78, 17, 17, 17, 93, 93, 93, 12, 12, 12, 23, 23, 23,
# 23, 52, 52, 88, 88, 79, 79, 42, 42, 34, 34, 47, 47, 1, 1, 1, 1, 71,
# 71, 1, 1, 45, 45, 101, 45, 39, 39, 50, 50, 50, 50]
That's the code that show us results, i choose to execute 3 times with 10000 executions:
from timeit import repeat
s = """\
import random
from itertools import chain
f = lambda x: [x]*random.randint(2,4)
a=list(chain.from_iterable(f(random.randint(0,100)) for _ in range(100)))
a[random.randint(1, 100)] = 101
"""
print('my 1st method:', repeat(stmt="""from collections import Counter
b=Counter(a)
elem = (k for k, v in b.items() if v == 1)
a.index(next(elem))""",
setup=s, number=10000, repeat=3)
print('my 2nd method:', repeat(stmt="""from collections import Counter
b = Counter(a)
elem = list(b.keys())[list(b.values()).index(1)]
a.index(elem)""",
setup=s, number=10000, repeat=3))
print('#Jblasco method:', repeat(stmt="""different = [ii for ii in set(a) if a.count(ii) == 1]
different""", setup=s, number=10000, repeat=3))
# my 1st method: [0.303596693000145, 0.27322746600111714, 0.2701447969993751]
# my 2nd method: [0.2715420649983571, 0.28590541199810104, 0.2821485950007627]
# #Jblasco method: [3.2133491599997797, 3.488262927003234, 2.884892332000163]
I would try maybe something like this:
newList = list(set(my_list))
print newList.pop()
Assuming there's only 1 different value and the rest are all the same.
There's a little bit of ambiguity in your question which makes it difficult to answer but that's all I could think of optimally.

finding multiples of a number in Python

I'm trying to write a code that lets me find the first few multiples of a number. This is one of my attempts:
def printMultiples(n, m):
for m in (n,m):
print(n, end = ' ')
I figured out that, by putting for m in (n, m):, it would run through the loop for whatever number was m.
def printMultiples(n, m):
'takes n and m as integers and finds all first m multiples of n'
for m in (n,m):
if n % 2 == 0:
while n < 0:
print(n)
After multiple searches, I was only able to find a sample code in java, so I tried to translate that into python, but I didn't get any results. I have a feeling I should be using the range() function somewhere in this, but I have no idea where.
If you're trying to find the first count multiples of m, something like this would work:
def multiples(m, count):
for i in range(count):
print(i*m)
Alternatively, you could do this with range:
def multiples(m, count):
for i in range(0,count*m,m):
print(i)
Note that both of these start the multiples at 0 - if you wanted to instead start at m, you'd need to offset it by that much:
range(m,(count+1)*m,m)
Does this do what you want?
print range(0, (m+1)*n, n)[1:]
For m=5, n=20
[20, 40, 60, 80, 100]
Or better yet,
>>> print range(n, (m+1)*n, n)
[20, 40, 60, 80, 100]
For Python3+
>>> print(list(range(n, (m+1)*n, n)))
[20, 40, 60, 80, 100]
Based on mathematical concepts, I understand that:
all natural numbers that, divided by n, having 0 as remainder, are all multiples of n
Therefore, the following calculation also applies as a solution (multiples between 1 and 100):
>>> multiples_5 = [n for n in range(1, 101) if n % 5 == 0]
>>> multiples_5
[5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
For further reading:
https://www.mathsisfun.com/definitions/natural-number.html
https://www.mathwizz.com/arithmetic/help/help9.htm
https://www.calculatorsoup.com/calculators/math/multiples.php
For the first ten multiples of 5, say
>>> [5*n for n in range(1,10+1)]
[5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
You can do:
def mul_table(n,i=1):
print(n*i)
if i !=10:
mul_table(n,i+1)
mul_table(7)
If this is what you are looking for -
To find all the multiples between a given number and a limit
def find_multiples(integer, limit):
return list(range(integer,limit+1, integer))
This should return -
Test.assert_equals(find_multiples(5, 25), [5, 10, 15, 20, 25])
Another method that can be done is trying to make a list. Here's my example for getting the first 20 multiples of 7.
Input:
multiples_7 = [x * 7 for x in range(1,21)]
print(multiples_7)
Output:
[7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98, 105, 112, 119, 126, 133, 140]
def multiples(n,m,starting_from=1,increment_by=1):
"""
# Where n is the number 10 and m is the number 2 from your example.
# In case you want to print the multiples starting from some other number other than 1 then you could use the starting_from parameter
# In case you want to print every 2nd multiple or every 3rd multiple you could change the increment_by
"""
print [ n*x for x in range(starting_from,m+1,increment_by) ]
For first 10 multiples of 5 you can do as
import numpy as np
#np.arange(1,11) array from 1 to 10
array_multipleof5 = [5*n for n in np.arange(1,11)]
array_multipleof5 = np.array(array_multipleof5)
print(array_multipleof5)
How to calculate the first n multiples of a given number x, in the compact python's lambda notation
n_multiples_of_x = lambda n,x : list( range(x, x*n + 1, x) )
Tests:
assert n_multiples_of_x(5, 5) == [5, 10, 15, 20, 25]

Categories