Skip to content

Instantly share code, notes, and snippets.

@kotakagi0914
Created July 31, 2022 10:13
Show Gist options
  • Save kotakagi0914/a6b760436e68e6422c202a5ba6d1c4d5 to your computer and use it in GitHub Desktop.
Save kotakagi0914/a6b760436e68e6422c202a5ba6d1c4d5 to your computer and use it in GitHub Desktop.
/*
## Facts
* m -> 3.28ft
* ft -> 12in
* hr -> 60min
* min -> 60sec
* E.g.
* {2, "m", "in"}
## Queries
* 2m -> ?in => answer: 78.72
* 13in -> ?m => answer: 0.330 (roughly)
* 13in -> ?hr => "not convertible"
* E.g.
* {13, "in", "m"}
*/
package main
import "fmt"
type unitFact struct {
from string
ratio float64
to string
}
type unitConversionQuery struct {
n float64
from, to string
}
type unit struct {
self string
convertibles map[string]float64
}
type unitGraph map[string]unit
func addNodeToUnitGraph(ug unitGraph, from, to string, ratio float64) {
if _, found := ug[from]; !found {
u := unit{self: from, convertibles: make(map[string]float64)}
u.convertibles[to] = ratio
ug[from] = u
} else {
if _, found = ug[from].convertibles[to]; !found {
ug[from].convertibles[to] = ratio
}
}
}
func makeUnitGraph(facts []unitFact) unitGraph {
ug := make(unitGraph)
for _, fact := range facts {
addNodeToUnitGraph(ug, fact.from, fact.to, fact.ratio)
addNodeToUnitGraph(ug, fact.to, fact.from, 1/fact.ratio)
}
return ug
}
func showAnswer(ans float64) {
fmt.Printf("answer: %f\n", ans)
}
func processQuery(ug unitGraph, queries []unitConversionQuery) {
for _, q := range queries {
println("From: ", q.from)
println("To : ", q.to)
// Check if a from/or unit is in facts
if _, found := ug[q.from]; !found {
println("unit not found in facts")
continue
}
if _, found := ug[q.to]; !found {
println("unit not found in facts")
continue
}
// Show the input val if from == to
if q.from == q.to {
showAnswer(q.n)
continue
}
// Explore nodes and check if it is convertible
toVisit := []string{q.to}
visited := make(map[string]bool)
multiplyVal := q.n
for len(toVisit) > 0 {
// Pop
target := toVisit[len(toVisit)-1]
println(target)
toVisit = toVisit[:len(toVisit)-1]
for unitName, ratio := range ug[target].convertibles {
if visited[unitName] {
continue
}
if q.to == unitName {
showAnswer(multiplyVal * ratio)
break
} else {
// Put popped node into visited
visited[target] = true
toVisit = append(toVisit, unitName)
multiplyVal *= ratio
break
}
}
}
}
}
func ConvertUnit(facts []unitFact, queries []unitConversionQuery) {
ug := makeUnitGraph(facts)
fmt.Println(ug)
processQuery(ug, queries)
}
func main() {
facts := []unitFact{
{from: "m", ratio: 3.28, to: "ft"},
{from: "ft", ratio: 12, to: "in"},
{from: "hr", ratio: 60, to: "min"},
{from: "min", ratio: 60, to: "sec"},
}
queries := []unitConversionQuery{
{n: 2, from: "m", to: "in"},
{n: 13, from: "in", to: "m"},
{n: 10, from: "hr", to: "sec"},
{n: 13, from: "in", to: "hr"},
{n: 13, from: "not", to: "hr"},
{n: 13, from: "in", to: "not"},
}
ConvertUnit(facts, queries)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment