aoc-all

My solutions to all Advent of Code
git clone https://git.instinctive.eu/aoc-all.git
Log | Files | Refs | README | LICENSE

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)