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

challenge passed (ca. 660 ms)

parent 7fffe9ba
No related branches found
No related tags found
No related merge requests found
/* with extra datastructures to perform better on evil inputs */
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "inputs.h"
#include "evil_input.h"
#ifdef INSTD
#define INPUT argv[1]
#elif defined(EVIL1)
#define INPUT somewhat_evil_input
#elif defined(EVIL2)
#define INPUT really_evil_input
#elif !defined(INPUT)
#define INPUT I
#endif
#define FREE 0xFFFFFFFFU
struct entry {
unsigned int width;
unsigned int prev;
unsigned int next;
unsigned int fno;
};
#define NI 524288U
struct entry ent[NI];
unsigned int nextinbucket[NI];
unsigned int firstinbucket[10] = {
FREE, FREE, FREE, FREE, FREE,
FREE, FREE, FREE, FREE, FREE,
};
static void
chkbucket(int where)
{
#ifdef dovis3
int i;
unsigned int n;
int e = 0;
for (i = 1; i <= 9; ++i) {
printf("bucket(%d): ", i);
n = firstinbucket[i];
while (n != FREE) {
if (ent[n].width == i)
printf("%u\033[0m ", n);
else {
printf("\033[5m%u(%u)\033[0m ", n, ent[n].width);
e = 1;
}
if (nextinbucket[n] != FREE &&
nextinbucket[n] <= n) {
printf("\033[1m");
e = 1;
}
n = nextinbucket[n];
}
printf("END\033[0m\n");
}
printf("chkbucket(%d): %s\n", where, e ? "ERROR" : "ok");
#endif
}
int
main(int argc, char *argv[])
{
size_t i, j, k, fl;
unsigned long long curblk, sum, nextblk;
unsigned char ch;
#ifdef INSTD
if (argc != 2)
errx(1, "Usage: ./a.out $(<inputfile)");
#endif
i = 0;
while ((ch = INPUT[i])) {
if (ch < '0' || ch > '9')
errx(2, "invalid input char: %02X", (unsigned int)ch);
ent[i].width = (unsigned int)ch - (unsigned int)'0';
ent[i].prev = i - 1U;
ent[i].next = i + 1U;
if (i & 1U) {
ent[i].fno = FREE;
} else {
ent[i].fno = i / 2U;
}
++i;
}
ent[0].prev = 0;
ent[i].width = 0;
ent[i].prev = i - 1U;
ent[i].next = i;
ent[i].fno = FREE;
fl = i + 1; /* freelist */
j = i--;
#ifdef dovis2
j = 0;
while (ent[j].next != j) {
unsigned int x;
ch = ent[j].fno == FREE ? '.' : '0' + ent[j].fno;
x = ent[j].width;
while (x--)
putchar(ch);
j = ent[j].next;
}
printf("\n");
#endif
do {
j -= 2;
nextinbucket[j] = firstinbucket[ent[j].width];
firstinbucket[ent[j].width] = j;
} while (j > 1);
chkbucket(0);
while (i) {
#ifdef dovis3
printf("i(%u) fno(%u) prev(%u)\n",
(unsigned)i, (unsigned)ent[i].fno, (unsigned)ent[i].prev);
#endif
if (ent[i].fno == FREE)
goto nexti;
j = k = ent[i].width;
while (++j <= 9)
if (firstinbucket[k] == FREE ||
(firstinbucket[j] != FREE &&
firstinbucket[j] < firstinbucket[k]))
k = j;
if ((j = firstinbucket[k]) == FREE || j > i)
goto nexti;
/* move */
/* free free-bucket */
firstinbucket[k] = nextinbucket[j];
#ifdef dovis3
printf("D: taking first (%u) from bucket %u, next is %u\n",
(unsigned)j, (unsigned)k, (unsigned)firstinbucket[k]);
#endif
/* easy move? */
if (ent[j].width == ent[i].width) {
ent[j].fno = ent[i].fno;
ent[i].fno = FREE;
} else {
ent[fl].width = ent[i].width;
ent[fl].prev = ent[j].prev;
ent[ent[fl].prev].next = fl;
ent[fl].next = j;
ent[j].prev = fl;
ent[fl].fno = ent[i].fno;
ent[i].fno = FREE;
ent[j].width -= ent[i].width;
if (++fl == NI)
errx(1, "out of space");
chkbucket(3);
/* put at right space in new bucket */
if (j < firstinbucket[ent[j].width]) {
nextinbucket[j] = firstinbucket[ent[j].width];
firstinbucket[ent[j].width] = j;
chkbucket(1);
} else {
k = firstinbucket[ent[j].width];
while (nextinbucket[k] < j)
k = nextinbucket[k];
/* now: k < j < nextinbucket[k] */
nextinbucket[j] = nextinbucket[k];
nextinbucket[k] = j;
chkbucket(2);
}
}
#ifdef dovis2
j = 0;
while (ent[j].next != j) {
unsigned int x;
ch = ent[j].fno == FREE ? '.' : '0' + ent[j].fno;
x = ent[j].width;
while (x--)
putchar(ch);
j = ent[j].next;
}
printf("\n");
#endif
nexti:
#if 0 /* I used this in s2.c but it can never have worked?! */
i = ent[i].prev;
#else
i -= 2;
#endif
}
#ifdef dovis
i = 0;
while (ent[i].next != i) {
unsigned int x;
ch = ent[i].fno == FREE ? '.' : '0' + ent[i].fno;
x = ent[i].width;
while (x--)
putchar(ch);
i = ent[i].next;
}
printf("\n");
#endif
i = 0;
curblk = 0;
sum = 0;
while (ent[i].next != i) {
nextblk = curblk + ent[i].width;
if (ent[i].fno != FREE) {
sum += (nextblk * (nextblk - 1U) - curblk * (curblk - 1U)) / 2U *
ent[i].fno;
}
curblk = nextblk;
i = ent[i].next;
}
printf("%llu\n", sum);
return (0);
}
../../i2c/str
\ No newline at end of file
i2c/str 0 → 100755
#!/bin/mksh
set -e
doone() {
print -r -- "static const char I[] = \"$(
sed 's/[\\"]/\\&/g' <"$1" #'"
)\";"
}
exec >inputs.h
print '#ifndef PROD'
print
doone c
print
print '#else'
print
doone i
print
print '#endif'
exec >/dev/null
exit 0
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