day 3
This commit is contained in:
parent
43035cf142
commit
7c03dd3d6a
4 changed files with 196 additions and 0 deletions
1
sample/day3-sample.txt
Normal file
1
sample/day3-sample.txt
Normal file
|
@ -0,0 +1 @@
|
|||
xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
|
2
sample/day3-sample2.txt
Normal file
2
sample/day3-sample2.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
|
||||
|
97
src/day3_p1.gleam
Normal file
97
src/day3_p1.gleam
Normal file
|
@ -0,0 +1,97 @@
|
|||
import gleam/int
|
||||
import gleam/io
|
||||
import gleam/iterator
|
||||
import gleam/list.{reverse, take_while}
|
||||
import gleam/option.{type Option, None, Some}
|
||||
import gleam/string.{join}
|
||||
import stdin.{stdin}
|
||||
|
||||
pub fn main() {
|
||||
stdin()
|
||||
|> read_input
|
||||
|> find_and_calculate(0)
|
||||
|> io.debug
|
||||
}
|
||||
|
||||
type FindResult {
|
||||
Expression(Int, Int, String)
|
||||
Nothing
|
||||
}
|
||||
|
||||
fn find_and_calculate(s: String, acc: Int) -> Int {
|
||||
// Drop all until first 'mul('
|
||||
let next =
|
||||
string.crop(from: s, before: "mul(")
|
||||
|> string.drop_start(up_to: 4)
|
||||
|
||||
case next {
|
||||
"" -> acc
|
||||
str -> {
|
||||
case find_expression(str) {
|
||||
Expression(a, b, rest) -> find_and_calculate(rest, acc + a * b)
|
||||
Nothing -> find_and_calculate(next, acc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_expression(str: String) -> FindResult {
|
||||
case
|
||||
str
|
||||
|> read_num
|
||||
|> then(read_char(","))
|
||||
|> then(read_num)
|
||||
|> then(read_char(")"))
|
||||
{
|
||||
Some(#(#(#(#(a, _), b), _), rest)) -> Expression(a, b, rest)
|
||||
None -> Nothing
|
||||
}
|
||||
}
|
||||
|
||||
fn read_char(char: String) {
|
||||
fn(str: String) -> Option(#(String, String)) {
|
||||
case string.pop_grapheme(str) {
|
||||
Ok(#(ch, rest)) if ch == char -> Some(#(char, rest))
|
||||
_ -> None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn then(
|
||||
current: Option(#(a, String)),
|
||||
next: fn(String) -> Option(#(b, String)),
|
||||
) -> Option(#(#(a, b), String)) {
|
||||
case current {
|
||||
None -> None
|
||||
Some(#(a, s)) ->
|
||||
next(s)
|
||||
|> option.map(fn(result) {
|
||||
let #(b, rest) = result
|
||||
#(#(a, b), rest)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const numbers = "0123456789"
|
||||
|
||||
fn read_num(str: String) -> Option(#(Int, String)) {
|
||||
let to_parse =
|
||||
str
|
||||
|> string.to_graphemes
|
||||
|> take_while(fn(c) { string.contains(does: numbers, contain: c) })
|
||||
|> join(with: "")
|
||||
|
||||
to_parse
|
||||
|> int.parse
|
||||
|> option.from_result
|
||||
|> option.map(fn(n) {
|
||||
#(n, string.drop_start(str, up_to: string.length(to_parse)))
|
||||
})
|
||||
}
|
||||
|
||||
fn read_input(it: iterator.Iterator(String)) -> String {
|
||||
it
|
||||
|> iterator.fold([], fn(acc, line) { [line, ..acc] })
|
||||
|> reverse
|
||||
|> join(with: "")
|
||||
}
|
96
src/day3_p2.gleam
Normal file
96
src/day3_p2.gleam
Normal file
|
@ -0,0 +1,96 @@
|
|||
import gleam/int
|
||||
import gleam/io
|
||||
import gleam/iterator
|
||||
import gleam/list.{reverse, take_while}
|
||||
import gleam/option.{type Option, None, Some}
|
||||
import gleam/string.{join}
|
||||
import stdin.{stdin}
|
||||
|
||||
pub fn main() {
|
||||
stdin()
|
||||
|> read_input
|
||||
|> find_and_calculate(0, can_mul: True)
|
||||
|> io.debug
|
||||
}
|
||||
|
||||
type FindResult {
|
||||
Expression(Int, Int, String)
|
||||
Nothing
|
||||
}
|
||||
|
||||
fn find_and_calculate(s: String, acc: Int, can_mul mul_enabled: Bool) -> Int {
|
||||
case s {
|
||||
"" -> acc
|
||||
"do()" <> rest -> find_and_calculate(rest, acc, can_mul: True)
|
||||
"don't()" <> rest -> find_and_calculate(rest, acc, can_mul: False)
|
||||
"mul(" <> rest if mul_enabled -> {
|
||||
case find_expression(rest) {
|
||||
Expression(a, b, rest) ->
|
||||
find_and_calculate(rest, acc + a * b, can_mul: mul_enabled)
|
||||
Nothing -> find_and_calculate(rest, acc, can_mul: mul_enabled)
|
||||
}
|
||||
}
|
||||
_ -> find_and_calculate(string.drop_start(s, 1), acc, can_mul: mul_enabled)
|
||||
}
|
||||
}
|
||||
|
||||
fn find_expression(str: String) -> FindResult {
|
||||
case
|
||||
str
|
||||
|> read_num
|
||||
|> then(read_char(","))
|
||||
|> then(read_num)
|
||||
|> then(read_char(")"))
|
||||
{
|
||||
Some(#(#(#(#(a, _), b), _), rest)) -> Expression(a, b, rest)
|
||||
None -> Nothing
|
||||
}
|
||||
}
|
||||
|
||||
fn read_char(char: String) {
|
||||
fn(str: String) -> Option(#(String, String)) {
|
||||
case string.pop_grapheme(str) {
|
||||
Ok(#(ch, rest)) if ch == char -> Some(#(char, rest))
|
||||
_ -> None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn then(
|
||||
current: Option(#(a, String)),
|
||||
next: fn(String) -> Option(#(b, String)),
|
||||
) -> Option(#(#(a, b), String)) {
|
||||
case current {
|
||||
None -> None
|
||||
Some(#(a, s)) ->
|
||||
next(s)
|
||||
|> option.map(fn(result) {
|
||||
let #(b, rest) = result
|
||||
#(#(a, b), rest)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const numbers = "0123456789"
|
||||
|
||||
fn read_num(str: String) -> Option(#(Int, String)) {
|
||||
let to_parse =
|
||||
str
|
||||
|> string.to_graphemes
|
||||
|> take_while(fn(c) { string.contains(does: numbers, contain: c) })
|
||||
|> join(with: "")
|
||||
|
||||
to_parse
|
||||
|> int.parse
|
||||
|> option.from_result
|
||||
|> option.map(fn(n) {
|
||||
#(n, string.drop_start(str, up_to: string.length(to_parse)))
|
||||
})
|
||||
}
|
||||
|
||||
fn read_input(it: iterator.Iterator(String)) -> String {
|
||||
it
|
||||
|> iterator.fold([], fn(acc, line) { [line, ..acc] })
|
||||
|> reverse
|
||||
|> join(with: "")
|
||||
}
|
Loading…
Reference in a new issue