This commit is contained in:
Hamcha 2024-12-07 18:56:32 +01:00
parent 68d39d8896
commit 24bae29e6e
Signed by: hamcha
GPG key ID: 1669C533B8CF6D89
3 changed files with 159 additions and 0 deletions

9
sample/day7-sample.txt Normal file
View file

@ -0,0 +1,9 @@
190: 10 19
3267: 81 40 27
83: 17 5
156: 15 6
7290: 6 8 6 15
161011: 16 10 13
192: 17 8 14
21037: 9 7 18 13
292: 11 6 16 20

68
src/day7_p1.gleam Normal file
View file

@ -0,0 +1,68 @@
import gleam/int
import gleam/io
import gleam/iterator
import gleam/list.{Continue, Stop, count, filter, fold, map}
import gleam/pair
import gleam/result
import gleam/string
import stdin.{stdin}
pub fn main() {
stdin()
|> read_input
|> filter(is_valid)
|> map(pair.first)
|> fold(0, int.add)
|> io.debug
}
fn is_valid(equation: #(Int, List(Int))) -> Bool {
let assert #(total, [base, ..operands]) = equation
let op_size = list.length(operands)
let limit = int.bitwise_shift_left(1, op_size)
list.range(0, limit)
|> list.any(fn(index) {
let operations =
index
|> int.to_base2
|> string.pad_start(to: op_size, with: "0")
|> string.to_graphemes
list.zip(operands, operations)
|> list.fold(base, fn(acc, op) {
let #(num, operation) = op
case operation {
"0" -> acc + num
"1" -> acc * num
_ -> panic as "unreachable"
}
})
|> fn(x) { x == total }
})
}
fn read_input(it: iterator.Iterator(String)) -> List(#(Int, List(Int))) {
it
|> iterator.to_list
|> map(string.trim)
|> filter(not(string.is_empty))
|> map(parse_line)
}
fn parse_line(line: String) -> #(Int, List(Int)) {
let assert Ok(#(total_str, ops_str)) = line |> string.split_once(":")
let assert Ok(total) = total_str |> int.parse
let assert Ok(ops) =
ops_str
|> string.trim
|> string.split(" ")
|> map(int.parse)
|> result.all
#(total, ops)
}
fn not(a: fn(a) -> Bool) {
fn(param: a) -> Bool { !a(param) }
}

82
src/day7_p2.gleam Normal file
View file

@ -0,0 +1,82 @@
import gleam/float
import gleam/int
import gleam/io
import gleam/iterator
import gleam/list.{Continue, Stop, count, filter, fold, map}
import gleam/pair
import gleam/result
import gleam/string
import stdin.{stdin}
pub fn main() {
stdin()
|> read_input
|> filter(is_valid)
|> map(pair.first)
|> fold(0, int.add)
|> io.debug
}
fn is_valid(equation: #(Int, List(Int))) -> Bool {
let assert #(total, [base, ..operands]) = equation
let op_size = list.length(operands)
let assert Ok(limit) =
int.power(3, of: op_size |> int.to_float) |> result.map(float.round)
list.range(0, limit)
|> list.any(fn(index) {
let assert Ok(operation_string) =
index
|> int.to_base_string(3)
let operations =
operation_string
|> string.pad_start(to: op_size, with: "0")
|> string.to_graphemes
list.zip(operands, operations)
|> list.fold(base, fn(acc, op) {
let #(num, operation) = op
case operation {
"0" -> acc + num
"1" -> acc * num
"2" -> concat(acc, num)
_ -> panic as "unreachable"
}
})
|> fn(x) { x == total }
})
}
fn concat(x: Int, y: Int) -> Int {
let assert Ok(x_digits) = int.digits(x, 10)
let assert Ok(y_digits) = int.digits(y, 10)
let assert Ok(num) = [x_digits, y_digits] |> list.flatten |> int.undigits(10)
num
}
fn read_input(it: iterator.Iterator(String)) -> List(#(Int, List(Int))) {
it
|> iterator.to_list
|> map(string.trim)
|> filter(not(string.is_empty))
|> map(parse_line)
}
fn parse_line(line: String) -> #(Int, List(Int)) {
let assert Ok(#(total_str, ops_str)) = line |> string.split_once(":")
let assert Ok(total) = total_str |> int.parse
let assert Ok(ops) =
ops_str
|> string.trim
|> string.split(" ")
|> map(int.parse)
|> result.all
#(total, ops)
}
fn not(a: fn(a) -> Bool) {
fn(param: a) -> Bool { !a(param) }
}