Skip to content

Instantly share code, notes, and snippets.

@skeeto
Last active October 6, 2022 19:47
Robot programming challenge
// Robot programming challenge
// See robot.h for documentation.
// This is free and unencumbered software released into the public domain.
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "robot.h"
#define WIDTH_MAX 80
#define HEIGHT_MAX 24
#define THICK_MAX 4
struct robot {
int x, y, d;
int w, h;
_Bool debug;
char map[HEIGHT_MAX][WIDTH_MAX];
};
static struct robot robot;
static const int dir[][2] = {{+1,+0}, {+0,+1}, {-1,+0}, {+0,-1}};
static int randint(unsigned long long *rng, int min, int max)
{
assert(min <= max);
*rng = *rng*0x3243f6a8885a308d + 1;
return min + (*rng>>32 & 0xffffffff)%(max - min + 1);
}
static void print(void)
{
for (int y = 0; y < robot.h; y++) {
for (int x = 0; x < robot.w; x++) {
if (x == robot.x && y == robot.y) {
putchar(">V<^"[robot.d]);
} else {
putchar(robot.map[y][x]);
}
}
putchar('\n');
}
putchar('\n');
fflush(stdout);
for (clock_t beg = clock(); clock() < beg+CLOCKS_PER_SEC/10;);
}
void init(long long seed)
{
unsigned long long rng = seed ^ 1111111111111111111;
int w = robot.w = randint(&rng, WIDTH_MAX*2/3, WIDTH_MAX);
int h = robot.h = randint(&rng, HEIGHT_MAX*2/3, HEIGHT_MAX);
robot.x = 0;
robot.y = h - 1;
robot.d = 0;
robot.debug = 0;
memset(robot.map, '.', sizeof(robot.map));
for (int x = 1; x < w-1; x++) {
int thick;
do {
thick = randint(&rng, 1, THICK_MAX);
} while (thick+x == w-2 || thick+x > w-1);
int hole = randint(&rng, 0, h-1);
for (int t = 0; t < thick; t++) {
for (int y = 0; y < h; y++) {
if (y != hole) {
robot.map[y][x+t] = '#';
}
}
}
x += thick;
}
}
void debug(void)
{
static char buf[1<<12];
setvbuf(stdout, buf, _IOFBF, sizeof(buf));
robot.debug = 1;
}
void halt(void)
{
assert(robot.x == robot.w-1 && robot.y == robot.h-1);
}
void turnleft(void)
{
robot.d = (robot.d + 3) % 4;
if (robot.debug) print();
}
void turnright(void)
{
robot.d = (robot.d + 1) % 4;
if (robot.debug) print();
}
static _Bool scan(int d)
{
int x = robot.x + dir[d][0];
int y = robot.y + dir[d][1];
return x<0 || x>=robot.w || y<0 || y>=robot.h || robot.map[y][x]=='#';
}
void moveforward(void)
{
assert(!scan(robot.d));
robot.x += dir[robot.d][0];
robot.y += dir[robot.d][1];
if (robot.debug) print();
}
_Bool scanleft(void)
{
return scan((robot.d + 3) % 4);
}
_Bool scanright(void)
{
return scan((robot.d + 1) % 4);
}
_Bool scanforward(void)
{
return scan(robot.d);
}
// Robot programming challenge
//
// The robot starts in the southwest corner facing east. The goal is to
// get to the southeast corner then halt. The dimensions of the map are
// unknown. Walls stretch vertically with a single tile gap. The wall
// thickness is unknown.
//
// Ref: https://old.reddit.com/r/C_Programming/comments/xx8oem
//
// This is free and unencumbered software released into the public domain.
#ifndef ROBOT_H
#define ROBOT_H
void init(long long seed); // initialize a new puzzle
void debug(void); // enable debug display
void turnleft(void); // turn robot left
void turnright(void); // turn robot right
void moveforward(void); // move robot forward (do no crash!)
_Bool scanleft(void); // true when wall is immediately left
_Bool scanright(void); // true when wall is immediately right
_Bool scanforward(void); // true when wall is immediately forward
void halt(void); // power down (must be in southeast corner!)
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment