import re
from math import gcd
class Solution:
def fractionAddition(self, expression: str) -> str:
# Find all fractions in the expression
tokens = re.findall(r'[+-]?\d+/\d+', expression)
numerator, denominator = 0, 1
for frac in tokens:
n, d = map(int, frac.split('/'))
# Add current fraction to the result
numerator = numerator * d + n * denominator
denominator *= d
# Simplify after every addition
g = gcd(abs(numerator), abs(denominator))
numerator //= g
denominator //= g
# If denominator is negative, make it positive and flip sign
if denominator < 0:
numerator = -numerator
denominator = -denominator
return f"{numerator}/{denominator}"
#include <string>
#include <vector>
#include <sstream>
#include <numeric>
using namespace std;
class Solution {
public:
string fractionAddition(string expression) {
vector<string> tokens;
int i = 0, n = expression.size();
while (i < n) {
int j = i + 1;
while (j < n && expression[j] != '+' && expression[j] != '-') ++j;
tokens.push_back(expression.substr(i, j - i));
i = j;
}
int numerator = 0, denominator = 1;
for (const string& frac : tokens) {
int n, d;
sscanf(frac.c_str(), "%d/%d", &n, &d);
numerator = numerator * d + n * denominator;
denominator *= d;
int g = gcd(abs(numerator), abs(denominator));
numerator /= g;
denominator /= g;
}
if (denominator < 0) {
numerator = -numerator;
denominator = -denominator;
}
return to_string(numerator) + "/" + to_string(denominator);
}
};
import java.util.*;
class Solution {
public String fractionAddition(String expression) {
List<String> tokens = new ArrayList<>();
int i = 0, n = expression.length();
while (i < n) {
int j = i + 1;
while (j < n && expression.charAt(j) != '+' && expression.charAt(j) != '-') j++;
tokens.add(expression.substring(i, j));
i = j;
}
int numerator = 0, denominator = 1;
for (String frac : tokens) {
String[] parts = frac.split("/");
int n1 = Integer.parseInt(parts[0]);
int d1 = Integer.parseInt(parts[1]);
numerator = numerator * d1 + n1 * denominator;
denominator *= d1;
int g = gcd(Math.abs(numerator), Math.abs(denominator));
numerator /= g;
denominator /= g;
}
if (denominator < 0) {
numerator = -numerator;
denominator = -denominator;
}
return numerator + "/" + denominator;
}
private int gcd(int a, int b) {
while (b != 0) {
int tmp = a % b;
a = b;
b = tmp;
}
return a;
}
}
var fractionAddition = function(expression) {
let tokens = expression.match(/[+-]?\d+\/\d+/g);
let numerator = 0, denominator = 1;
function gcd(a, b) {
if (!b) return a;
return gcd(b, a % b);
}
for (let frac of tokens) {
let [n, d] = frac.split('/').map(Number);
numerator = numerator * d + n * denominator;
denominator *= d;
let g = Math.abs(gcd(numerator, denominator));
numerator /= g;
denominator /= g;
}
if (denominator < 0) {
numerator = -numerator;
denominator = -denominator;
}
return numerator + "/" + denominator;
};
You are given a string expression
representing a mathematical expression involving the addition and subtraction of fractions (e.g., "-1/2+1/2+1/3"
). Each fraction is represented as numerator/denominator
and the expression may include both positive and negative fractions, separated by '+'
and '-'
signs. Your task is to compute the result of the expression and return it as a string in the form "numerator/denominator"
, where the numerator and denominator are reduced to their simplest form (i.e., the greatest common divisor of numerator and denominator is 1, and the denominator is always positive).
'+'
or '-'
signs.The core challenge in this problem is to systematically parse and process a string that represents a sequence of fraction additions and subtractions. At first, one might think to split the string by operators and process each fraction, but handling signs and ensuring correct parsing can be tricky, especially with negative fractions or consecutive operations.
A brute-force approach would be to convert each fraction to a floating-point number, sum them, and then convert the result back to a fraction. However, this may lead to precision errors, and the problem specifically requires the answer in reduced fractional form.
Therefore, a better approach is to:
Let's break down the algorithm step by step:
a/b + c/d = (a*d + c*b) / (b*d)
.numerator/denominator
".By always reducing the fraction at each step, we avoid integer overflow and ensure correctness.
Let's walk through an example with the input expression = "-1/2+1/2+1/3"
:
Brute-force Approach:
The regular expression or manual parsing is linear in the length of the string, and the arithmetic operations are efficient.
The problem requires adding and subtracting fractions represented as a string and returning the result in reduced form. The key insight is to parse each fraction with its sign, use integer arithmetic to avoid floating-point errors, and reduce the result at every step using the greatest common divisor. This approach is efficient, accurate, and ensures the answer is always in the correct format. The solution elegantly combines careful string parsing with fundamental arithmetic operations, demonstrating a practical application of number theory in programming.