Day 6: Trash Compactor ## Megathread guidelines - Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever) - You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL ## FAQ - What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268 - Where do I participate?: https://adventofcode.com/ - Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
You must log in or register to comment.
Nim
The hardest part was reading the part 2 description. I literally looked at it for minutes trying to understand where the problem numbers come from and how they’re related to the example input. But then it clicked.
The next roadblock was that my template was stripping whitespace at the end of the last line, making parsing a lot harder. I’ve replaced
strip()withstrip(chars={'\n'})to keep the trailing space intact.Runtime:
1.4 ms618 μsview code
type AOCSolution[T,U] = tuple[part1: T, part2: U] proc solve(input: string): AOCSolution[int, int] = let lines = input.splitLines() let numbers = lines[0..^2] let ops = lines[^1] block p1: let numbers = numbers.mapIt(it.splitWhiteSpace().mapIt(parseInt it)) let ops = ops.splitWhitespace() for x in 0 .. numbers[0].high: var res = numbers[0][x] for y in 1 .. numbers.high: case ops[x] of "*": res *= numbers[y][x] of "+": res += numbers[y][x] result.part1 += res block p2: var problems: seq[(char, Slice[int])] var ind = 0 while ind < ops.len: let len = ops.skipWhile({' '}, ind+1) problems.add (ops[ind], ind .. ind + len - (if ind+len < ops.high: 1 else: 0)) ind += len + 1 for (op, cols) in problems: var res = 0 for x in cols: var num = "" for y in 0 .. numbers.high: num &= numbers[y][x] if res == 0: res = parseInt num.strip else: case op of '*': res *= parseInt num.strip of '+': res += parseInt num.strip else: discard result.part2 += resFull solution at Codeberg: solution.nim
C
Well so much for reading a grid of ints in part 1! For part 2, initially I reworked the parsing to read into a big buffer, but then thought it would be fun to try and use memory-mapped I/O as not to use any more memory than strictly necessary for the final version:
Code
#include <stdio.h> #include <stdlib.h> #include <inttypes.h> #include <ctype.h> #include <assert.h> #include <sys/mman.h> #include <unistd.h> #include <err.h> #define GH 5 int main() { char *data, *g[GH], *p; uint64_t p1=0,p2=0, acc; int len, h=0, i, x,y, val; char op; if ((len = (int)lseek(0, 0, SEEK_END)) == -1) err(1, "<stdin>"); if (!(data = mmap(NULL, len, PROT_READ, MAP_SHARED, 0, 0))) err(1, "<stdin>"); for (i=0; i<len; i++) if (!i || data[i-1]=='\n') { assert(h < GH); g[h++] = data+i; } for (x=0; g[h-1]+x < data+len; x++) { if ((op = g[h-1][x]) != '+' && op != '*') continue; for (acc = op=='*', y=0; y<h-1; y++) { val = atoi(&g[y][x]); acc = op=='+' ? acc+val : acc*val; } p1 += acc; for (acc = op=='*', i=0; ; i++) { for (val=0, y=0; y<h-1; y++) { p = &g[y][x+i]; if (p < g[y+1] && isdigit(*p)) val = val*10 + *p-'0'; } if (!val) break; acc = op=='+' ? acc+val : acc*val; } p2 += acc; } printf("06: %"PRIu64" %"PRIu64"\n", p1, p2); }

