day22.nim (2148B)
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 foldl, map, mapIt, toSeq, zip 16 from std/strutils import parseInt 17 from std/tables import `[]`, `[]=`, getOrDefault, hasKey, pairs, Table 18 19 # Read input file 20 21 let data = stdin.lines().toSeq().map(parseInt) 22 23 # Puzzle 1 24 25 func step(n: int): int = 26 let 27 s1 = ((n * 64) xor n) mod 16777216 28 s2 = ((s1 div 32) xor s1) mod 16777216 29 s3 = ((s2 * 2048) xor s2) mod 16777216 30 result = s3 31 32 let test_data = @[123, 15887950, 16495136, 527345, 704524, 1553684, 12683156, 11100544, 12249484, 7753432, 5908254] 33 34 for (a,b) in zip(test_data[0 .. ^2], test_data[1 .. ^1]): 35 assert step(a) == b 36 37 func steps(n, s: int): int = 38 result = n 39 for i in 1 .. s: 40 result = step(result) 41 42 echo "Puzzle 1: ", data.mapIt(steps(it, 2000)).foldl(a + b) 43 44 # Puzzle 2 45 46 var scores: Table[seq[int], int] 47 var max_score = 0 48 49 for seed in data: 50 let 51 s1 = step(seed) 52 s2 = step(s1) 53 s3 = step(s2) 54 var 55 last = s3 56 d = @[0, (s1 mod 10) - (seed mod 10), (s2 mod 10) - (s1 mod 10), (s3 mod 10) - (s2 mod 10)] 57 58 var seen: Table[seq[int], bool] 59 for i in 4 .. 2000: 60 let next = step(last) 61 d = d[1 .. ^1] 62 d.add((next mod 10) - (last mod 10)) 63 if not seen.hasKey(d): 64 seen[d] = true 65 let new_score = scores.getOrDefault(d, 0) + (next mod 10) 66 scores[d] = new_score 67 max_score = max(max_score, new_score) 68 last = next 69 70 echo "Puzzle 2: ", max_score