Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm a beginner in programming and I'm looking for a nice idea how to generate three integers that satisfy a condition.
Example:
We are given n = 30, and we've been asked to generate three integers a, b and c, so that 7*a + 5*b + 3*c = n.
I tried to use for loops, but it takes too much time and I have a maximum testing time of 1000 ms.
I'm using Python 3.
My attempt:
x = int(input())
c = []
k = []
w = []
for i in range(x):
for j in range(x):
for h in range(x):
if 7*i + 5*j + 3*h = x:
c.append(i)
k.append(j)
w.append(h)
if len(c) == len(k) == len(w)
print(-1)
else:
print(str(k[0]) + ' ' + str(c[0]) + ' ' + str(w[0]))
First, let me note that your task is underspecified in at least two respects:
The allowed range of the generated values is not specified. In particular, you don't specify whether the results may include negative integers.
The desired distribution of the generated values is not specified.
Normally, if not specified, one might assume that a uniform distribution on the set of possible solutions to the equation was expected (since it is, in a certain sense, the most random possible distribution on a given set). But a (discrete) uniform distribution is only possible if the solution set is finite, which it won't be if the range of results is unrestricted. (In particular, if (a, b, c) is a solution, then so is (a, b + 3k, c − 5k) for any integer k.) So if we interpret the task as asking for a uniform distribution with unlimited range, it's actually impossible!
On the other hand, if we're allowed to choose any distribution and range, the task becomes trivial: just make the generator always return a = −n, b = n, c = n. Clearly this is a solution to the equation (since −7n + 5n + 3n = (−7 + 5 + 3)n = 1n), and a degenerate distribution that assigns all probability mass to single point is still a valid probability distribution!
If you wanted a slightly less degenerate solution, you could pick a random integer k (using any distribution of your choice) and return a = −n, b = n + 3k, c = n − 5k. As noted above, this is also a solution to the equation for any k. Of course, this distribution is still somewhat degenerate, since the value of a is fixed.
If you want to let all return values be at least somewhat random, you could also pick a random h and return a = −n + h, b = n − 2h + 3k and c = n + h − 5k. Again, this is guaranteed to be a valid solution for any h and k, since it clearly satisfies the equation for h = k = 0, and it's also easy to see that increasing or decreasing either h or k will leave the value of the left-hand side of the equation unchanged.
In fact, it can be proved that this method can generate all possible solutions to the equation, and that each solution will correspond to a unique (h, k) pair! (One fairly intuitive way to see this is to plot the solutions in 3D space and observe that they form a regular lattice of points on a 2D plane, and that the vectors (+1, −2, +1) and (0, +3, −5) span this lattice.) If we pick h and k from some distribution that (at least in theory) assigns a non-zero probability to every integer, then we'll have a non-zero probability of returning any valid solution. So, at least for one somewhat reasonable interpretation of the task (unbounded range, any distribution with full support) the following code should solve the task efficiently:
from random import gauss
def random_solution(n):
h = int(gauss(0, 1000)) # any distribution with full support on the integers will do
k = int(gauss(0, 1000))
return (-n + h, n - 2*h + 3*k, n + h - 5*k)
If the range of possible values is restricted, the problem becomes a bit trickier. On the positive side, if all values are bounded below (or above), then the set of possible solutions is finite, and so a uniform distribution exists on it. On the flip side, efficiently sampling this uniform distribution is not trivial.
One possible approach, which you've used yourself, is to first generate all possible solutions (assuming there's a finite number of them) and then sample from the list of solutions. We can do the solution generation fairly efficiently like this:
find all possible values of a for which the equation might have a solution,
for each such a, find all possible values of b for which there still have a solution,
for each such (a, b) pair, solve the equation for c and check if it's valid (i.e. an integer within the specified range), and
if yes, add (a, b, c) to the set of solutions.
The tricky part is step 2, where we want to calculate the range of possible b values. For this, we can make use of the observation that, for a given a, setting c to its smallest allowed value and solving the equation gives an upper bound for b (and vice versa).
In particular, solving the equation for a, b and c respectively, we get:
a = (n − 5b − 3c) / 7
b = (n − 7a − 3c) / 5
c = (n − 7a − 5b) / 3
Given lower bounds on some of the values, we can use these solutions to compute corresponding upper bounds on the others. For example, the following code will generate all non-negative solutions efficiently (and can be easily modified to use a lower bound other than 0, if needed):
def all_nonnegative_solutions(n):
a_min = b_min = c_min = 0
a_max = (n - 5*b_min - 3*c_min) // 7
for a in range(a_min, a_max + 1):
b_max = (n - 7*a - 3*c_min) // 5
for b in range(b_min, b_max + 1):
if (n - 7*a - 5*b) % 3 == 0:
c = (n - 7*a - 5*b) // 3
yield (a, b, c)
We can then store the solutions in a list or a tuple and sample from that list:
from random import choice
solutions = tuple(all_nonnegative_solutions(30))
a, b, c = choice(solutions)
Ps. Apparently Python's random.choice is not smart enough to use reservoir sampling to sample from an arbitrary iterable, so we do need to store the full list of solutions even if we only want to sample from it once. Or, of course, we could always implement our own sampler:
def reservoir_choice(iterable):
r = None
n = 0
for x in iterable:
n += 1
if randrange(n) == 0:
r = x
return r
a, b, c = reservoir_choice(all_nonnegative_solutions(30))
BTW, we could make the all_nonnegative_solutions function above a bit more efficient by observing that the (n - 7*a - 5*b) % 3 == 0 condition (which checks whether c = (n − 7a − 5b) / 3 is an integer, and thus a valid solution) is true for every third value of b. Thus, if we first calculated the smallest value of b that satisfies the condition for a given a (which can be done with a bit of modular arithmetic), we could iterate over b with a step size of 3 starting from that minimum value and skip the divisibility check entirely. I'll leave implementing that optimization as an exercise.
import numpy as np
def generate_answer(n: int, low_limit:int, high_limit: int):
while True:
a = np.random.randint(low_limit, high_limit + 1, 1)[0]
b = np.random.randint(low_limit, high_limit + 1, 1)[0]
c = (n - 7 * a - 5 * b) / 3.0
if int(c) == c and low_limit <= c <= high_limit:
break
return a, b, int(c)
if __name__ == "__main__":
n = 30
ans = generate_answer(low_limit=-5, high_limit=50, n=n)
assert ans[0] * 7 + ans[1] * 5 + ans[2] * 3 == n
print(ans)
If you select two of the numbers a, b, c, you know the third. In this case, I randomize ints for a, b, and I find c by c = (n - 7 * a - 5 * b) / 3.0.
Make sure c is an integer, and in the allowed limits, and we are done.
If it is not, randomize again.
If you want to generate all possibilities,
def generate_all_answers(n: int, low_limit:int, high_limit: int):
results = []
for a in range(low_limit, high_limit + 1):
for b in range(low_limit, high_limit + 1):
c = (n - 7 * a - 5 * b) / 3.0
if int(c) == c and low_limit <= c <= high_limit:
results.append((a, b, int(c)))
return results
If third-party libraries are allowed, you can use SymPy's diophantine.diop_linear linear Diophantine equations solver:
from sympy.solvers.diophantine.diophantine import diop_linear
from sympy import symbols
from numpy.random import randint
n = 30
N = 8 # Number of solutions needed
# Unknowns
a, b, c = symbols('a, b, c', integer=True)
# Coefficients
x, y, z = 7, 5, 3
# Parameters of parametric equation of solution
t_0, t_1 = symbols('t_0, t_1', integer=True)
solution = diop_linear(x * a + y * b + z * c - n)
if not (None in solution):
for s in range(N):
# -10000 and 10000 (max and min for t_0 and t_1)
t_sub = [(t_0, randint(-10000, 10000)), (t_1, randint(-10000, 10000))]
a_val, b_val, c_val = map(lambda t : t.subs(t_sub), solution)
print('Solution #%d' % (s + 1))
print('a =', a_val, ', b =', b_val, ', c =', c_val)
else:
print('no solutions')
Output (random):
Solution #1
a = -141 , b = -29187 , c = 48984
Solution #2
a = -8532 , b = -68757 , c = 134513
Solution #3
a = 5034 , b = 30729 , c = -62951
Solution #4
a = 7107 , b = 76638 , c = -144303
Solution #5
a = 4587 , b = 23721 , c = -50228
Solution #6
a = -9294 , b = -106269 , c = 198811
Solution #7
a = -1572 , b = -43224 , c = 75718
Solution #8
a = 4956 , b = 68097 , c = -125049
Why your solution can't cope with large values of n
You may understand that everything in a for loop with a range of i, will run i times. So it will multiply the time taken by i.
For example, let's pretend (to keep things simple) that this runs in 4 milliseconds:
if 7*a + 5*b + 3*c = n:
c.append(a)
k.append(b)
w.append(c)
then this will run in 4×n milliseconds:
for c in range(n):
if 7*a + 5*b + 3*c = n:
c.append(a)
k.append(b)
w.append(c)
Approximately:
n = 100 would take 0.4 seconds
n = 250 would take 1 second
n = 15000 would take 60 seconds
If you put that inside a for loop over a range of n then the whole thing will be repeated n times. I.e.
for b in range(n):
for c in range(n):
if 7*a + 5*b + 3*c = n:
c.append(a)
k.append(b)
w.append(c)
will take 4n² milliseconds.
n = 30 would take 4 seconds
n = 50 would take 10 seconds
n = 120 would take 60 seconds
Putting it in a third for-loop will take 4n³ milliseconds.
n = 10 would take 4 seconds
n = 14 would take 10 seconds.
n = 24 would take 60 seconds.
Now, what if you halved the original if to 2 milliseconds? n would be able to increase by 15000 in the first case... and 23 in the last case. The lesson here is that fewer for-loops is usually much more important than speeding up what's inside them. As you can see in Gulzar's answer part 2, there are only two for loops which makes a big difference. (This only applies if the loops are inside each other; if they are just one after another you don't have the multiplication problem.)
from my perspective, the last number of the three is never a random number. let say you generate a and b first then c is never a random because it should be calculated from the equation
n = 7*a + 5*b + 3*c
c = (7*a + 5*b - n) / -3
this means that we need to generate two random values (a,b)
that 7*a + 5*b - n is divisible by 3
import random
n = 30;
max = 1000000;
min = -1000000;
while True:
a = random.randint(min , max);
b = random.randint(min , max);
t = (7*a) + (5*b) - n;
if (t % 3 == 0) :
break;
c = (t/-3);
print("A = " + str(a));
print("B = " + str(b));
print("C = " + str(c));
print("7A + 5B + 3C =>")
print("(7 * " + str(a) + ") + (5 * " + str(b) + ") + (3 * " + str(c) + ") = ")
print((7*a) + (5*b) + (3*c));
REPL
Define a function that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.
For example, given 6,7,8, the function that I defined should return 113
When I gave my code, it solves most of the problems but apparently there is some possibility that I haven't tried?? I think my code is flawed but not sure what other possibilities are there. Would really appreciate some help thank you so much!
def bigger_sum(a,b,c):
if(a+b>b+c):
return(a*a+b*b)
if(a+c>b+c):
return(a*a+c*c)
if(b+c>a+c):
return(b*b+c*c)
You can use min for this problem:
def big2_sqrsum(a,b,c):
x = min(a,b,c)
return (a*a + b*b + c*c) - (x*x)
print(big2_sqrsum(6,7,8))
Output:
113
Alternate solution with if-else
def big2_sqrsum2(a,b,c):
if a < b and a <c:
return b*b + c*c
elif b < a and b < c:
return a*a + c*c
elif c < a and c < b:
return a*a + b*b
Just check for the smallest number. That known, assign the values to two new variables that will hold the largest and second largest value and sum their squares.
Something like this :
big1 = 0
big2 = 0
if ([a is smallest]):
big1 = b
big2 = c
elif ([b is smallest]):
big1 = a
big2 = c
elif ([c is smallest]):
big1 = a
big2 = b
allows you to have only one place to calculate your formula :
return big1 * big1 + big2 * big2
Let's take a look at why your code is flawed. Given a comparison like if a + b > b + c:, the implication that both a and b are both greater than c is false. b can be the smallest number. All you know is that a > c, since you can subtract b from both sides of the inequality.
You need to find and discard the smallest number. The simplest way is to compute the minimum with min and subtract it off, as #Sociopath's answer suggests.
If you want to keep your if-elsestructure, you have to compare numbers individually:
if a > b:
n1= a
n2 = b if b > c else c
elif a > c:
n1, n2 = a, b
else:
n1, n2 = b, c
You can Simply Define Function With Using min()
def two_bigger_sum(num1,num2,num3):
min_num = min(num1,num2,num3) # it returns minimum number
return ((num1**2 + num2**2 + num3**2)-(min_num**2)) # num**2 = square of num
print(two_bigger_sum(6,7,8))
Output = 113
Sociopath's answer works, but is inefficient since it requires two extra floating point multiplies. If you're doing this for a large number of items, it will take twice as long! Instead, you can find the two largest numbers directly. Basically, we're sorting the list and taking the two largest, this can be directly as follows:
def sumsquare(a,b,c):
# Strategy: swap, and make sure c is the smallest by the end
if c > b:
b, c = c, b
if c > a:
a, c = c, a
return a**2 + b**2
# Test:
print(sumsquare(3,1,2))
print(sumsquare(3,2,1))
print(sumsquare(1,2,3))
print(sumsquare(1,3,2))
print(sumsquare(2,1,3))
print(sumsquare(2,3,2))
I have tried to use list comprehension & list slicing with sorting method.
def b2(l):
return sum([x**2 for x in sorted(l)[1:]])
print(b2([1,2,3]))
OP:-
13
Ok so I'm fairly new to coding and I am to approximate a WCET T(a, b) and complexity of a function. Example function:
def testFunction(self):
x = 0
for r in range(a):
for c in range(b):
if testFunction2(r, c):
x = x + 1
return x
I understand that the complexity of this function is quadratic O(N^2) but I'm not sure on approximating the WCET?
Also isn't there only two assignments in that function, being:
x = 0
and
x = x + 1
?
If so, how do I express the assignments with T(a, b)?
Maths has never been my strong point but I want to learn how to do this. None of the materials I've read explains it in a way I understand.
Thanks in advance.
def testFunction(self):
x = 0 # 1
for r in range(a): # a
for c in range(b): # b
if testFunction2(r, c): # a*b
x = x + 1 # depends testFunction2
return x # 1
WCET for this function ab where a=n b=n then you can say O(n^2)
if always testFunction2 returns True then x = x +1 will execute ab times but it wont effect the sum of execution time.
Finally you sum all this exection time:
(1 + a + b + a*b + a*b + 1)
2 + a + b + 2*a*b
for example, while n = 1000 and a=b=n
2 + 1000 + 1000 + 2*1000*1000
2002 + 2000000
so when you evalute this result you will see 2002 is nothing while you have 2000000.
For a Worst Case Execution Time, you can simply assume there is an input specifically crafted to make your program slow. In this case that would be testfunction2 always returns true.
Within the body of the loop, the assignment x = x + 1 happens a * b times in the worst case.
Instead of describing this as O(N^2), I would describe it as O(ab), and then note for a ~= b ~= N that is O(N^2)
When i run this code it doesn't have an output, and please can you explain the purpose of this code and give a line-by-line explanation of how it achieves its purpose.
def mystery(n):
a, b = 0, 1
while a < n
print (a)
a, b = b, a + b
I have also figured out how to make it output
You add a line which is mystery(n) e.g. mystery(200)
I think it is like this:
• The first line defines a function with one parameter. The word “def” presents a function
definition. The function “def” must be followed by the function name e.g. mystery.
• The second line contains a multiple assignment. It is saying that the variable “a” is equal
to 0 and “b” is equal to 1
• The function defines the value of “n”. On the third line “n” is undefined.
• The fourth line is to print (a)
• The fifth line makes
This code is a Fibonacci series generator upto n. The only error is the missing colon (:) after while statement. It starts with a=0 abd b=1: compares a < n; prints a if comparison generates True; assigns b to a and increments b by a; continues while loop until comparison generates False:
>>> def mystery(n):
... a, b = 0, 1
... while a < n:
... print (a)
... a,b = b,a+b
...
>>> mystery (10)
0
1
1
2
3
5
8
# This is a method.
# You can call this method to its logic. (sea last line)
# N would be the maximum value
def mystery(n):
# This is the same as:
# a = 0 Asign a to 0
# b = 1 Asign b to 1
a, b = 0, 1
# Do the following until a is the same or bigger than n.
while a < n:
# Print the value of a
print a
# This is the same as:
# temp = a
# a = b
# b = a + b
# Example: a =1 and b =2
# temp = a
# a = 2
# b = temp + 2
a, b = b, a + b
# Calling the method with value 10
# you first have to call this before it executes
mystery(10)
Output:
0
1
1
2
3
5
8
This is called fibonacci
Instead of defining the value you want the Fibonacci sequence for inside of the code, why not change the code to:
def mystery(n):
a, b = 0, 1
while a < n:
print (a)
a, b = b, a + b
mystery(int(input("Insert A Number: ")))
This will allow the user to input a value of which, the Fibonacci sequence will be shown.
This is my code:
def sum_even(a, b):
count = 0
for i in range(a, b, 1):
if(i % 2 == 0):
count += [i]
return count
An example I put was print(sum_even(3,7)) and the output is 0. I cannot figure out what is wrong.
Your indentation is off, it should be:
def sum_even(a, b):
count = 0
for i in range(a, b, 1):
if(i % 2 == 0):
count += i
return count
so that return count doesn't get scoped to your for loop (in which case it would return on the 1st iteration, causing it to return 0)
(And change [i] to i)
NOTE: another problem - you should be careful about using range:
>>> range(3,7)
[3, 4, 5, 6]
so if you were to do calls to:
sum_even(3,7)
sum_even(3,8)
right now, they would both output 10, which is incorrect for sum of even integers between 3 and 8, inclusive.
What you really want is probably this instead:
def sum_even(a, b):
return sum(i for i in range(a, b + 1) if i % 2 == 0)
Move the return statement out of the scope of the for loop (otherwise you will return on the first loop iteration).
Change count += [i] to count += i.
Also (not sure if you knew this), range(a, b, 1) will contain all the numbers from a to b - 1 (not b). Moreover, you don't need the 1 argument: range(a,b) will have the same effect. So to contain all the numbers from a to b you should use range(a, b+1).
Probably the quickest way to add all the even numbers from a to b is
sum(i for i in xrange(a, b + 1) if not i % 2)
You can make it far simpler than that, by properly using the step argument to the range function.
def sum_even(a, b):
return sum(range(a + a%2, b + 1, 2))
You don't need the loop; you can use simple algebra:
def sum_even(a, b):
if (a % 2 == 1):
a += 1
if (b % 2 == 1):
b -= 1
return a * (0.5 - 0.25 * a) + b * (0.25 * b + 0.5)
Edit:
As NPE pointed out, my original solution above uses floating-point maths. I wasn't too concerned, since the overhead of floating-point maths is negligible compared with the removal of the looping (e.g. if calling sum_even(10, 10000)). Furthermore, the calculations use (negative) powers of two, so shouldn't be subject by rounding errors.
Anyhow, with the simple trick of multiplying everything by 4 and then dividing again at the end we can use integers throughout, which is preferable.
def sum_even(a, b):
if (a % 2 == 1):
a += 1
if (b % 2 == 1):
b -= 1
return (a * (2 - a) + b * (2 + b)) // 4
I'd like you see how your loops work if b is close to 2^32 ;-)
As Matthew said there is no loop needed but he does not explain why.
The problem is just simple arithmetic sequence wiki. Sum of all items in such sequence is:
(a+b)
Sn = ------- * n
2
where 'a' is a first item, 'b' is last and 'n' is number if items.
If we make 'a' and b' even numbers we can easily solve given problem.
So making 'a' and 'b' even is just:
if ((a & 1)==1):
a = a + 1
if ((b & 1)==1):
b = b - 1
Now think how many items do we have between two even numbers - it is:
b-a
n = --- + 1
2
Put it into equation and you get:
a+b b-a
Sn = ----- * ( ------ + 1)
2 2
so your code looks like:
def sum_even(a,b):
if ((a & 1)==1):
a = a + 1
if ((b & 1)==1):
b = b - 1
return ((a+b)/2) * (1+((b-a)/2))
Of course you may add some code to prevent a be equal or bigger than b etc.
Indentation matters in Python. The code you write returns after the first item processed.
This might be a simple way of doing it using the range function.
the third number in range is a step number, i.e, 0, 2, 4, 6...100
sum = 0
for even_number in range(0,102,2):
sum += even_number
print (sum)
def sum_even(a,b):
count = 0
for i in range(a, b):
if(i % 2 == 0):
count += i
return count
Two mistakes here :
add i instead of [i]
you return the value directly at the first iteration. Move the return count out of the for loop
The sum of all the even numbers between the start and end number (inclusive).
def addEvenNumbers(start,end):
total = 0
if end%2==0:
for x in range(start,end):
if x%2==0:
total+=x
return total+end
else:
for x in range(start,end):
if x%2==0:
total+=x
return total
print addEvenNumbers(4,12)
little bit more fancy with advanced python feature.
def sum(a,b):
return a + b
def evensum(a,b):
a = reduce(sum,[x for x in range(a,b) if x %2 ==0])
return a
SUM of even numbers including min and max numbers:
def sum_evens(minimum, maximum):
sum=0
for i in range(minimum, maximum+1):
if i%2==0:
sum = sum +i
i= i+1
return sum
print(sum_evens(2, 6))
OUTPUT is : 12
sum_evens(2, 6) -> 12 (2 + 4 + 6 = 12)
List based approach,
Use b+1 if you want to include last value.
def sum_even(a, b):
even = [x for x in range (a, b) if x%2 ==0 ]
return sum(even)
print(sum_even(3,6))
4
[Program finished]
This will add up all your even values between 1 and 10 and output the answer which is stored in the variable x
x = 0
for i in range (1,10):
if i %2 == 0:
x = x+1
print(x)