Skip to content

Instantly share code, notes, and snippets.

@erikseulean
Last active May 22, 2022 12:05
Show Gist options
  • Select an option

  • Save erikseulean/913aa9ada62296c75f20037ef4584b9b to your computer and use it in GitHub Desktop.

Select an option

Save erikseulean/913aa9ada62296c75f20037ef4584b9b to your computer and use it in GitHub Desktop.
from collections import defaultdict
class ConversionNotPossible(Exception):
def __init__(self, from_unit, to_unit):
super(Exception).__init__()
self.from_unit = from_unit
self.to_unit = to_unit
def __repr__(self) -> str:
return f"Cannot convert from {self.from_unit} to {self.to_unit}"
class UnitConversion:
def __init__(self):
self._conversions = defaultdict(dict)
def store_conversion_units(self, conversion_pairs):
for from_unit, conversion_factor, to_unit in conversion_pairs:
self._conversions[from_unit][to_unit] = conversion_factor
self._conversions[to_unit][from_unit] = 1/conversion_factor
def convert(self, value, from_unit, to_unit):
# this makes the first call for a from-to pair take the performance hit of the
# graph traversal, however, we can eagerly store all the conversion units
# when we construct the graph. That way the convert function would be O(1)
conversion_factor = self.find_conversion_factor(from_unit, to_unit)
return value * conversion_factor
def find_conversion_factor(self, from_unit, to_unit):
visited_units = set()
def _find_conversion_factor(from_unit, to_unit):
if from_unit in visited_units:
return
if from_unit not in self._conversions:
return
if to_unit in self._conversions[from_unit]:
return self._conversion[from_unit][to_unit]
for unit, conversion_factor in self._conversions[from_unit].items():
overall_conversion_factor = self.find_conversion_factor(self, unit, to_unit)
if not overall_conversion_factor:
continue
return overall_conversion_factor * conversion_factor
visited_units.add(from_unit)
conversion_factor = _find_conversion_factor(from_unit, to_unit)
if not conversion_factor:
raise ConversionNotPossible(from_unit, to_unit)
self._conversions[from_unit][to_unit] = conversion_factor
self._conversions[to_unit][from_unit] = 1/conversion_factor
return conversion_factor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment