day07.nim (2285B)
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 concat, filter, foldl, map, mapIt, toSeq 16 from std/strutils import parseInt, split, splitWhitespace 17 18 # Read input file 19 20 func parse_line(l: string): seq[int] = 21 let halves = l.split(": ") 22 assert len(halves) == 2 23 result = concat(@[parseInt(halves[0])], halves[1].splitWhitespace().map(parseInt)) 24 25 let data = stdin.lines().toSeq().map(parse_line) 26 27 # First puzzle 28 # 354 is too low 29 # 465092164034 is too low 30 31 func is_good(target, acc: int, terms: seq[int]): bool = 32 if len(terms) == 0: 33 result = acc == target 34 elif acc > target: 35 result = false 36 else: 37 result = is_good(target, acc * terms[0], terms[1 .. ^1]) or 38 is_good(target, acc + terms[0], terms[1 .. ^1]) 39 40 func line_is_good(l: seq[int]): bool = 41 is_good(l[0], l[1], l[2 .. ^1]) 42 43 echo "Puzzle 1: ", data.filter(line_is_good).mapIt(it[0]).foldl(a + b) 44 45 # Second puzzle 46 # 54566744875618 is too low 47 # 68296976306294 is too low 48 49 func int_cat(a, b: int): int = 50 var f = 10 51 while f <= b: 52 f *= 10 53 result = a * f + b 54 55 func is_good2(target, acc: int, terms: seq[int]): bool = 56 if len(terms) == 0: 57 result = acc == target 58 elif acc > target: 59 result = false 60 else: 61 result = is_good2(target, int_cat(acc, terms[0]), terms[1 .. ^1]) or 62 is_good2(target, acc * terms[0], terms[1 .. ^1]) or 63 is_good2(target, acc + terms[0], terms[1 .. ^1]) 64 65 func line_is_good2(l: seq[int]): bool = 66 is_good2(l[0], l[1], l[2 .. ^1]) 67 68 echo "Puzzle 2: ", data.filter(line_is_good2).mapIt(it[0]).foldl(a + b)