my solutions to advent of code
aoc advent-of-code
at main 2.6 kB view raw
1import gleam/io.{println} 2import gleam/list 3import gleam/result 4import gleam/string.{trim} 5import simplifile.{read} 6 7fn has_three_letter_sequence( 8 input input, 9 iterator i, 10 prev_letter_value prev_letter_value, 11 line_length line_length, 12) { 13 let letter = string.slice(input, i, 1) 14 case letter != "" { 15 False -> False 16 True -> { 17 let assert [codepoint] = string.to_utf_codepoints(letter) 18 let v = string.utf_codepoint_to_int(codepoint) 19 let in_sequence = prev_letter_value == v - 1 20 case in_sequence && line_length == 1 { 21 False -> { 22 let line_length = case in_sequence { 23 True -> line_length + 1 24 False -> 0 25 } 26 has_three_letter_sequence(input, i + 1, v, line_length) 27 } 28 True -> True 29 } 30 } 31 } 32} 33 34fn has_two_pairs(input input, iterator i, prev_letter prev_letter, pairs pairs) { 35 let letter = string.slice(input, i, 1) 36 case letter != "" { 37 False -> False 38 True -> { 39 let pair = prev_letter == letter 40 case pair { 41 False -> has_two_pairs(input, i + 1, letter, pairs) 42 True -> { 43 let pairs = pairs + 1 44 case pairs { 45 2 -> True 46 _ -> has_two_pairs(input, i + 1, "", pairs) 47 } 48 } 49 } 50 } 51 } 52} 53 54fn valid_password(input) { 55 has_three_letter_sequence(input, 1, 50, 0) 56 && ["i", "o", "l"] 57 |> list.fold_until(True, fn(_, letter) { 58 case !string.contains(input, letter) { 59 False -> list.Stop(False) 60 True -> list.Continue(True) 61 } 62 }) 63 && has_two_pairs(input, 0, "", 0) 64} 65 66fn increment_password(input) { 67 { 68 input 69 |> string.to_utf_codepoints 70 |> list.fold_right(#([], 0), fn(acc, letter) { 71 let #(acc_str, pass) = acc 72 let add = case acc_str == [] { 73 True -> 1 74 False -> pass 75 } 76 let new_letter = string.utf_codepoint_to_int(letter) + add 77 let assert Ok(letter_codepoint) = string.utf_codepoint(new_letter) 78 case new_letter > 122 { 79 True -> { 80 let assert Ok(a) = string.utf_codepoint(97) 81 #(list.prepend(acc_str, a), 1) 82 } 83 False -> #(list.prepend(acc_str, letter_codepoint), 0) 84 } 85 }) 86 }.0 87 |> string.from_utf_codepoints 88} 89 90fn get_valid_password(input) { 91 case valid_password(input) { 92 False -> get_valid_password(increment_password(input)) 93 True -> input 94 } 95} 96 97pub fn main() { 98 let input = read(from: "../input.txt") |> result.unwrap("") |> trim() 99 100 let part1 = get_valid_password(input) 101 println(part1) 102 let part2 = get_valid_password(increment_password(part1)) 103 println(part2) 104}