commit ce41fdc97c986f8edd76368c7a1d746ca36c5f72 Author: celso Date: Wed Jan 4 17:14:28 2023 -0300 initial commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..428bcaf --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +CC = gcc +CFLAGS = -Wall -Wpedantic -Wextra +SRC = src +BINDIR = bin +BIN = skomb + +all: $(BIN) + +$(BIN): + $(CC) $(CFLAGS) -O2 -DNDEBUG -Funroll-loops -march=native -s $(SRC)/$(BIN).c -o $(BINDIR)/$@ + +debug: + $(CC) $(CFLAGS) -O0 -g $(SRC)/$(BIN).c -o $(BINDIR)/$(BIN) + +clean: + $(RM) -r $(BINDIR)/* diff --git a/bin/.gitkeep b/bin/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/skomb.c b/src/skomb.c new file mode 100644 index 0000000..63e3f1b --- /dev/null +++ b/src/skomb.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include "skomb.h" + +#define VERSION "1.1" +#define ERROR_MSG(msg) fprintf(stderr, "error: "msg"\n") +#define HELPMSG printf("skomb is a program that returns the possible combinations for a given number and cells it spans in a sudoku killer board\nthis current version only supports numbers in the same column or line, or in the same 9x9, although this may change in future versions\nusage: skomb\n skomb [-h|--help] shows this message\n skomb [-v|--version] shows version number\n") + +int main(int argc, char **argv){ + if (argc >= 2 && (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "--version") == 0)){ + printf(VERSION"\n"); + return 0; + } + if (argc >= 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)){ + HELPMSG; + return 0; + } + while (1){ + printf("Insert number to solve for > "); + /* number can only be two digits at most + space for null character */ + char *numberc = malloc(sizeof(char) * 3); + readline(numberc, 3); + if (numberc[0] == '\0'){ + free(numberc); + break; + } + int number = atoi(numberc); + free(numberc); + /* cells can only be one digit at most + space for null character */ + printf("Insert cells it takes up > "); + char *cellsc = malloc(sizeof(char) * 2); + readline(cellsc, 2); + int cells = atoi(cellsc); + free(cellsc); + printf("Insert numbers that can't be in the group separated by spaces > "); + char *not_allowedc = malloc(sizeof(char) * 20); + readline(not_allowedc, 20); + int *not_allowed = malloc(sizeof(int) * 9); + int *not_allowed_len = malloc(sizeof(int)*1); + *not_allowed_len = splitc_toi(not_allowedc, ' ', not_allowed); + free(not_allowedc); + switch (cells){ + case 2: + if (number >= 3 && number <= 17){ + pair *pairs = malloc(sizeof(pair) * 4); + int len = perm2(number, not_allowed, not_allowed_len, pairs); + printf("%d:\n", number); + for (int i = 0; i < len; i++){ + printf("\t%d + %d\n", pairs[i].x, pairs[i].y); + } + free(pairs); + break; + } + ERROR_MSG("number too small or big for ammount of cells"); + free(not_allowed); + free(not_allowed_len); + return 3; + case 3: + if (number >= 6 && number <= 24){ + trio *trios = malloc(sizeof(trio) * 9); + int len = perm3(number, not_allowed, not_allowed_len, trios); + printf("%d:\n", number); + for (int i = 0; i < len; i++){ + printf("\t%d + %d + %d\n", trios[i].x, trios[i].y, trios[i].z); + } + free(trios); + break; + } + ERROR_MSG("number too small or big for ammount of cells"); + free(not_allowed); + free(not_allowed_len); + return 3; + case 4: + if (number >= 10 && number <= 30){ + quartet *quartets = malloc(sizeof(quartet) * 12); + int len = perm4(number, not_allowed, not_allowed_len, quartets); + printf("%d:\n", number); + for (int i = 0; i < len; i++){ + printf("\t%d + %d + %d + %d\n", quartets[i].x, quartets[i].y, quartets[i].z, quartets[i].w); + } + free(quartets); + break; + } + ERROR_MSG("number too small or big for ammount of cells"); + free(not_allowed); + free(not_allowed_len); + return 3; + case 5: + if (number >= 15 && number <= 35){ + quintet *quintets = malloc(sizeof(quintet) * 12); + int len = perm5(number, not_allowed, not_allowed_len, quintets); + printf("%d:\n", number); + for (int i = 0; i < len; i++){ + printf("\t%d + %d + %d + %d + %d\n", quintets[i].x, quintets[i].y, quintets[i].z, quintets[i].w, quintets[i].v); + } + free(quintets); + break; + } + ERROR_MSG("number too small or big for ammount of cells"); + free(not_allowed); + free(not_allowed_len); + return 3; + default: + ERROR_MSG("invalid ammount of cells"); + free(not_allowed); + free(not_allowed_len); + HELPMSG; + return 4; + } + free(not_allowed); + free(not_allowed_len); + } + return 0; +} diff --git a/src/skomb.h b/src/skomb.h new file mode 100644 index 0000000..795eb86 --- /dev/null +++ b/src/skomb.h @@ -0,0 +1,222 @@ +#ifndef STDIO_H +#define STDIO_H +#include +#endif + +#ifndef STRING_H +#define STRING_H +#include +#endif + +#ifndef STDLIB_H +#define STDLIB_H +#include +#endif + +#ifndef SKOMBLIB_H +#define SKOMBLIB_H + +typedef struct pair{ + int x; + int y; +} pair; + +typedef struct trio{ + int x; + int y; + int z; +} trio; + +typedef struct quartet{ + int x; + int y; + int z; + int w; +} quartet; + +typedef struct quintet{ + int x; + int y; + int z; + int w; + int v; +} quintet; + +void readline(char *line, int len); +int splitc_toi(char *line, int sep, int *dest); +int perm2(int number, int *not_allowed, int* not_allowed_len, pair *pairs); +int perm3(int number, int *not_allowed, int* not_allowed_len, trio *trios); +int perm4(int number, int *not_allowed, int* not_allowed_len, quartet *quartets); +int perm5(int number, int *not_allowed, int* not_allowed_len, quintet *quintets); + +void readline(char *line, int len){ + int i = 0; + int c; + while ((c = getchar()) != '\n' && i < len){ + line[i] = c; + i++; + } + line[i] = '\0'; +} + +int splitc_toi(char *line, int sep, int *dest){ + int i, j; + i = j = 0; + char temp[2]; + temp[1] = '\0'; + while (line[i] != '\0'){ + if (line[i] == sep){ + i++; + continue; + } + temp[0] = line[i]; + dest[j] = atoi(temp); + i++; + j++; + } + return j; +} + +int perm2(int number, int* not_allowed, int* not_allowed_len, pair* dest){ + int i, j, k; + int skip; + k = 0; + for (i = 1; i < 10; i++){ + for (j = 0; j < *not_allowed_len; j++){ + if (i == not_allowed[j] || number - i == not_allowed[j]){ + skip = 1; + break; + } + } + if (skip == 1){ + skip = 0; + continue; + } + if (i != number && i < number - i && number - i < 10){ + dest[k].x = i; + dest[k].y = number - i; + k++; + } + } + return k; +} + +int perm3(int number, int *not_allowed, int *not_allowed_len, trio *trios){ + int i, j, k; + int skip, len; + k = 0; + pair *pairs = malloc(sizeof(pair) * 4); + for (i = 1; i < 10; i++){ + for (j = 0; j < *not_allowed_len; j++){ + if (i == not_allowed[j]){ + skip = 1; + break; + } + } + if (skip == 1){ + skip = 0; + continue; + } + if (i != number && number - i < 18 && number - i > 2 + && i < number){ + not_allowed[*not_allowed_len] = i; + (*not_allowed_len)++; + len = perm2(number-i, not_allowed, not_allowed_len, pairs); + if (len > 0){ + for (j = 0; j < len; j++){ + if (i < pairs[j].x && i < pairs[j].y){ + trios[k].x = i; + trios[k].y = pairs[j].x; + trios[k].z = pairs[j].y; + k++; + } + } + } + (*not_allowed_len)--; + not_allowed[*not_allowed_len] = 0; + } + } + free(pairs); + return k; +} + +int perm4(int number, int *not_allowed, int *not_allowed_len, quartet *quartets){ + int i, j, k; + int skip, len; + k = 0; + trio *trios = malloc(sizeof(pair) * 8); + for (i = 1; i < 10; i++){ + for (j = 0; j < *not_allowed_len; j++){ + if (i == not_allowed[j]){ + skip = 1; + break; + } + } + if (skip == 1){ + skip = 0; + continue; + } + if (i != number && number - i < 25 && number - i > 5){ + not_allowed[*not_allowed_len] = i; + (*not_allowed_len)++; + len = perm3(number - i, not_allowed, not_allowed_len, trios); + if (len > 0){ + for (j = 0; j < len; j++){ + if (i < trios[j].x && i < trios[j].y && i < trios[j].z){ + quartets[k].x = i; + quartets[k].y = trios[j].x; + quartets[k].z = trios[j].y; + quartets[k].w = trios[j].z; + k++; + } + } + } + (*not_allowed_len)--; + not_allowed[*not_allowed_len] = 0; + } + } + free(trios); + return k; +} + +int perm5(int number, int *not_allowed, int* not_allowed_len, quintet *quintets){ + int i, j, k; + int skip, len; + k = 0; + quartet *quartets = malloc(sizeof(pair) * 12); + for (i = 1; i < 10; i++){ + for (j = 0; j < *not_allowed_len; j++){ + if (i == not_allowed[j]){ + skip = 1; + break; + } + } + if (skip == 1){ + skip = 0; + continue; + } + if (i != number && number - i < 31 && number - i > 9){ + not_allowed[*not_allowed_len] = i; + (*not_allowed_len)++; + len = perm4(number-i, not_allowed, not_allowed_len, quartets); + if (len > 0){ + for (j = 0; j < len; j++){ + if (i < quartets[j].x && i < quartets[j].y && i < quartets[j].z && i < quartets[j].w){ + quintets[k].x = i; + quintets[k].y = quartets[j].x; + quintets[k].z = quartets[j].y; + quintets[k].w = quartets[j].z; + quintets[k].v = quartets[j].w; + k++; + } + } + } + (*not_allowed_len)--; + not_allowed[*not_allowed_len] = 0; + } + } + free(quartets); + return k; +} + +#endif