Created
April 28, 2020 19:07
-
-
Save ygrenzinger/df5e1e9cdc341ed6d16f663499d130c2 to your computer and use it in GitHub Desktop.
Unit Converter exercise on Jetbrain academy
This file contains 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
Enter what you want to convert (or exit): 1 degree Celsius to Kelvins | |
1.0 degree Celsius is 274.15 Kelvins | |
Enter what you want to convert (or exit): -272.15 dc to K | |
-272.15 degrees Celsius is 1.0 Kelvin | |
Enter what you want to convert (or exit): 1 kn to feet | |
Conversion from ??? to feet is impossible | |
Enter what you want to convert (or exit): 1 km to feet | |
1.0 kilometer is 3280.839895013123 feet | |
Enter what you want to convert (or exit): 3 pount to ounces | |
Conversion from ??? to ounces is impossible | |
Enter what you want to convert (or exit): 3 pound to ounces | |
3.0 pounds is 47.99999999999999 ounces | |
Enter what you want to convert (or exit): 3 kelvins to grams | |
Conversion from Kelvins to grams is impossible | |
Enter what you want to convert (or exit): 3 grams to meters | |
Conversion from grams to meters is impossible | |
Enter what you want to convert (or exit): exit | |
Enter what you want to convert (or exit): 1 F in K | |
1.0 degree Fahrenheit is 255.92777777777778 Kelvins | |
Enter what you want to convert (or exit): 1 K in F | |
1.0 Kelvin is -457.87 degrees Fahrenheit | |
Enter what you want to convert (or exit): 1 C in K | |
1.0 degree Celsius is 274.15 Kelvins | |
Enter what you want to convert (or exit): 1 K in C | |
1.0 Kelvin is -272.15 degrees Celsius | |
Enter what you want to convert (or exit): 1 F in C | |
1.0 degree Fahrenheit is -17.22222222222222 degrees Celsius | |
Enter what you want to convert (or exit): 1 C in F | |
1.0 degree Celsius is 33.8 degrees Fahrenheit | |
Enter what you want to convert (or exit): one boa in parrots | |
Parse error | |
Enter what you want to convert (or exit): please convert distance to the Moon to steps | |
Parse error | |
Enter what you want to convert (or exit): many things to improve! | |
Parse error | |
Enter what you want to convert (or exit): exit |
This file contains 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
package converter | |
import java.util.* | |
interface Unit { | |
fun label(): String | |
fun type(): String | |
fun <T : Unit> conversionMessage(x: Double, destination: T): String | |
fun conversionMessage(x: Double, destination: String): String { | |
return findUnit(destination)?.let { | |
return if (this.type() == it.type()) { | |
conversionMessage(x, it) | |
} else { | |
"Conversion from ${this.label()} to ${it.label()} is impossible" | |
} | |
} ?: "Conversion from ${this.label()} to ??? is impossible" | |
} | |
companion object { | |
fun findUnit(unit: String): Unit? = UnitOfLength.toUnit[unit] as Unit? | |
?: UnitOfWeight.toUnit[unit] as Unit? | |
?: UnitOfTemperature.toUnit[unit] as Unit? | |
fun conversionMessage(x: Double, origin: String, destination: String): String { | |
return findUnit(origin)?.let { | |
return it.conversionMessage(x, destination) | |
} ?: findUnit(destination)?.let { | |
"Conversion from ??? to ${it.label()} is impossible" | |
} ?: "Conversion from ??? to ??? is impossible" | |
} | |
} | |
} | |
interface SimpleUnit : Unit { | |
val abbr: String | |
val singular: String | |
val plural: String | |
val ratio: Double | |
fun labelFor(x: Double) = if (x == 1.0) { | |
singular | |
} else { | |
plural | |
} | |
override fun label() = plural | |
override fun <T : Unit> conversionMessage(x: Double, destination: T): String { | |
return this.conversionMessage(x, destination as SimpleUnit) | |
} | |
fun conversionMessage(x: Double, destination: SimpleUnit): String { | |
if (x < 0) return "${this.type()} shouldn't be negative." | |
val c = (x * this.ratio) / destination.ratio | |
return "$x ${this.labelFor(x)} is $c ${destination.labelFor(c)}" | |
} | |
} | |
enum class UnitOfLength(override val abbr: String, override val singular: String, override val plural: String, override val ratio: Double) : SimpleUnit { | |
METER("m", "meter", "meters", 1.0), | |
KILOMETER("km", "kilometer", "kilometers", 1000.0), | |
CENTIMETER("cm", "centimeter", "centimeters", 0.01), | |
MILLIMETER("mm", "millimeter", "millimeters", 0.001), | |
MILE("mi", "mile", "miles", 1609.35), | |
YARD("yd", "yard", "yards", 0.9144), | |
FOOT("ft", "foot", "feet", 0.3048), | |
INCH("in", "inch", "inches", 0.0254); | |
override fun type() = "Length" | |
companion object { | |
val toUnit: Map<String, UnitOfLength> = values() | |
.flatMap { u -> listOf(u.abbr to u, u.singular to u, u.plural to u) } | |
.toMap() | |
} | |
} | |
enum class UnitOfWeight(override val abbr: String, override val singular: String, override val plural: String, override val ratio: Double) : SimpleUnit { | |
GRAM("g", "gram", "grams", 1.0), | |
KILOGRAM("kg", "kilogram", "kilograms", 1000.0), | |
MILLIGRAM("mg", "milligram", "milligrams", 0.001), | |
POUND("lb", "pound", "pounds", 453.592), | |
OUNCE("oz", "ounce", "ounces", 28.3495); | |
override fun type() = "Weight" | |
override fun labelFor(x: Double) = if (x == 1.0) { | |
singular | |
} else { | |
plural | |
} | |
companion object { | |
val toUnit: Map<String, UnitOfWeight> = values() | |
.flatMap { u -> listOf(u.abbr to u, u.singular to u, u.plural to u) } | |
.toMap() | |
} | |
} | |
enum class UnitOfTemperature(val names: List<String>, val convert: (Double, UnitOfTemperature) -> Double) : Unit { | |
CELSIUS(listOf("degree Celsius", "degrees Celsius", "celsius", "dc", "c"), | |
{ x, unit -> | |
when (unit) { | |
CELSIUS -> x | |
FAHRENHEIT -> (x * 9.0) / 5.0 + 32.0 | |
KELVINS -> x + 273.15 | |
} | |
}) { | |
override fun label() = "degrees Celsius" | |
}, | |
FAHRENHEIT(listOf("degree Fahrenheit", "degrees Fahrenheit", "fahrenheit", "df", "f"), | |
{ x, unit -> | |
when (unit) { | |
CELSIUS -> (x - 32.0) * (5.0 / 9.0) | |
FAHRENHEIT -> x | |
KELVINS -> (x + 459.67) * (5.0 / 9.0) | |
} | |
}) { | |
override fun label() = "degrees Fahrenheit" | |
}, | |
KELVINS(listOf("Kelvin", "Kelvins", "k"), | |
{ x, unit -> | |
when (unit) { | |
CELSIUS -> x - 273.15 | |
FAHRENHEIT -> (x * 9.0) / 5.0 - 459.67 | |
KELVINS -> x | |
} | |
}) { | |
override fun label() = "Kelvins" | |
}; | |
override fun type() = "Temperature" | |
private fun labelFor(x: Double) = if (x == 1.0) { | |
names[0] | |
} else { | |
names[1] | |
} | |
override fun <T : Unit> conversionMessage(x: Double, destination: T): String { | |
return this.conversionMessage(x, destination as UnitOfTemperature) | |
} | |
private fun conversionMessage(x: Double, destination: UnitOfTemperature): String { | |
val c = this.convert(x, destination) | |
return "$x ${labelFor(x)} is $c ${destination.labelFor(c)}" | |
} | |
companion object { | |
val toUnit: Map<String, UnitOfTemperature> = values() | |
.flatMap { u -> u.names.map { it.toLowerCase() to u } } | |
.toMap() | |
} | |
} | |
fun parseAndConvert(line: String): String { | |
val regex = """(-?[0-9]+(\.?[0-9]+)?)\s((degree\s|degrees\s)?[a-zA-Z]+)\s([a-zA-Z]+)\s(.+)""".toRegex() | |
val matchResult: MatchResult = regex.find(line) ?: return "parse error" | |
val value = matchResult.groupValues[1].toDouble() | |
val origin = matchResult.groupValues[3] | |
val destination = matchResult.groupValues[6] | |
return Unit.conversionMessage(value, origin, destination) | |
} | |
private fun promptUnitOfLength(scanner: Scanner) { | |
do { | |
print("Enter what you want to convert (or exit): ") | |
val line = scanner.nextLine() | |
if (line.isBlank()) { | |
continue | |
} | |
if (line == "exit") { | |
break | |
} | |
val result = parseAndConvert(line.toLowerCase()) | |
println(result) | |
} while (true) | |
} | |
fun main() { | |
val scanner = Scanner(System.`in`) | |
promptUnitOfLength(scanner) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment