day 7
This commit is contained in:
parent
68d39d8896
commit
24bae29e6e
3 changed files with 159 additions and 0 deletions
9
sample/day7-sample.txt
Normal file
9
sample/day7-sample.txt
Normal 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
68
src/day7_p1.gleam
Normal 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
82
src/day7_p2.gleam
Normal 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) }
|
||||
}
|
Loading…
Reference in a new issue