Skip to content

Commit

Permalink
day 05: improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
sreedevk committed Dec 5, 2024
1 parent 704859d commit 7aeb8b2
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 50 deletions.
70 changes: 20 additions & 50 deletions src/print_queue.gleam
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import gleam/bool
import gleam/int
import gleam/io
import gleam/list
import gleam/pair
import gleam/result
import gleam/string
import utils/list as listutils

type Rule =
#(Int, Int)
Expand Down Expand Up @@ -34,31 +35,9 @@ fn parse_file(input: String) -> #(List(Rule), List(Order)) {
#(parsed_rules, parsed_orders)
}

fn contains(ls: List(a), item: a) -> Bool {
result.is_ok(list.find(ls, fn(x) { x == item }))
}

fn filter_with_index(ls: List(a), f: fn(Int, a) -> Bool) -> List(a) {
list.index_map(ls, fn(item, index) { #(index, item) })
|> list.filter(fn(x) { f(pair.first(x), pair.second(x)) })
|> list.map(fn(y) { pair.second(y) })
}

fn at(ls: List(a), idx: Int) -> Result(a, Nil) {
list.index_map(ls, fn(item, index) { #(index, item) })
|> list.find(fn(x) { pair.first(x) == idx })
|> result.map(fn(res) { pair.second(res) })
}

fn rule_applicable(order: Order, rule: Rule) -> Bool {
let #(x, y) = rule
contains(order, x) && contains(order, y)
}

fn index(ls: List(a), item: a) -> Result(Int, Nil) {
list.index_map(ls, fn(x, index) { #(index, x) })
|> list.find(fn(x) { pair.second(x) == item })
|> result.map(fn(x) { pair.first(x) })
listutils.contains(order, x) && listutils.contains(order, y)
}

fn rule_satisfied(order: Order, rule: Rule) -> Bool {
Expand All @@ -74,44 +53,35 @@ fn order_follows_rules(order: Order, rules: List(Rule)) -> Bool {
|> list.all(fn(rule) { rule_satisfied(order, rule) })
}

fn rule_satisfied_or_swap(order: Order, rule: Rule) -> Order {
case rule_satisfied(order, rule) {
True -> order
False -> listutils.swap(order, pair.first(rule), pair.second(rule))
}
}

fn make_order_follow_rules(order: Order, rules: List(Rule)) -> Order {
rules
|> list.filter(rule_applicable(order, _))
|> list.fold(order, fn(oc, rule) {
case rule_satisfied(oc, rule) {
True -> oc
False -> swap(oc, pair.first(rule), pair.second(rule))
}
})
|> fn(oc) {
case order_follows_rules(oc, rules) {
True -> oc
False -> make_order_follow_rules(oc, rules)
case order_follows_rules(order, rules) {
True -> order
False -> {
list.filter(rules, rule_applicable(order, _))
|> list.fold(order, rule_satisfied_or_swap)
|> make_order_follow_rules(rules)
}
}
}

fn middle(order: Order) -> Int {
order
|> at(list.length(order) / 2)
|> listutils.at(list.length(order) / 2)
|> result.unwrap(0)
}

fn swap(ls: List(a), ea: a, eb: a) -> List(a) {
list.map(ls, fn(x) {
case x {
val if val == ea -> eb
val if val == eb -> ea
val -> val
}
})
}

pub fn solve_a(input: String) -> Int {
let #(rules, orders) = parse_file(input)

orders
|> list.filter(fn(order) { order_follows_rules(order, rules) })
|> list.filter(order_follows_rules(_, rules))
|> list.map(middle)
|> list.fold(0, int.add)
}
Expand All @@ -120,8 +90,8 @@ pub fn solve_b(input: String) -> Int {
let #(rules, orders) = parse_file(input)

orders
|> list.filter(fn(order) { !order_follows_rules(order, rules) })
|> list.map(fn(order) { make_order_follow_rules(order, rules) })
|> list.filter(fn(order) { bool.negate(order_follows_rules(order, rules)) })
|> list.map(make_order_follow_rules(_, rules))
|> list.map(middle)
|> list.fold(0, int.add)
}
35 changes: 35 additions & 0 deletions src/utils/list.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import gleam/list
import gleam/pair
import gleam/result

pub fn at(ls: List(a), idx: Int) -> Result(a, Nil) {
list.index_map(ls, fn(item, index) { #(index, item) })
|> list.find(fn(x) { pair.first(x) == idx })
|> result.map(fn(res) { pair.second(res) })
}

pub fn index(ls: List(a), item: a) -> Result(Int, Nil) {
list.index_map(ls, fn(x, index) { #(index, x) })
|> list.find(fn(x) { pair.second(x) == item })
|> result.map(fn(x) { pair.first(x) })
}

pub fn filter_with_index(ls: List(a), f: fn(Int, a) -> Bool) -> List(a) {
list.index_map(ls, fn(item, index) { #(index, item) })
|> list.filter(fn(x) { f(pair.first(x), pair.second(x)) })
|> list.map(fn(y) { pair.second(y) })
}

pub fn contains(ls: List(a), item: a) -> Bool {
result.is_ok(list.find(ls, fn(x) { x == item }))
}

pub fn swap(ls: List(a), ea: a, eb: a) -> List(a) {
list.map(ls, fn(x) {
case x {
val if val == ea -> eb
val if val == eb -> ea
val -> val
}
})
}

0 comments on commit 7aeb8b2

Please sign in to comment.