feat: add temperature unit conversions (#5315)

Co-authored-by: Bama Charan Chhandogi <b.c.chhandogi@gmail.com>
This commit is contained in:
Piotr Idzik
2024-08-22 08:43:52 +02:00
committed by GitHub
parent 5149051e95
commit 07dbc51e1b
5 changed files with 189 additions and 0 deletions

View File

@ -0,0 +1,23 @@
package com.thealgorithms.conversions;
public final class AffineConverter {
private final double slope;
private final double intercept;
public AffineConverter(final double inSlope, final double inIntercept) {
slope = inSlope;
intercept = inIntercept;
}
public double convert(final double inValue) {
return slope * inValue + intercept;
}
public AffineConverter invert() {
assert slope != 0.0;
return new AffineConverter(1.0 / slope, -intercept / slope);
}
public AffineConverter compose(final AffineConverter other) {
return new AffineConverter(slope * other.slope, slope * other.intercept + intercept);
}
}

View File

@ -0,0 +1,14 @@
package com.thealgorithms.conversions;
import static java.util.Map.entry;
import java.util.Map;
import org.apache.commons.lang3.tuple.Pair;
public final class UnitConversions {
private UnitConversions() {
}
public static final UnitsConverter TEMPERATURE = new UnitsConverter(Map.ofEntries(entry(Pair.of("Kelvin", "Celsius"), new AffineConverter(1.0, -273.15)), entry(Pair.of("Celsius", "Fahrenheit"), new AffineConverter(9.0 / 5.0, 32.0)),
entry(Pair.of("Réaumur", "Celsius"), new AffineConverter(5.0 / 4.0, 0.0)), entry(Pair.of("Delisle", "Celsius"), new AffineConverter(-2.0 / 3.0, 100.0)), entry(Pair.of("Rankine", "Kelvin"), new AffineConverter(5.0 / 9.0, 0.0))));
}

View File

@ -0,0 +1,86 @@
package com.thealgorithms.conversions;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.tuple.Pair;
public final class UnitsConverter {
private final Map<Pair<String, String>, AffineConverter> conversions;
private final Set<String> units;
private static void putIfNeeded(Map<Pair<String, String>, AffineConverter> conversions, final String inputUnit, final String outputUnit, final AffineConverter converter) {
if (!inputUnit.equals(outputUnit)) {
final var key = Pair.of(inputUnit, outputUnit);
conversions.putIfAbsent(key, converter);
}
}
private static Map<Pair<String, String>, AffineConverter> addInversions(final Map<Pair<String, String>, AffineConverter> knownConversions) {
Map<Pair<String, String>, AffineConverter> res = new HashMap<Pair<String, String>, AffineConverter>();
for (final var curConversion : knownConversions.entrySet()) {
final var inputUnit = curConversion.getKey().getKey();
final var outputUnit = curConversion.getKey().getValue();
putIfNeeded(res, inputUnit, outputUnit, curConversion.getValue());
putIfNeeded(res, outputUnit, inputUnit, curConversion.getValue().invert());
}
return res;
}
private static Map<Pair<String, String>, AffineConverter> addCompositions(final Map<Pair<String, String>, AffineConverter> knownConversions) {
Map<Pair<String, String>, AffineConverter> res = new HashMap<Pair<String, String>, AffineConverter>();
for (final var first : knownConversions.entrySet()) {
final var firstKey = first.getKey();
putIfNeeded(res, firstKey.getKey(), firstKey.getValue(), first.getValue());
for (final var second : knownConversions.entrySet()) {
final var secondKey = second.getKey();
if (firstKey.getValue().equals(secondKey.getKey())) {
final var newConversion = second.getValue().compose(first.getValue());
putIfNeeded(res, firstKey.getKey(), secondKey.getValue(), newConversion);
}
}
}
return res;
}
private static Map<Pair<String, String>, AffineConverter> addAll(final Map<Pair<String, String>, AffineConverter> knownConversions) {
final var res = addInversions(knownConversions);
return addCompositions(res);
}
private static Map<Pair<String, String>, AffineConverter> computeAllConversions(final Map<Pair<String, String>, AffineConverter> basicConversions) {
var tmp = basicConversions;
var res = addAll(tmp);
while (res.size() != tmp.size()) {
tmp = res;
res = addAll(tmp);
}
return res;
}
private static Set<String> extractUnits(final Map<Pair<String, String>, AffineConverter> conversions) {
Set<String> res = new HashSet<>();
for (final var conversion : conversions.entrySet()) {
res.add(conversion.getKey().getKey());
}
return res;
}
public UnitsConverter(final Map<Pair<String, String>, AffineConverter> basicConversions) {
conversions = computeAllConversions(basicConversions);
units = extractUnits(conversions);
}
public double convert(final String inputUnit, final String outputUnit, final double value) {
if (inputUnit.equals(outputUnit)) {
throw new IllegalArgumentException("inputUnit must be different from outputUnit.");
}
final var conversionKey = Pair.of(inputUnit, outputUnit);
return conversions.get(conversionKey).convert(value);
}
public Set<String> availableUnits() {
return units;
}
}