diff --git a/day3/main.roc b/day3/main.roc index 9ef65ad..7dd8310 100644 --- a/day3/main.roc +++ b/day3/main.roc @@ -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