Created
April 5, 2022 12:19
-
-
Save tnguven/fdd3021631f00eb1ffa61e02da7f2d77 to your computer and use it in GitHub Desktop.
Currency conversion algorithm with Depth First Search algorithm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const currencies = [ | |
['USD', 'EUR', 0.89], | |
['EUR', 'CHF', 1.03], | |
['CAD', 'USD', 0.79], | |
['GBP', 'USD', 1.34], | |
['AUD', 'HKF', 5.68], | |
['GBP', 'CAD', 1.7], | |
['JPY', 'CAD', 0.011], | |
['GBP', 'JPY', 154.28], | |
] as [CurrencyType, CurrencyType, number][]; | |
type CurrencyType = 'USD' | 'EUR' | 'CHF' | 'CAD' | 'GBP' | 'AUD' | 'JPY'; | |
function convert(val: number, from: CurrencyType, to: CurrencyType) { | |
if (from === to) return val; | |
const res = currencies.reduce((result, currency) => { | |
if (currency.includes(from) && currency.includes(to)) { | |
const [f, , r] = currency; | |
if (f === from) { | |
result = val * r; | |
} else { | |
result = val / r; | |
} | |
} | |
return result; | |
}, 0); | |
if (res) return res; | |
const currencyNames = currencies.reduce((acc, [f, t]) => { | |
acc.add(f); | |
acc.add(t); | |
return acc; | |
}, new Set<CurrencyType>()); | |
const graphList = new Map(); | |
const addNode = (currency: CurrencyType) => { | |
graphList.set(currency, []); | |
}; | |
const addEdge = (origin: CurrencyType, destination: CurrencyType) => { | |
graphList.get(origin).push(destination); | |
graphList.get(destination).push(origin); | |
}; | |
currencyNames.forEach(addNode); | |
currencies.forEach(([f, t]) => addEdge(f, t)); | |
function findPath( | |
start: CurrencyType, | |
visited = new Set<CurrencyType>() | |
): CurrencyType[] | undefined { | |
visited.add(start); | |
const destinations = graphList.get(start); | |
const indexOfFinalDest = destinations.findIndex((currency: CurrencyType) => currency === to); | |
if (indexOfFinalDest !== -1) { | |
return [...visited, destinations[indexOfFinalDest]]; | |
} | |
for (const destination of destinations) { | |
if (destination === to) { | |
return [...visited]; | |
} | |
if (!visited.has(destination)) { | |
return findPath(destination, visited); | |
} | |
} | |
return undefined; | |
} | |
const conversionPath = findPath(from); | |
if (!conversionPath) return null; | |
const { result } = conversionPath.reduce( | |
(acc, path) => { | |
if (acc.query.length < 2) { | |
acc.query.push(path); | |
} | |
if (acc.query.length === 2) { | |
acc.result = convert(acc.result, acc.query[0], acc.query[1]) as number; | |
acc.query.shift(); | |
} | |
return acc; | |
}, | |
{ result: val, query: [] } as { result: number; query: CurrencyType[] } | |
); | |
return result; | |
} | |
const JPY = convert(20, 'EUR', 'JPY'); | |
console.log({ JPY }); // 2585.9505... | |
const GBP = convert(20, 'EUR', 'GBP'); | |
console.log({ GBP }); // 16.77008... | |
const EUR = convert(10, 'USD', 'EUR'); | |
console.log({ EUR }); // 8.9 | |
const AUD = convert(5, 'JPY', 'AUD'); | |
console.log({ AUD }); // null |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment