Skip to content
Snippets Groups Projects
Verified Commit 7f6fb96f authored by mirabilos's avatar mirabilos Committed by mirabilos
Browse files

replace the postprocessing chain in preparation for s2

parent 6057e0cd
No related branches found
No related tags found
No related merge requests found
s1e.tmp
#!/bin/mksh
# append -DPROD for production use
set -ex
gcc -O3 -Wall "$@" s1e.c
./a.out > s1e.tmp
if [[ " $* " = *' -DPROD '* ]]; then
thresh=100
else
thresh=1
fi
python3 s1e.py $thresh
/* copy of s1d with different output format + postprocessor */
#include <err.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "inputs.h"
/* without outer walls */
#define HH (H - 2U)
#define WW (W - 2U)
#define INFCOST ((unsigned int)-1)
struct node {
struct node *nb[4];
unsigned int cost;
unsigned short y;
unsigned short x;
unsigned char wall;
unsigned char next;
};
static struct node NN[HH][WW];
#define N(y,x) (&(NN[(y) - 1U][(x) - 1U]))
static struct node *start;
static struct node *finish;
static void
makenodes(void)
{
unsigned int y, x;
struct node *n;
/* safety */
start = NULL;
finish = NULL;
y = 0;
for (x = 0; x < W; ++x)
if (I[y][x] != '#')
errx(1, "upper wall");
y = H - 1U;
for (x = 0; x < W; ++x)
if (I[y][x] != '#')
errx(1, "lower wall");
/* convert, scan for S/E */
for (y = 1U; y < H - 1U; ++y) {
if (I[y][0] != '#')
errx(1, "left wall %u", y);
for (x = 1U; x < W - 1U; ++x) {
n = N(y, x);
n->nb[0] = y == 1U ? NULL : N(y - 1U, x);
n->nb[1] = x == W - 2U ? NULL : N(y, x + 1U);
n->nb[2] = y == H - 2U ? NULL : N(y + 1U, x);
n->nb[3] = x == 1U ? NULL : N(y, x - 1U);
n->cost = INFCOST;
n->y = y;
n->x = x;
switch (I[y][x]) {
case 'S':
if (start)
errx(1, "duplicate start");
start = n;
if (0) {
/* FALLTHROUGH */
case 'E':
if (finish)
errx(1, "duplicate end");
finish = n;
}
/* FALLTHROUGH */
case '.':
n->wall = 0;
break;
case '#':
n->wall = 1;
break;
default:
errx(1, "invalid map character at %u,%u", y, x);
}
n->next = 0;
}
if (I[y][W - 1U] != '#')
errx(1, "right wall %u", y);
}
}
static void
runmainpath(void)
{
struct node *n = start;
unsigned int cost = 0;
unsigned int dir = 0;
loop:
n->cost = cost++;
if (n == finish)
return;
while (n->nb[dir] == NULL || n->nb[dir]->wall) {
dir = (dir + 1U) % 4U;
if (n->nb[dir] == NULL || n->nb[dir]->wall)
dir = (dir + 2U) % 4U;
}
n->next = dir;
n = n->nb[n->next];
goto loop;
}
static inline void
listshortcut(struct node *np, struct node *n1, struct node *n2)
{
unsigned int saving;
saving = n2->cost - np->cost;
/* this value is off by two due to the cost of traversing the cheat */
if (saving < 3)
return;
saving -= 2;
/*
* Here we arrived at a conundrum. The specs say:
*
* > cheats are uniquely identified by their start position and
* > end position.
*
* They do not, however, clarify whether their start position
* is the path or the wall. The end position is the path I think.
*/
/* Part II clarifies this. */
#if 0
/* gives identical output for part I though */
printf("%05u (%u,%u) (%u,%u)\n", saving,
n1->y, n1->x, n2->y, n2->x);
#else
printf("%u (%u,%u)-(%u,%u)\n", saving,
np->y, np->x, n2->y, n2->x);
#endif
/*
* Note the output will need to be uniq(1)ified first,
* verifying that a cheat has no two different savings
* either, then grouped. Something like:
* ./a.out | sort -k2 | uniq | cut -d\ -f1 | sort | uniq -c | sort -nk2
*/
}
static void
listshortcuts(void)
{
struct node *n = start;
struct node *nb1, *nb2;
unsigned int dsc1, dsc2;
loop:
if (n == finish)
return;
/* scan for shortcuts in all four directions… */
for (dsc1 = 0; dsc1 < 4U; ++dsc1) {
/* … where the first step is a nōn-outer wall, */
/* to avoid testing the previous/next step on the path */
if (n->nb[dsc1] == NULL || !n->nb[dsc1]->wall)
continue;
nb1 = n->nb[dsc1];
/* check second step */
for (dsc2 = 0; dsc2 < 4U; ++dsc2) {
/* all directions save where we came from */
if ((dsc2 ^ 2U) == dsc1)
continue;
nb2 = nb1->nb[dsc2];
/* needs to be a path again */
if (!nb2 || nb2->wall)
continue;
/* shortcut or loop back? */
if (nb2->cost < n->cost)
continue;
listshortcut(n, nb1, nb2);
}
}
n = n->nb[n->next];
goto loop;
}
int
main(void)
{
makenodes();
runmainpath();
listshortcuts();
return (0);
}
#!/usr/bin/env python3
import sys
thresh = int(sys.argv[1])
sc = {}
with open("s1e.tmp", "r") as f:
for l in f.readlines():
l, r = l.strip().split(' ')
l = int(l)
if (r not in sc) or (l > sc[r]):
sc[r] = l
cnt = {}
for v in sc.values():
cnt.setdefault(v, 0)
cnt[v] += 1
# list for example, too
if thresh == 1:
for k in sorted(cnt.keys()):
print(k, cnt[k])
res = 0
for k, v in cnt.items():
if k >= thresh:
res += v
print('result:', res)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment