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 KelvinC
for CelsiusF
for FahrenheitR
for RankineD
for DelisleN
for NewtonRø
for RømerRé
for Réaumur.
Example:
tempconv K C 0 273.15 373.15
-273.15
0.0
100.0
My solution in Kotlin:
enum class TemperatureConverter(
val toKelvin: (Double) -> Double,
val fromKelvin: (Double) -> Double,
vararg val names: String,
) {
KELVIN ({kelvin -> kelvin }, {kelvin -> kelvin }, "K", "k"),
CELSIUS ({celsius -> celsius + 273.15 }, {kelvin -> kelvin - 273.15 }, "°C", "C", "c"),
DELISLE ({delisle -> 373.15 - delisle * 2 / 3 }, {kelvin -> (373.15 - kelvin) * 3 / 2 }, "°De", "De", "DE", "de"),
FAHRENHEIT({fahrenheit -> (fahrenheit + 459.67) * 5 / 9 }, {kelvin -> kelvin * 9 / 5 - 459.67 }, "°F", "F", "f"),
NEWTON ({newton -> newton * 100 / 33 + 273.15 }, {kelvin -> (kelvin - 273.15) * 33 / 100 }, "°N", "N", "n"),
RANKINE ({rankine -> rankine * 5 / 9 }, {kelvin -> kelvin * 9 / 5 }, "°R", "R", "r"),
RÉAUMUR ({réaumur -> réaumur * 5 / 4 + 273.15 }, {kelvin -> (kelvin - 273.15) * 4 / 5 }, "°Ré", "°Re", "Ré", "RÉ", "ré", "Re", "RE", "re"),
RØMER ({rømer -> (rømer - 7.5) * 40 / 21 + 273.15}, {kelvin -> (kelvin - 273.15) * 21 / 40 + 7.5}, "°Rø", "°Ro", "Rø", "RØ", "rø", "Ro", "RO", "ro"),
;
companion object {
@JvmStatic
private val converters = values()
.asSequence()
.flatMap { it.names.asSequence().map { name -> name to it }}
.toMap()
operator fun get(name: String) = converters[name]!!
}
}
fun main(vararg args: String) {
val toKelvin = TemperatureConverter[args[0]].toKelvin
val fromKelvin = TemperatureConverter[args[1]].fromKelvin
args
.asSequence()
.drop(2)
.map(String::toDouble)
.map(toKelvin)
.map(fromKelvin)
.forEach { println(it) }
}
Note: I'm aware that the lines defining the enum are a bit long. I'm okay with sacrificing a bit of line length for retaining a tabular format in this case.
I'm aware that error handling will dump exceptions to the user. I'm ok with that, this is not central to the design.