app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br", } import pf.Stdout import "data.txt" as data : Str 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" |> Str.toU32 |> Result.isOk toDigit = \u8s -> Str.fromUtf8 u8s |> Result.withDefault "0" |> Str.toU32 |> Result.withDefault 0 fromVal = \val -> when val is Val x -> x Null -> 0