I’m writing in Python3.
I created two lists in my code and I want to ‘connect’ them in a loop as fractions. Is there any possibility to do it in another way than using Fractions library? Unfortunately I can’t use it because it’s the task requirement. The problem comes up when fraction is a floating point number (for example 1/3).
How can I solve this problem?
Here's an example:
p = [1,2,3]
q = [3,5,9]
frac = []
for i in p:
for j in q:
f = i/j
if f not in frac:
frac.append(f)
You can use the fractions.Fraction type.
import this using: from fractions import Fraction
cast your f equation f = p/q with Fraction; f = Fraction(p/q)
then use the string conversion as well; f = str(Fraction(p/q))
from fractions import Fraction
f = str(Fraction(p/q))
If I understood correctly your problem is not on "how to convert floats to fractions" but yes "how to get a string representation of fraction from arrays of numbers", right?
Actually you can do that in one line:
p = [1,2,3]
q = [3,5,9]
list(map(lambda pair: f"{pair[0]}/{pair[1]}", [(x, y) for x in p for y in q])))
Explaining:
map - receives a function and an iterator, passing each element of the iterator to that function.
[(x, y) for x in p for y in q] - this is a list comprehension, it is generating pairs of numbers "for each x in array p for each y in array q".
lambda pair - this is an anonymous function receiving an argument pair (which we know will be a tuple '(x, y)') and returns the string "x/y" (which is "pair[0]/pair[1]")
Optional procedures
Eliminate zeros in denominator
If you want to avoid impossible fractions (like anything over 0), the list comprehension should be this one:
[(x, y) for x in p for y in q if x != 0]
Eliminate duplicates
Also, if on top of that you want to eliminate duplicate items, just wrap the entire list in a set() operation (sets are iterables with unique elements, and converting a list to a set automatically removes the duplicate elements):
set([(x, y) for x in p for y in q if x != 0])
Eliminate unnecessary duplicate negative signs
The list comprehension is getting a little bigger, but still ok:
set([(x, y) if x>0 or y>0 else (-x,-y) for x in p for y in q if x != 0])
Explaining: if x>0 or y>0, this means that only one of them could be a negative number, so that's ok, return (x,y). If not, that means both of them are negative, so they should be positive, then return (-x,-y).
Testing
The final result of the script is:
p = [1, -1, 0, 2, 3]
q = [3, -5, 9, 0]
print(list(map(lambda pair: f"{pair[0]}/{pair[1]}", set([(x, y) if x>0 or y>0 else (-x,-y) for x in p for y in q if y != 0]))))
# output:
# ['3/-5', '2/-5', '1/5', '1/-5', '0/3', '0/9', '2/3', '2/9', '3/3', '-1/3', '-1/9', '0/5', '3/9', '1/3', '1/9']
(0.33).as_integer_ratio() could work for your problem. Obviously 0.33 would be replaced by whatever float.
Per this question,
def float_to_ratio(flt):
if int(flt) == flt:
return int(flt), 1
flt_str = str(flt)
flt_split = flt_str.split('.')
numerator = int(''.join(flt_split))
denominator = 10 ** len(flt_split[1])
return numerator, denominator
this is also a solution.
You can use a loop to figure out the fraction by the simple code below
x = 0.6725
a = 0
b = 1
while (x != a/b):
if x > a/b:
a += 1
elif x < a/b:
b += 1
print(a, b)
The result of a and b is going to be
269 400
Related
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
This question already has answers here:
Round a Python list of numbers and maintain their sum
(5 answers)
Closed 1 year ago.
I have a list of floats that add up to an integer. For circumstantial reasons, I have to iterate using a for loop x times, x being each float in the list, but since the argument for the range() function must be an integer, each float must be rounded. However, I want the total number of loops to remain equal to the sum of the original floats, which doesn't usually add up to the sum of the rounded numbers. How would you solve this problem?
Thank you.
I recently had to solve a similar problem and decided it was something common enough to various projects of mine to generalize a python solution and package it. Check out iteround.
Ok, this is going to be a bit mathematical:
You have a series of real numbers Xi
Their sum equals N
sum(Xi) = N
Let's break each real number to its floor integer and residual real part (between 0 and 1): Xi = Ri + fi
Now, you need a series of integers Yi that are as close to Xi, but are integers and also sum to N. We can break them like this: Yi = Ri + Fi (where Fi is an integer either 0 or 1).
Now we need that:
sum(Yi) = sum(Xi) = N
If you break that, you'll get this equation as a requirement for the solution:
sum(Fi) = sum(fi) = N - sum(Ri)
Let's denote: K = N - sum(Ri)
Now the solution is simple, choose the K elements which have the largest fi values, and assign their corresponding Fi to 1; assign the other Fi to 0.
Now you have your values for Yi which in your case are the loop sizes
Here's the code for it:
def round_series_retain_integer_sum(xs):
N = sum(xs)
Rs = [round(x) for x in xs]
K = N - sum(Rs)
assert K == round(K)
fs = [x - round(x) for x in xs]
indices = [i for order, (e, i) in enumerate(reversed(sorted((e,i) for i,e in enumerate(fs)))) if order < K]
ys = [R + 1 if i in indices else R for i,R in enumerate(Rs)]
return ys
xs = [5.2, 3.4, 2.1, 7.3, 3.25, 6.25, 8.2, 9.1, 10.1, 55.1]
ys = round_series_retain_integer_sum(xs)
print xs, sum(xs)
print ys, sum(ys)
I think I don't have any bugs, I hope you get the idea even if so
To explain this, this is basically a way to shrink floating point vector data into 8-bit or 16-bit signed or unsigned integers with a single common unsigned exponent (the most common of which being bs16 for precision with a common exponent of 11).
I'm not sure what this pseudo-float method is called; all I know is to get the resulting float, you need to do this:
float_result = int_value / ( 2.0 ** exponent )
What I'd like to do is match this data by basically guessing the exponent by attempting to re-calculate it from the given floats.
(if done properly, it should be able to be re-calculated in other formats as well)
So if all I'm given is a large group of 1140 floats to work with, how can I find the common exponent and convert these floats into this shrunken bu8, bs8, bu16, or bs16 (specified) format?
EDIT: samples
>>> for value in array('h','\x28\xC0\x04\xC0\xF5\x00\x31\x60\x0D\xA0\xEB\x80'):
print( value / ( 2. ** 11 ) )
-7.98046875
-7.998046875
0.11962890625
12.0239257812
-11.9936523438
-15.8852539062
EDIT2:
I wouldn't exactly call this "compression", as all it really is, is an extracted mantissa to be re-computed via the shared exponent.
Maybe something like this:
def validExponent(x,e,a,b):
"""checks if x*2.0**e is an integer in range [a,b]"""
y = x*2.0**e
return a <= y <= b and y == int(y)
def allValid(xs,e,a,b):
return all(validExponent(x,e,a,b) for x in xs)
def firstValid(xs,a,b,maxE = 100):
for e in xrange(1+maxE):
if allValid(xs,e,a,b):
return e
return "None found"
#test:
xs = [x / ( 2. ** 11 ) for x in [-12,14,-5,16,28]]
print xs
print firstValid(xs,-2**15,2**15-1)
Output:
[-0.005859375, 0.0068359375, -0.00244140625, 0.0078125, 0.013671875]
11
You could of course write a wrapper function which will take a string argument such as 'bs16' and automatically compute the bounds a,b
On Edit:
1) If you have the exact values of the floats the above should work. It anything has introduced any round-off error you might want to replace y == int(y) by abs(y-round(y)) < 0.00001 (or something similar).
2) The first valid exponent will be the exponent you want unless all of the integers in the original integer list are even. If you have 1140 values and they are in some sense random, the chance of this happening is vanishingly small.
On Further Edit: If the floats in question are not generated by this process but you want to find an optimal exponent which allows for (lossy) compression to ints of a given size you can do something like this (not thoroughly tested):
import math
def maxExp(x,a,b):
"""returns largest nonnegative integer exponent e with
a <= x*2**e <= b, where a, b are integers with a <= 0 and b > 0
Throws an error if no such e exists"""
if x == 0.0:
e = -1
elif x < 0.0:
e = -1 if a == 0 else math.floor(math.log(a/float(x),2))
else:
e = math.floor(math.log(b/float(x),2))
if e >= 0:
return int(e)
else:
raise ValueError()
def bestExponent(floats,a,b):
m = min(floats)
M = max(floats)
e1 = maxExp(m,a,b)
e2 = maxExp(M,a,b)
MSE = []
for e in range(1+min(e1,e2)):
MSE.append(sum((x - round(x*2.0**e)/2.0**e)**2 for x in floats)/float(len(floats)))
minMSE = min(MSE)
for e,error in enumerate(MSE):
if error == minMSE:
return e
To test it:
>>> import random
>>> xs = [random.uniform(-10,10) for i in xrange(1000)]
>>> bestExponent(xs,-2**15,2**15-1)
11
It seems like the common exponent 11 is chosen for a reason.
If you've got the original values, and the corresponding result, you can use log to find the exponent. Math has a log function you can use. You'd have to log Int_value/float_result to the base 2.
EG:
import Math
x = (int_value/float_result)
math.log(x,2)
I am a brand new to programming and am taking a course in Python. I was asked to do linear regression on a data set that my professor gave out. Below is the program I have written (it doesn't work).
from math import *
f=open("data_setshort.csv", "r")
data = f.readlines()
f.close()
xvalues=[]; yvalues=[]
for line in data:
x,y=line.strip().split(",")
x=float(x.strip())
y=float(y.strip())
xvalues.append(x)
yvalues.append(y)
def regression(x,y):
n = len(x)
X = sum(x)
Y = sum(y)
for i in x:
A = sum(i**2)
return A
for i in x:
for j in y:
C = sum(x*y)
return C
return C
D = (X**2)-nA
m = (XY - nC)/D
b = (CX - AY)/D
return m,b
print "xvalues:", xvalues
print "yvalues:", yvalues
regression(xvalues,yvalues)
I am getting an error that says: line 23, in regression, A = sum (I**2). TypeError: 'float' object is not iterable.
I need to eventually create a plot for this data set (which I know how to do) and for the line defined by the regression. But for now I am trying to do linear regression in Python.
You can't sum over a single float, but you can sum over lists. E. g. you probably mean A = sum([xi**2 for xi in x]) to calculate Sum of each element in x to the power of 2. You also have various return statements in your code that don't really make any sense and can probably be removed completely, e. g. return C after the loop. Additionally, multiplication of two variables a and b can only be done by using a*b in python. Simply writing ab is not possible and will instead be regarded as a single variable with name "ab".
The corrected code could look like this:
def regression(x,y):
n = len(x)
X = sum(x)
Y = sum(y)
A = sum([xi**2 for xi in x])
C = sum([xi*yi for xi, yi in zip(x,y)])
D = X**2 - n*A
m = (X*Y - n*C) / float(D)
b = (C*X - A*Y) / float(D)
return (m, b)
You should probably put in something like A += i**2
As you must understand from the error message that you cannot iterate over a float, which means if i=2 you can't iterate over it as it is not a list, but if as you need to sum all the squares of x, you are iterating over x in for i in x and then you add the squares of i i**2 to A A+=i**2 adn then you return A.
Hope this helps!
I am trying to create a calculator, but I am having trouble writing a function that will subtract numbers from a list.
For example:
class Calculator(object):
def __init__(self, args):
self.args = args
def subtract_numbers(self, *args):
return ***here is where I need the subtraction function to be****
For addition, I can simply use return sum(args) to calculate the total but I am unsure of what I can do for subtractions.
from functools import reduce # omit on Python 2
import operator
a = [1,2,3,4]
xsum = reduce(operator.__add__, a) # or operator.add
xdif = reduce(operator.__sub__, a) # or operator.sub
print(xsum, xdif)
## 10 -8
reduce(operator.xxx, list) basically "inserts" the operator in-between list elements.
It depends exactly what you mean. You could simply subtract the sum of the rest of the numbers from the first one, like this:
def diffr(items):
return items[0] - sum(items[1:])
It's tough to tell because in subtraction it's dependent on the order in which you subtract; however if you subtract from left to right, as in the standard order of operations:
x0 - x1 - x2 - x3 - ... - xn = x0 - (x1 + x2 + x3 + ... + xn)
which is the same interpretation as the code snippet defining diffr() above.
It seems like maybe in the context of your calculator, x0 might be your running total, while the args parameter might represent the numbers x1 through xn. In that case you'd simply subtract sum(args) from your running total. Maybe I'm reading too much into your code... I think you get it, huh?
Subtract function is same as sum having negative signs like this
x = 1
y = 2
sum([x, y])
>>> 3
sum([x, -y])
>>> -1
for more numbers
a = 5
b = 10
c = 15
sum([a, b, c])
sum([a, -b, -c])
In general,
Subtract function is formed by changing you list signs like this
l = [1, 2, 3, 4, ...., n]
new_l = l[0] + [-x for x in l[1:]
# Or
new_l = [-x for x in l]
new_l[0] = -newl[0]
# Or one liner,
new_l = [-x for x in l if x != l[0]]