Repository navigation
Expand file tree
/
Copy pathInputParser.kt
More file actions
59 lines (52 loc) · 2.01 KB
/
Copy pathInputParser.kt
File metadata and controls
59 lines (52 loc) · 2.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package calculator.model.input
object InputParser {
const val NON_NUMERIC_DEFAULT_VALUE = -1
private val DEFAULT_DELIMITERS = arrayOf(",", ":")
private val customDelimiterRegex: Regex by lazy {
Regex("//(.)\n(.*)")
}
private val nonNumericCharacterRegex: Regex by lazy {
Regex("-?\\d+")
}
fun parse(input: String?): List<Int> {
if (input.isNullOrEmpty()) return listOf(0)
val (customDelimiter, numberInput) = extractDelimiterAndNumbers(input)
val delimiters = combineDelimiters(customDelimiter)
val tokens = splitInputByDelimiters(numberInput, delimiters)
val numbers = parseNonNegativeNumbers(tokens)
val nonNumeric = extractNonNumericCharacters(numberInput)
InputValidator.validateDelimiters(nonNumeric, delimiters)
InputValidator.validateNumbers(numbers)
return numbers
}
private fun extractDelimiterAndNumbers(input: String): DelimiterAndNumbers {
val result = customDelimiterRegex.find(input)
return if (result != null) {
val customDelimiter = result.groupValues[1]
val numbers = result.groupValues[2]
DelimiterAndNumbers(customDelimiter, numbers)
} else {
DelimiterAndNumbers(null, input)
}
}
private fun combineDelimiters(customDelimiter: String?): Array<String> {
return mutableListOf(*DEFAULT_DELIMITERS).apply {
customDelimiter?.let(::add)
}.toTypedArray()
}
private fun splitInputByDelimiters(
numberInput: String,
delimiters: Array<String>,
): List<String> {
return numberInput.split(*delimiters)
}
private fun parseNonNegativeNumbers(tokens: List<String>): List<Int> {
return tokens.map { token ->
token.toIntOrNull() ?: NON_NUMERIC_DEFAULT_VALUE
}
}
private fun extractNonNumericCharacters(input: String): List<String> {
return input.replace(nonNumericCharacterRegex, "").trim()
.map { "$it" }
}
}