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