Making 6 different random Numbers - python

I'm not that good at coding right now, i am trying to improve and learn. ATM i was trying to write a code that randomly picks 6 non-repeating numbers, but i fail at it. what should i do?
import random
a = random.randint(1, 100)
b = random.randint(1, 100)
c = random.randint(1, 100)
x = random.randint(1, 100)
y = random.randint(1, 100)
z = random.randint(1, 100)
outa = b, c, x, y, z
outb = a, c, x, y, z
outc = a, b, x, y, z
outx = a, b, c, y, z
outy = a, b, c, x, z
outz = a, b, c, x, y
all = a, b, c, x, y, z
while a in outa or b in outb or c in outc or x in outx or y in outy or z in outz:
if a in outa:
a = random.randint(1,100)
elif b in outb:
b = random.randint(1,100)
elif c in outc:
c = random.randint(1,100)
elif x in outx:
x = random.randint(1,100)
elif y in outy:
y = random.randint(1,100)
elif z in outz:
z = random.randint(1,100)
print(all)

There is a function in random that does just that:
all = random.sample(range(1,101), 6)
If the list of possible values is too large to build, then your algorithm is fine, but better with a list:
all = []
while len(all) < 6:
x = random.randint(1, 10000000)
if not x in all:
all.append(x)
If your list is much bigger than 6 you can consider using a set instead of a list.
UPDATE: Actually, random.sample() is pretty smart, and with python3 this code:
all = random.sample(range(1,10000000001), 6)
works just fine, while this one:
all = random.sample(list(range(1,10000000001)), 6)
eats all my memory.
If you are with python2 you can use xrange instead of range to get the same effect.

all = a, b, c, x, y, z
Things like that creates a tuple of values. So at the time the line executes, that tuple has fixed values inside and cannot be changed. It especially does not change when you update one of the variables you originally used to construct it. So you cannot use all for the final result, or the outX tuples to check for any duplicates because they are fixed and will not update.
In order for your code to work, you would have to recreate all those tuples in every iteration of your while loop. But in general, you will quickly notice that having those explicit variables is not a good idea.
If you want to keep using randint, then you could just generate one number at a time, and “reroll” whenever you encounter a number you already have:
numbers = []
while len(numbers) < 6:
num = random.randint(1, 100)
if num not in numbers:
numbers.append(num)
I’m using a list here, which is a mutable data structure to collect multiple values (compared to the tuple, which is immutable).
You can also use random.sample here which offers an even easier way to get any number of unique values from a range of numbers:
numbers = random.sample(range(1, 100), 6)

Instead of creating 6 different variables, you could create a list that generates 6 unique numbers using random.sample:
import random
nums = random.sample(range(1,100), 6)
print (nums)
Output:
[2,34,5,61,99,3]

Like this:
random.sample(range(1,100), 6)

Related

I want to select some random numbers but their addition should always be even in Python

import random
for i in range(100):
a = random.randint(1, 20)
b = random.randint(1, 20)
c = random.randint(1, 20)
if ((a + b + c) % 2) == 0:
print(str(a) + "," + str(b) + "," + str(c))
I tried this but I am not getting the desired output. I want it in a way that three random numbers are chosen between 1 and 20 such that their sum is always even. Here the programme prints only the outputs that are even it does not select the numbers in such a way.
Hope you help me. Thanks!
How about checking if the sum first two (a, b) is even or odd, and then accordingly set c?
import random
for i in range(100):
a = random.randint(1, 20)
b = random.randint(1, 20)
if (a + b) % 2 == 0:
c = random.randint(1, 10) * 2
else:
c = random.randint(1, 10) * 2 - 1
if ((a + b + c) % 2) == 0:
print(str(a) + "," + str(b) + "," + str(c))
You could do this:
import random
from itertools import product
# Prepare a list of triplets that add up to an even number
even_triplets = [x for x in product(range(1,21), range(1,21),range(1,21))
if (sum(x)%2)==0]
# Now select 100 of those triplets randomly, allowing
# duplicates (allowing same triplet to appear multiple times)
result = random.choices(even_triplets, k=100)
# If you don't want repetitions, un-comment below line instead of above:
# result = random.sample(even_triplets, 100)
# Print the first and last of the selected 100 triplets, just to verify
print(result[0])
print(result[-1])
Note:
The way the question is phrased currently is a self-contradiction: it says that a, b, and c are to be selected randomly, and it also says that they should add up to an even number. If the selection of a, b, and c is truly random, then it cannot be subject to the additional constraint of adding up to an even number.
for completeness, a less efficient way of generating samples with this distribution would be to use rejection sampling. this works by rejecting values that aren't wanted, in this case where the sum isn't even
from random import randint
def fn():
while True:
x = tuple(randint(1, 20) for _ in range(3))
if sum(x) & 1 == 0:
return x
which can be used as:
for i in range(100):
a, b, c = fn()
print(f'{a}, {b}, {c}')
rejection sampling can be wasteful, but on average we'd only expect to reject one sample for every one we accept so it's not too bad here

Finding number of pythagorean triples in a list using python?

I am coding a solution for a problem where the code will find the number of Pythagorean triples in a list given a list a. However, when I submit my code to the auto-grader, there are some test cases where my code fails, but I have no idea what went wrong. Please help me point out my mistake.....
def Q3(a):
lst = [i ** 2 for i in a]
lst.sort()
ans = 0
for x in lst:
for y in lst:
if (x + y) in lst:
ans += 1
return ans // 2
"Pythagorean triples" are integer solutions to the Pythagorean Theorem, for example, 32+42=52. Given a list of positive integers, find the number of Pythagorean triplets. Two Pythagorean triplets are different if at least one integer is different.
Implementation
· Implement a function Q3(A), where the A is a list of positive integers. The size of list A is up to 250.
· There are no duplicates in the list A
· This function returns the number of Pythagorean triplets.
Sample
· Q3( [3,4,6,5] ) = 1
· Q3( [4,5,6] ) = 0
Simple but not very efficient solution would be to loop through the list of numbers in the range (I have taken number from 1 to 100 for instance) in 3 nested for loops as below. But it would be slower as for 100 elements, it needs to have 100^3 operations
triplets = []
for base in range(1,101):
for height in range(1,101):
for hypotenuse in range(1,101):
# check if forms a triplet
if hypotenuse**2 == base**2 + height**2:
triplets.append(base, height, hypotenuse)
This can be made slightly more efficient (there are better solutions)
by calculating hypotenuse for each base and height combination and then check if the hypotenuse is an Integer
triplets = []
for base in range(1,101):
for height in range(1,101):
hypotenuse = math.sqrt(base**2 + height**2)
# check if hypotenuse is integer by ramiander division by 1
if hypotenuse%1==0:
triplets.append(base, height, hypotenuse)
# the above solution written a list comprehension
a = range(1,101)
[(i,j,math.sqrt(i*i+j*j)) for i in a for j in a if math.sqrt(i*i+j*j)%1==0]
If you consider (3,4,5) and (3,5,4) as different, use a set instead of list and get the len(triplets_set) in the end
Problem 1: Suppose your input is
[3,4,5,5,5]
Though it's somewhat unclear in your question, my presumption is that this should count as three Pythogorean triples, each using one of the three 5s.
Your function would only return 1.
Problem 2: As Sayse points out, your "triple" might be trying to use the same number twice.
You would be better off using itertools.combinations to get distinct combinations from your squares list, and counting how many suitable triples appear.
from itertools import combinations
def Q3(a):
squares = [i**2 for i in a]
squares.sort()
ans = 0
for x,y,z in combinations(squares, 3):
if x + y == z:
ans += 1
return ans
Given the constraints of the input you now added to your question with an edit, I don't think there's anything logically wrong with your implementation. The only type of test cases that your code can fail to pass has to be performance-related as you are using one of the slowest solutions by using 3 nested loops iterating over the full range of the list (the in operator itself is implemented with a loop).
Since the list is sorted and we want x < y < z, we should make y start from x + 1 and make z start from y + 1. And since given an x, the value of x depends on the value of y, for each given y we can increment z until z * z < x * x + y * y no longer holds, and if z * z == x * x + y * y at that point, we've found a Pythagorean triple. This allows y and z to sweep through the values above x only once and therefore reduces the time complexity from O(n^3) to O(n^2), making it around 40 times faster when the size of the list is 250:
def Q3(a):
lst = [i * i for i in sorted(a)]
ans = 0
for x in range(len(lst) - 2):
y = x + 1
z = y + 1
while z < len(lst):
while z < len(lst) and lst[z] < lst[x] + lst[y]:
z += 1
if z < len(lst) and lst[z] == lst[x] + lst[y]:
ans += 1
y += 1
return ans

python generating numbers in modulus

i need to iteratively generate number x, which follow these conditions
(x^z) mod n * x < n
n is known, z changes in every cycle
i need it because I'm implementing timing attack on RSA, and it's needed to generate such number to measure time without modular reduction
Thanks.
If the list of z values is not known in advance you could probably try coroutine for this:
def compute_current(x, n, z):
# some computation here
def crunch(x, n):
current = x
z = yield current
while True:
current = compute_current(current, n, z)
z = yield current
c = crunch(x=10)
next(c)
new_x = crunch.send(some_z)
newer_x = crunch.send(some_other_z)
...

Creating a N sets of combinations of variables from the given range of each variable

This may be a very vague question -- I apologize in advance.
y is a function of a,b,c,d,e.
a can go from 1 to 130; b from 0.5 to 1; c from 3 to 10; d from 0 to 1; and e is 1-d.
Is there a way in python I can create N (say, 10,000) sets of combinations of a,b,c,d and e from the given range?
itertools is a great library for creating iterators like that. In your case, it is product that we need. However, you cannot set the number of point you want. You are going to have to derive that mathematically and translate it into steps (the 1s at the end of the range() function).
a = [i for i in range(1, 131, 1)]
b = [i/10 for i in range(5, 11,1)]
c = [i for i in range(3, 11, 1)]
d = [i/10 for i in range(0, 11, 1)]
from itertools import product
combs = product(a, b, c, d)
for i, x in enumerate(combs, 1):
x = list(x)
x.append(1-x[-1])
print(i, x) # example print: 52076 [99, 0.8, 9, 0.1, 0.9]
The example above produces: 130 * 6 * 8 * 11 = 68640 combinations
These are more than you requested but you get the point. You can also decide to have a variable more ro less finely discretised.
I am also assuming a & c are integer variables..
I assume you want floating point numbers for all of these. If you want ints use random.randint
from random import uniform
inputs = [[uniform(1,130), uniform(.5, 1), uniform(3,10), uniform(0,1)] for _ in range(N)]
for input_list in inputs:
input_list.append(1-input_list[-1])
a(*input_list)

Looping the Fibbonacci Sequence in Python

I am writing a program in Python 2.7.6 that calculates the Fibonacci Sequence(1,1,2,3,5,8,etc.). This is the code(so far):
x = int(input("Enter a number: "))
y = int(input("Enter the number that comes before it:"))
z = x + y
a = z + x
b = a + z
c = b + a
d = c + b
e = d + c
f = e + d
g = f + e
print x, z, a, b, c, d, e, f, g
Is there a way I can loop the process so that I don't have to keep typing f=e+d and others?
Sure, just use some form of loop. For example, if you want to make a list of the first 11 Fibonacci numbers after x:
fiblist = [x]
for _ in range(10):
z = x + y
fiblist.append(z)
x, y = z, x
print(fiblist)
(or use a loop instead of the single print to vary the output's cosmetics -- not relevant to your core Q).
For different purposes (e.g "list all numbers in the sequence until the first one above 100") you could easily tweak the loop (e.g in lieu of the for use while x <= 100:).
You can write a loop or just use the built-in reduce function in Python.
fib = lambda n: reduce(lambda x, y: x+[x[-1]+x[-2]],range(n-2), [0, 1])

Categories