|
|
|
@ -9,6 +9,40 @@ main =
|
|
|
|
|
Stdout.line! "Part 1: $(Num.toStr (run data 1))"
|
|
|
|
|
Stdout.line! "Part 2: $(Num.toStr (run data 2))"
|
|
|
|
|
|
|
|
|
|
run = \code, part ->
|
|
|
|
|
Str.walkUtf8 code { digits: [], chars: [], curNum: [], firstNum: Null, enabled: Bool.true } \state, elem ->
|
|
|
|
|
isEnabled = state.enabled || part == 1
|
|
|
|
|
previousChar = Result.withDefault (List.last state.chars) 0
|
|
|
|
|
|
|
|
|
|
when elem is
|
|
|
|
|
'd' -> { state & chars: ['d'] }
|
|
|
|
|
'o' if state.chars == ['d'] -> { state & chars: List.append state.chars 'o' }
|
|
|
|
|
'(' if state.chars == ['d', 'o'] -> { state & chars: List.append state.chars '(' }
|
|
|
|
|
')' if state.chars == ['d', 'o', '('] -> { state & enabled: Bool.true }
|
|
|
|
|
|
|
|
|
|
'n' if state.chars == ['d', 'o'] -> { state & chars: List.append state.chars 'n' }
|
|
|
|
|
'\'' if state.chars == ['d', 'o', 'n'] -> { state & chars: List.append state.chars '\'' }
|
|
|
|
|
't' if state.chars == ['d', 'o', 'n', '\''] -> { state & chars: List.append state.chars 't' }
|
|
|
|
|
'(' if state.chars == ['d', 'o', 'n', '\'', 't'] -> { state & chars: List.append state.chars '(' }
|
|
|
|
|
')' if state.chars == ['d', 'o', 'n', '\'', 't', '('] -> { state & enabled: Bool.false }
|
|
|
|
|
|
|
|
|
|
_ if !isEnabled -> state
|
|
|
|
|
|
|
|
|
|
'm' -> { state & chars: ['m'], curNum: [], firstNum: Null }
|
|
|
|
|
'u' if state.chars == ['m'] -> { state & chars: List.append state.chars 'u' }
|
|
|
|
|
'l' if state.chars == ['m', 'u'] -> { state & chars: List.append state.chars 'l' }
|
|
|
|
|
'(' if state.chars == ['m', 'u', 'l'] -> { state & chars: List.append state.chars '(' }
|
|
|
|
|
|
|
|
|
|
d if state.chars == ['m', 'u', 'l', '('] && isDigit d -> { state & chars: List.append state.chars d, curNum: [d] }
|
|
|
|
|
d if isDigit d && isDigit previousChar -> { state & chars: List.append state.chars d, curNum: List.append state.curNum d }
|
|
|
|
|
d if isDigit d && previousChar == ',' -> { state & chars: List.append state.chars d, curNum: [d] }
|
|
|
|
|
|
|
|
|
|
',' if isDigit previousChar && state.firstNum == Null -> { state & chars: List.append state.chars ',', curNum: [], firstNum: Val (toDigit state.curNum) }
|
|
|
|
|
')' if isDigit previousChar && state.firstNum != Null -> { state & curNum: [], digits: List.append state.digits (fromVal state.firstNum, toDigit state.curNum) }
|
|
|
|
|
_ -> { state & chars: [], curNum: [], firstNum: Null } # didn't match, blank it out
|
|
|
|
|
|> .digits
|
|
|
|
|
|> List.walk 0 \sum, (l, r) -> sum + l * r
|
|
|
|
|
|
|
|
|
|
isDigit = \char ->
|
|
|
|
|
Str.fromUtf8 [char]
|
|
|
|
|
|> Result.withDefault "0"
|
|
|
|
@ -25,49 +59,3 @@ fromVal = \val ->
|
|
|
|
|
when val is
|
|
|
|
|
Val x -> x
|
|
|
|
|
Null -> 0
|
|
|
|
|
|
|
|
|
|
run = \code, part ->
|
|
|
|
|
Str.walkUtf8 code { digits: [], chars: [], curNum: [], firstNum: Null, enabled: Bool.true } \state, elem ->
|
|
|
|
|
isEnabled = state.enabled || part == 1
|
|
|
|
|
previousChar = Result.withDefault (List.last state.chars) 0
|
|
|
|
|
|
|
|
|
|
when elem is
|
|
|
|
|
'd' -> { state & chars: ['d'] }
|
|
|
|
|
'o' if state.chars == ['d'] -> { state & chars: List.append state.chars 'o' }
|
|
|
|
|
'(' if state.chars == ['d', 'o'] -> { state & chars: List.append state.chars '(' }
|
|
|
|
|
')' if state.chars == ['d', 'o', '('] -> { state & enabled: Bool.true }
|
|
|
|
|
|
|
|
|
|
'n' if state.chars == ['d', 'o'] -> { state & chars: List.append state.chars 'n' }
|
|
|
|
|
'\'' if state.chars == ['d', 'o', 'n'] -> { state & chars: List.append state.chars '\'' }
|
|
|
|
|
't' if state.chars == ['d', 'o', 'n', '\''] -> { state & chars: List.append state.chars 't' }
|
|
|
|
|
'(' if state.chars == ['d', 'o', 'n', '\'', 't'] -> { state & chars: List.append state.chars '(' }
|
|
|
|
|
')' if state.chars == ['d', 'o', 'n', '\'', 't', '('] -> { state & enabled: Bool.false }
|
|
|
|
|
|
|
|
|
|
_ if !isEnabled -> state
|
|
|
|
|
|
|
|
|
|
'm' -> { state & chars: ['m'], curNum: [], firstNum: Null }
|
|
|
|
|
'u' if state.chars == ['m'] -> { state & chars: List.append state.chars 'u' }
|
|
|
|
|
'l' if state.chars == ['m', 'u'] -> { state & chars: List.append state.chars 'l' }
|
|
|
|
|
'(' if state.chars == ['m', 'u', 'l'] -> { state & chars: List.append state.chars '(' }
|
|
|
|
|
|
|
|
|
|
d if isDigit d && state.chars == ['m', 'u', 'l', '('] -> { state & curNum: [d], chars: List.append state.chars d }
|
|
|
|
|
d if isDigit d && isDigit previousChar -> { state & curNum: List.append state.curNum d, chars: List.append state.chars d }
|
|
|
|
|
d if isDigit d && previousChar == ',' -> { state & curNum: [d], chars: List.append state.chars d }
|
|
|
|
|
|
|
|
|
|
',' if isDigit previousChar && state.firstNum == Null -> {
|
|
|
|
|
state &
|
|
|
|
|
chars: List.append state.chars ',',
|
|
|
|
|
curNum: [],
|
|
|
|
|
firstNum: Val (toDigit state.curNum)
|
|
|
|
|
}
|
|
|
|
|
')' if isDigit previousChar && state.firstNum != Null -> {
|
|
|
|
|
state &
|
|
|
|
|
chars: List.append state.chars ')',
|
|
|
|
|
curNum: [],
|
|
|
|
|
firstNum: Null,
|
|
|
|
|
digits: List.append state.digits (fromVal state.firstNum, toDigit state.curNum)
|
|
|
|
|
}
|
|
|
|
|
_ -> { state & chars: [], curNum: [], firstNum: Null } # didn't match, blank it out
|
|
|
|
|
|
|
|
|
|
|> .digits
|
|
|
|
|
|> List.walk 0 \sum, (l, r) -> sum + l * r
|
|
|
|
|