Last active
October 6, 2022 19:47
Robot programming challenge
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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