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);
}