day05.nim (2296B)
1 # Copyright (c) 2024, Natacha Porté 2 # 3 # Permission to use, copy, modify, and distribute this software for any 4 # purpose with or without fee is hereby granted, provided that the above 5 # copyright notice and this permission notice appear in all copies. 6 # 7 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 15 from std/sequtils import allIt, count, deduplicate, filterIt, foldl, map, mapIt, toSeq, concat 16 from std/strutils import parseInt, split 17 18 # Read input file 19 20 func process_input(s: seq[string], sep: string): seq[seq[int]] = 21 s.mapIt(it.split(sep)).filterIt(it.len() >= 2).mapIt(it.map(parseInt)) 22 23 func listmax(s: seq[int]): int = s.foldl(max(a, b)) 24 func listmin(s: seq[int]): int = s.foldl(min(a, b)) 25 26 let 27 raw_data = stdin.lines().toSeq() 28 part1 = process_input(raw_data, "|") 29 part2 = process_input(raw_data, ",") 30 smallest = min(part1.map(listmin).listmin(), part2.map(listmin).listmin()) 31 largest = max(part1.map(listmax).listmax(), part2.map(listmax).listmax()) 32 33 # Puzzle 1 34 35 var needs: seq[seq[int]] 36 37 for i in 0 .. largest: 38 needs.add(part1.filterIt(it[1] == i).mapIt(it[0])) 39 40 proc is_ordered(s: seq[int]): bool = 41 len(s) < 2 or 42 (s[1 .. ^1].allIt(needs[s[0]].count(it) == 0) and is_ordered(s[1 .. ^1])) 43 44 proc score1(s: seq[int]): int = 45 if is_ordered(s): 46 result = s[(len(s)-1) div 2] 47 48 echo "Puzzle 1: ", part2.map(score1).foldl(a + b) 49 50 # Puzzle 2 51 52 proc local_min(s: seq[int]): int = 53 result = -1 54 for i in 0 ..< len(s): 55 if s.allIt(needs[s[i]].count(it) == 0): 56 return s[i] 57 58 proc local_sort(s: seq[int]): seq[int] = 59 if len(s) < 2: 60 return s 61 else: 62 let m = local_min(s) 63 result = local_sort(s.filterIt(it != m)) 64 result.add(m) 65 66 proc score2(s: seq[int]): int = 67 if not is_ordered(s): 68 let s2 = local_sort(s) 69 result = s2[(len(s2) - 1) div 2] 70 71 echo "Puzzle 2: ", part2.map(score2).foldl(a + b)