0
\$\begingroup\$

Problem statement:

Write a program that converts all given temperatures from a given input temperature scale to a given output temperature scale. The temperature scales to be supported are Kelvin, Celsius, Fahrenheit, Rankine, Delisle, Newton, Rømer, Réaumur.

Synopsis: tempconv INPUT_SCALE OUTPUT_SCALE [TEMPERATURE]...

The INPUT_SCALE and OUTPUT_SCALE shall be given as follows:

  • K for Kelvin
  • C for Celsius
  • F for Fahrenheit
  • R for Rankine
  • D for Delisle
  • N for Newton
  • for Rømer
  • for Réaumur.

Example:

tempconv K C 0 273.15 373.15
-273.15
0.0
100.0

My solution in Golang:

package main

import (
    "fmt"
    "os"
    "strconv"
)

type TempConv struct {
    toKelvin   func(other float64) float64
    fromKelvin func(kelvin float64) float64
}

var scales = map[string]TempConv{}

func init() {
    register := func(toKelvin func(other float64) float64, fromKelvin func(kelvin float64) float64, names []string) {
        conv := TempConv{toKelvin, fromKelvin};
        for _, name := range names {
            scales[name] = conv
        }
    }

    register(func(celsius    float64) float64 { return celsius + 273.15                 }, func(kelvin float64) float64 { return kelvin - 273.15                 }, []string{"°C", "C", "c"});
    register(func(kelvin     float64) float64 { return kelvin                           }, func(kelvin float64) float64 { return kelvin                          }, []string{"K"});
    register(func(fahrenheit float64) float64 { return (fahrenheit + 459.67) * 5 / 9    }, func(kelvin float64) float64 { return kelvin * 9 / 5 - 459.67         }, []string{"°F", "F", "f"});
    register(func(delisle    float64) float64 { return 373.15 - delisle * 2 / 3         }, func(kelvin float64) float64 { return (373.15 - kelvin) * 3 / 2       }, []string{"°De", "De", "DE", "de"});
    register(func(newton     float64) float64 { return newton*100/33 + 273.15           }, func(kelvin float64) float64 { return (kelvin - 273.15) * 33 / 100    }, []string{"°N", "N", "n"});
    register(func(rankine    float64) float64 { return rankine * 5 / 9                  }, func(kelvin float64) float64 { return kelvin * 9 / 5                  }, []string{"°R", "R", "r"});
    register(func(réaumur    float64) float64 { return réaumur * 5 / 4 + 273.15         }, func(kelvin float64) float64 { return (kelvin - 273.15) * 4 / 5       }, []string{"°Ré", "°Re", "Ré", "RÉ", "ré", "Re", "RE", "re"});
    register(func(rømer      float64) float64 { return (rømer - 7.5) * 40 / 21 + 273.15 }, func(kelvin float64) float64 { return (kelvin-273.15) * 21 / 40 + 7.5 }, []string{"°Rø", "°Ro", "Rø", "RØ", "rø", "Ro", "RO", "ro"});
}

func main() {
    toKelvin := scales[os.Args[1]].toKelvin
    fromKelvin := scales[os.Args[2]].fromKelvin
    for _, arg := range os.Args[3:] {
        inputTemp, _ := strconv.ParseFloat(arg, 64)
        fmt.Println(fromKelvin(toKelvin(inputTemp)))
    }
}

I'm aware that error handling is incomplete.

I'm particularly interested in the following feedback:

  • Is there a smarter way to initialize scales without requiring an init() function?
  • Is there a way to make the calls to register() shorter? I know golang doesn't have a terse lambda syntax with -> or => (or has it?), but maybe there's another way?
\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.