From 10f4f8572d0b162c88777bb2095def066828d9f9 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Wed, 8 Sep 2021 14:10:05 +0200 Subject: [PATCH] C two-bucket: final version + separate main --- c/two-bucket/main.c | 26 ++++++ c/two-bucket/two_bucket.c | 181 ++++++++++---------------------------- 2 files changed, 71 insertions(+), 136 deletions(-) create mode 100644 c/two-bucket/main.c diff --git a/c/two-bucket/main.c b/c/two-bucket/main.c new file mode 100644 index 0000000..be3c1a9 --- /dev/null +++ b/c/two-bucket/main.c @@ -0,0 +1,26 @@ +/* Standalone tests. + * See GNUmakefile below for explanation + * https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile + */ +#include "two_bucket.h" + +#ifdef UNIT_TEST +int main(int ac, char **av) +{ + int arg=1; + int b1, b2, goal, start; + bucket_result_t res;; + + for (; argX, y=board->Y; - printf("board(%d, %d)\n", x, y); - for (int row = y-1; row >= 0; --row) { - printf("%03d ", row); - for (int col = 0; col < x; ++col) { - //printf("C: i=%d j=%d cell %d\n", i, j, i*x+j); - //printf(" %d ", board[i*x+j]); - printf(" %2d ", board->board[SQUARE(col, row, board)]); - //printf("row=%d col=%d x=%d square=%d\n", row, col, x, SQUARE(col, row, x)); - } - putchar('\n'); - } - putchar('\n'); -} - -static inline void board_init(struct board *board, int goal) -{ - int i, x=board->X, y=board->Y; - - printf("board_init(%d, %d, goal=%d)\n", x, y, goal); - //board_print(board, x, y); - for (i=0; i < x*y; ++i) { - printf("setting square %d (%d, %d)\n", i, COL(i, board), ROW(i, board)); + int i; + board->X=X; + board->Y=Y; + for (i=0; i < board->X*board->Y; ++i) *(board->board+i) = AVAILABLE; - } - board_print(board); /* set target on goal row */ - if (x > goal) { - for (i = 0; i < y; ++i) { - printf("A: x=%d i=%d goal=%d setting %d\n", x, i, goal, SQUARE(goal, i, board)); + if (board->X > goal) { + for (i = 0; i < board->Y; ++i) board->board[SQUARE(goal, i, board)] = GOAL; - //board_print(board, x, y); - } } /* set target on goal col */ - board_print(board); - if (y > goal) { - for (i = 0; i < x; ++i) { - printf("B: x=%d i=%d goal=%d setting %d\n", x, i, goal, SQUARE(i, goal, board)); + if (board->Y > goal) { + for (i = 0; i < board->X; ++i) board->board[SQUARE(i, goal, board)] = GOAL; - } - board_print(board); } } static inline void enqueue(struct stack *s, int v) { - printf("pushing v=%d\n", v); - //if (s->stack[s->last] == AVAILABLE) s->s[s->last++] = v; } static inline int dequeue(struct stack *s) { - int res; - printf("dequeue: first=%d last=%d val=%d\n", s->first, s->last, s->s[s->first]); - res = s->first < s->last ? s->s[s->first++] : -1; - printf("popping v=%d\n", res); - return res; + return s->first < s->last ? s->s[s->first++] : -1; } static int move(struct board *board, struct stack *stack, int col, int row, - int level, char *text) + int level) { - printf("move to [%s] on (%d, %d) - level=%d curval=%d : ", - text, col, row, level, board->board[SQUARE(col, row, board)]); board->board[SQUARE(col, row, board)] = level; enqueue (stack, SQUARE(col, row, board)); return 0; } -static int move_maybe(struct board *board, struct stack *stack, int col, int row, - int level, char *text) +static int move_maybe(struct board *board, struct stack *stack, + int col, int row, int level) { - printf("trying to [%s] on (%d, %d) - level=%d curval=%d : ", - text, col, row, level, board->board[SQUARE(col, row, board)]); - if (board->board[SQUARE(col, row, board)] == AVAILABLE) { - printf("OK\n"); - - move(board, stack, col, row, level, text); - //board->board[SQUARE(col, row, board)] = level; - //enqueue (stack, SQUARE(col, row, board)); - } else if (board->board[SQUARE(col, row, board)] == GOAL) { - printf("**************** GOAL\n"); - return 1; - } else { - printf("Impossible\n"); + switch (board->board[SQUARE(col, row, board)]) { + case GOAL: + return 1; + case AVAILABLE: + return move(board, stack, col, row, level); + default: + return 0; } - return 0; } -static bucket_result_t board_bfs(struct board *board, struct stack *stack, int start, +static bucket_result_t board_bfs(struct board *board, struct stack *stack, const int goal) { int level = 0; @@ -162,57 +116,52 @@ static bucket_result_t board_bfs(struct board *board, struct stack *stack, int s int min, row, col, col1, row1; int X=board->X, Y=board->Y; bucket_result_t res = { .possible = false, .move_count = 0 }; - /* initialize 1st square used */ - printf("bfs(start=%d, X=%d, Y=%d)\n", start, board->X, board->Y); /* now we consume as we can... */ while ((cur_square = dequeue(stack)) >= 0) { col=COL(cur_square, board); row=ROW(cur_square, board); level=board->board[cur_square]; - board_print(board); - printf("move[pop=%d](col=%d, row=%d)=%d level=%d\n", - cur_square, col, row, board->board[cur_square], level); if (col > 0) { col1 = 0; row1 = row; - if (move_maybe(board, stack, col1, row1, level+1, "empty b1")) + if (move_maybe(board, stack, col1, row1, level+1)) goto found; } if (row > 0) { col1 = col; row1 = 0; - if (move_maybe(board, stack, col1, row1, level+1, "empty b2")) + if (move_maybe(board, stack, col1, row1, level+1)) goto found; } if (col < X-1) { col1 = X-1; row1 = row; - if (move_maybe(board, stack, col1, row1, level+1, "fill b1")) + if (move_maybe(board, stack, col1, row1, level+1)) goto found; } if (row < Y-1) { col1 = col; row1 = Y-1; - if (move_maybe(board, stack, col1, row1, level+1, "fill b2")) + if (move_maybe(board, stack, col1, row1, level+1)) goto found; } if (col > 0 && row < Y-1) { min = MIN(col, Y-row-1); - col1 = col-min; - row1 = row+min; - if (move_maybe(board, stack, col1, row1, level+1, "pour b1 in b2")) + col1 = col - min; + row1 = row + min; + if (move_maybe(board, stack, col1, row1, level+1)) goto found; } if (row > 0 && col < X-1) { min = MIN(row, X-col-1); - col1 = col+min; - row1 = row-min; - if (move_maybe(board, stack, col1, row1, level+1, "pour b2 in b1")) + col1 = col + min; + row1 = row - min; + if (move_maybe(board, stack, col1, row1, level+1)) goto found; } } - goto end; /* no more possible move */ + goto end; /* fail: no more moves */ found: res.possible = true; res.move_count = level+1; @@ -224,10 +173,6 @@ found: res.other_bucket_liters=col1; } end: - printf("END: possible=%d\n", res.possible); - printf(" move-count=%d\n", res.move_count); - printf(" goal-bucket=%d\n", res.goal_bucket); - printf(" other-bucket=%d\n", res.other_bucket_liters); return res; } @@ -245,12 +190,13 @@ bucket_result_t measure(const bucket_liters_t b1, struct board *board; struct stack *stack; - printf("measure(b1=%d, b2=%d, goal=%d, start=%d)\n", b1, b2, goal, start); + /* impossible goal */ if (goal > b1 && goal > b2) return res; + + /* initial move is the solution ? */ if ((start == BUCKET_ID_1 && goal == b1) || (start == BUCKET_ID_2 && goal == b2)) { - printf("done in 1\n"); res.possible = true; res.move_count = 1; res.goal_bucket = start; @@ -259,18 +205,13 @@ bucket_result_t measure(const bucket_liters_t b1, if (!(stack = malloc(sizeof(*stack) + sizeof(*stack->s)*(b1+1)*(b2+1)))) return res; - stack->first = 0; - stack->last = 0; - printf("board size: %lu int=%lu n=%d, %lu\n", sizeof(*board), sizeof(int), - (b1+1)*(b2+1), - sizeof(*board) + sizeof(*board->board)*(b1+1)*(b2+1)); + //int i; + stack->first = stack->last = 0; if (!(board = malloc(sizeof(*board) + sizeof(*board->board)*(b1+1)*(b2+1)))) { free(stack); return res; } - board->X = b1+1; - board->Y = b2+1; - board_init(board, goal); + board_init(board, b1+1, b2+1, goal); /* only for exercism. better solutions could be found. Remove the next * 3 lines to allow a different starting bucket (possibly better solution). */ @@ -278,43 +219,11 @@ bucket_result_t measure(const bucket_liters_t b1, board->board[SQUARE(0, b2, board)] = FORBIDDEN; board->board[SQUARE(b1, 0, board)] = FORBIDDEN; - if (start == BUCKET_ID_1) { - move(board, stack, b1, 0, 1, "start with b1"); - //enqueue(stack, SQUARE(b1, 0, board)); - //board->board[SQUARE(b1, 0, board)] = 1; - } else { - move(board, stack, 0, b2, 1, "start with b1"); - //enqueue(stack, SQUARE(0, b2, board)); - //board->board[SQUARE(0, b2, board)] = 1; - } - board_print(board); + /* initial move */ + move(board, stack, start==BUCKET_ID_1? b1: 0, start==BUCKET_ID_2? b2: 0, 1); - res = board_bfs(board, stack, start, goal); + res = board_bfs(board, stack, goal); free(stack); free(board); return res; } - -/* See GNUmakefile below for explanation - * https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile - */ -#ifdef UNIT_TEST -int main(int ac, char **av) -{ - int arg=1; - int b1, b2, goal, start; - bucket_result_t res;; - - for (; arg