Appending function values to a list while iterating - python

I am a total Python newbie
so pardon me for this stupid question
The composition() function returns a certain value
However I only want the value to be <=10, and I want 100 of them
The code below calculates the times it took to simulate 100 composition() values to be of <=10
def find():
i=1
aaa=composition()
while(aaa>10):
aaa=composition()
i=i+1
return i
Customers_num=[find() for i in range(100)]
Customers_num=np.array(Customers_num)
print(np.sum(Customers_num))
However, Suppose that the code above returns 150.
And I also want to know all the values that were being simulated in 150 times of composition()
What kind of code should I start with?
I am thinking about combining it with the if else method statement and appending the values to an empty list, but so far my code has been a total disaster
def find():
i=1
aaa=composition()
bbb=[]
if aaa<=10:
bbb.appendd([aaa])
else:
bbb.append([aaa])
aaa=composition()
bbb.appendd([aaa])
while(aaa>10):
i=i+1
if aaa>10:
bbb.append([aaa])
else:
bbb.append([aaa])
return i,bbb
find()
Thanks in advance!

You could make a generator that will generate n of list of values from composition() and stop when n of them are <= 10. This list will include all the numbers, so you have all the intermediate values, and the length of this list will be how "long" it took to generate it. For example (with a fake random composition() function:
from random import randint
def composition():
return randint(0, 20)
def getN(n):
while n > 0:
c = composition()
if c < 10:
n -= 1
yield c
values = list(getN(10)) # get 10 values less than 10
# [2, 0, 11, 15, 12, 8, 16, 16, 2, 8, 10, 3, 14, 2, 9, 18, 6, 11, 1]
time = len(values)
# 19

Related

Faster way to find the biggest prime number less than or equal to the given input

Given an integer number, I want to find the biggest prime number under it. For example:
input 20 -> output 19
input 100 -> output 97.
I already have the simple program given below, but I'm curious about how to make it faster.
def isPrime(x):
for j in range(2,int(x**0.5)+1):
if x%j==0:
return False
return True
def findPrimeNum(num):
for i in range(num-1,1,-1):
if isPrime(i):
return i
findPrimeNum(600851475143) # -> 600851475067
The best way is probably to mirror what several number theory libraries use to implement an efficient next_prime function. The basic layout is identical to yours: an isPrime(x) function, and a loop counting down. Those provide two areas for optimization.
Optimizing isPrime
The recommended approach is to use a number theory library for Python like gmpy2, and a probabilistic primality test like Miller-Rabin repeated an appropriate number of times. This scales fairly well with larger numbers, and you can even get a deterministic primality test by using Miller-Rabin with enough small bases.
Optimizing iteration over possible primes
There is already a comprehensive guide for optimizing next_prime in practice, which basically involves choosing the first k primes (e.g. 2, 3 and 5) and computing all residues modulo their product that could potentially be a prime. Then, rather than iterating over all smaller numbers, you jump between those residues only. To adapt this to previousPrime, we just jump between residues in the opposite direction.
For 2, 3, and 5, those residues mod 30 are L = [1, 7, 11, 13, 17, 19, 23, 29]. For an integer x > 30, say x = 30*q + r, you would do a binary search over L for the largest element less than r, and iterate backwards in this list:
residues = [1, 7, 11, 13, 17, 19, 23, 29]
small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
def prevPrime(num):
if num <= 2:
return 0
q, r = divmod(num, 30)
if q == 0:
return small_primes[bisect_left(small_primes, num) - 1]
num = 30 * q
if r <= 2:
num -= 30
q -= 1
idx = len(residues) - 1
else:
idx = bisect_left(residues, r) - 1
num += residues[idx]
while not (isPrime(num)):
idx -= 1
if idx < 0:
q -= 1
idx = len(residues) - 1
num = 30 * q + residues[idx]
return num

Sorting in ascending order with selection sort

I'm in need of big help, I cant seem to figure out how to do this code. So I am sorting an unsorted list of numbers in ascending order using selection sort and then returning the number of swaps it takes to sort the list.
Below is my code:
def swaps(numbers):
count = 0
for i in range(len(numbers)):
minIndex = i
for j in range(i + 1, len(numbers)):
if numbers[j] < numbers[minIndex]:
minIndex = j
if i != minIndex:
numbers[i], numbers[minIndex] = numbers[minIndex], numbers[i]
count += 1
return count
For these two test cases:
numbers = [0, 4, 2, 7, 5]
print(swaps(numbers))
numbers = [9, 8, 7, 6, 5, 4]
print(swaps(numbers))
it works perfect but for this test case it doesn't work:
import random
random.seed(30)
numbers = [random.randint(1, 50) for index in range(10)]
print(numbers)
print(swaps(numbers))
The numbers list for this test case is [35, 19, 40, 2, 40, 42, 14, 17, 4, 26]. Now working it out it swaps it 7 times but in my test program it is suppose to have swapped 8 times. Is this because of the repeat of 40 ?
How do I configure my code so that it takes into account a repeat of the same number?
If you are supposed to count an extra swap when you have a single pair of duplicate values, an easy way to match that expectation is to change the numbers[j] < numbers[minIndex] check to use <= instead of <.
That's making the code worse though, so I'd be sure to double check if that expectation is actually real or not. Managing to sort with fewer swaps should be a feature, not a bug!

How to make a script that prints the multiples of a number using a for loop and range() function in python

The multiples of number is when you add that number to it self multiple times.
range() generates a sequence of integer numbers. It can take one, two, or three parameters:
range(n): 0, 1, 2, ... n-1
range(x,y): x, x+1, x+2, ... y-1
range(p,q,r): p, p+r, p+2r, p+3r, ... q-1 (if it's a valid increment).
This code with print all the multiples a given number x, n times
x = 2
n = 5
multiples = [x * i for i in range(1, n+1)]
print(multiples)
output:
[2, 4, 6, 8, 10]
This can be accomplished range itself - by setting third argument same as first, assuming that you want to get 10 multiplies of 3 you can do:
n = 3
k = 10
mult = list(range(n, (n*k)+1, n))
print(mult) # [3, 6, 9, 12, 15, 18, 21, 24, 27, 30]
Note that due to first argument being inclusive and second being exclusive I need to add 1 to n*k, otherwise I would get 9 instead of 10 numbers. Keep in mind that range is designed for integer numbers.
def the_multiples_of_number(start_number,end_number,the_number_you_want_to_the_multiples):
for x in range(start_number,end_number,the_number_you_want_to_the_multiples):
print(x)
the_multiples_of_number(0,100,7) #it should prints out the multiples of 7 between 0 & 100
What you want is already implemented by the range function in python.
You can read its documentation here.

Finding max returns unexpected output

I am undertaking a course in discrete mathematics. During this course our book talks about different sorting algorithms. To better understand this I tried to translate one of these algorithms into python, however the algorithm returns some unexpected output and I am failing to realise where my error is. If you would, please have a look below. Any help is much appreciated.
### Find max ###
# A = Array of values to find max from.
# n = Length of array A. Can also be described as the number of loops the array will perform
A = [100, 3, 7, 15, 17, 19, 25, 31, 32, 8, 21, 5, 51, 64, 63]
n = len(A) #len: python command to retrieve length of an array.
def find_max(A, n):
max = 0
for i in range(0, n):
if A[i] > max:
max = i
return max
### Input A and N in the algorithm and print the output ###
print find_max(A, n)
Here the expected output should be 0 since the first entry in the array has the highest value. However the script returns 14, which is the highest key in the array.
I would like the python script to resemble the pseudo code as much as possible. Simply so it is easier for us new students to compare the them to eachother. This is the pseudo code from our book:
find_max(A, n)
max = 0
for i = 0 to n-1
if (A[i] > A[max]) max = i
return max
Why it doesn't work: your attempt is mixing indices & values.
to look like the pseudo-code (with, added a check in case the array is empty so it doesn't return 0):
def find_max(A, n)
if not A:
raise Exception("empty array")
max = 0
for i in range(1,n): # no need to start at 0, already covered
if A[i] > A[max]:
max = i
return max
As a conclusion, the best way to be efficient and pythonic would probably be to use enumerate to carry indices & values and built-in max with a lambda to tell max to look for the values:
max(enumerate(A),key=lambda x:x[1])[0]
First, you shouldn't use max as a variable because it's a Python keyword, second, your variable max (let's call it mx), is holding the index of the maximum value, not the value itself, so here's a solution to your problem :
A = [17, 19, 25, 31, 32, 3, 7, 15, 8, 21, 100, 5, 51, 64, 63]
n = len(A)
def find_max(A, n):
mx = 0 # we call it mx
for i in range(1, n): # since mx = 0, no need start at 0
if A[i] > A[mx]: # we compare the number in A[i] with the number in A[mx] not with mx
mx = i
return mx # index
print(find_max(A, n)) # => 10
this would get the job done :
def find_max(A, n):
max = 0
for i in range(0, n):
if A[i] > max:
max = A[i]
return max
or you can use the buil-in max function :
result = max(A)

Algorithm for finding if an array is balanced [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm trying to create a program that will create a 10 element array and then assign random values to each element. I then want the program to tell if the array is balanced. By balanced I mean, is there anywhere in the array values that at a certain element the sum of the values in the elements are equal to the sum of the array values in the elements greater than that current element.
Example
Element (1,2,3,4) Values (2,1,3,0)
The program would then display that elements 1-2 are balanced to elemtns 3-4, because they both equal 4.
So far I have
import random
size = 10
mean = 0
lists = [0] * size
for i in range(size):
var = random.randint(0,4)
lists[i] = var
for i in lists:
mean += i
avg = (mean)/(size)
I figured the only way the elements could be balanced is if the values average is equal to 2, so I figured that's how I should start.
I'd appreciate any help in the right direction.
If I understand the question, the simplest solution is something like this:
def balanced(numbers):
for pivot in range(len(numbers)):
left_total = sum(numbers[:pivot])
right_total = sum(numbers[pivot:])
if left_total == right_total:
return pivot
return None
For example:
>>> numbers = [2, 1, 3, 0]
>>> balanced(numbers)
2
>>> more_numbers = [2, 1, 3, 4]
>>> balanced(numbers)
(That didn't print anything, because it returned None, meaning there is no pivot to balance the list around.)
While this is the simplest solution, it's obviously not the most efficient, because you keep adding the same numbers up over and over.
If you think about it, it should be pretty easy to figure out how to keep running totals for left_total and right_total, only calling sum once.
def balanced(numbers):
left_total, right_total = 0, sum(numbers)
for pivot, value in enumerate(numbers):
if left_total == right_total:
return pivot
left_total += value
right_total -= value
return None
Finally, here's how you can build a program around it:
size = 10
numbers = [random.range(4) for _ in range(size)]
pivot = balanced(numbers)
if pivot is None:
print('{} is not balanced'.format(numbers))
else:
print('{} is balanced, because elements 1-{} equal {}-{}'.format(
numbers, pivot+1, pivot+2, size+1))
A good data structure to know about for this kind of problem is an array that has the cumulative sum. element[j] - element[i] is the sum from i to j in the original series. If you have the original series [1, 2, 3, 4], the cumulative series is [0, 1, 3, 6, 10]. The sum up to the i position in the original series is element[i] - element[0]. For this problem, we are interested in only a sum starting at 0, so this is a bit of overkill but, again, more fully useful for other problems.
Here is code to make a cumulative sum:
def cumulative_sum(series):
s = [0]
for element in series:
s.append(element + s[-1])
return s
Given that, we can find the pivot point with this code:
def find_pivot(series):
cs = cumulative_sum(series)
total = cs[-1]
even_total = not (total & 1)
if even_total:
target = total // 2
for i, element in enumerate(cs[1:]):
if element == target:
return i + 1
return -1
Notice that it is not necessary to try dividing the series if we know the series sums to an odd number: there cannot be a pivot point then.
Alternatively, you can write find_pivot like this:
def find_pivot(series):
cs = cumulative_sum(series)
total = cs[-1]
even_total = not (total & 1)
if even_total:
target = total // 2
try:
return cs.index(target)
except ValueError:
return -1
return -1
It has the advantage that the looping is not done explicitly in python but in C code in the standard library.
Trying the code out:
def test():
for i in range(1, 30):
test_values = range(i)
j = find_pivot(test_values)
if j >= 0:
print "{0} == {1}".format(test_values[:j], test_values[j:])
And we get this output:
[0] == []
[0, 1, 2] == [3]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] == [15, 16, 17, 18, 19, 20]

Categories

Resources