├── Makefile ├── README.md ├── includes └── functions.h └── src ├── common.c ├── main.c ├── parsing.c └── rules.c /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFILES=$(shell find src -type f -name "*.c") 3 | HEADERS_DIR=includes/ 4 | CFLAGS=-Wall -Wextra -Werror -I $(HEADERS_DIR) 5 | DEBUG_FLAGS=-Wall -Wextra -Werror 6 | NAME=skyscraper 7 | OBJS=${CFILES:.c=.o} 8 | 9 | all: $(OBJS) 10 | $(CC) $(CFLAGS) $(OBJS) -o $(NAME) 11 | 12 | clean: 13 | rm -rf src/*.o 14 | 15 | debug: 16 | $(CC) $(DEBUG_FLAGS) -g debug/test.c 17 | 18 | fclean: clean 19 | rm -f $(NAME) 20 | 21 | re: fclean all 22 | 23 | .PHONY: all clean debug fclean re -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # skyscraperSolver
2 | A little nogui program to solve 4*4 skyscraper puzzles
3 |
4 | How to start ?
5 |
6 | make
7 | ./skyscraper "4 1 2 3 1 2 2 2 2 2 2 1 3 2 1 4"
8 |
9 |
10 | order of the digits in the argument:
11 | 1 - checking columns from the top
12 | 2 - checking columns from the bottom
13 | 3 - checking rows from the left
14 | 4 - checking row from the right
-------------------------------------------------------------------------------- /includes/functions.h: -------------------------------------------------------------------------------- 1 | #ifndef __FUNCTIONS_H__ 2 | #define __FUNCTIONS_H__ 3 | 4 | void ft_putnbr(int nb); 5 | void ft_putchar(char c); 6 | void ft_putstr(char *str); 7 | 8 | int ft_atoi(char *str); 9 | int ft_strlen(char *str); 10 | int *get_numbers(char *str); 11 | int check(int ac, char **av); 12 | int check_double(int tab[4][4], int pos, int num); 13 | int check_case(int tab[4][4], int pos, int entry[16]); 14 | 15 | #endif -------------------------------------------------------------------------------- /src/common.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Prints a single char 4 | void ft_putchar(char c) 5 | { 6 | write(1, &c, 1); 7 | } 8 | 9 | //prints a list of characters 10 | void ft_putstr(char *str) 11 | { 12 | while (*str) 13 | write(1, str++, 1); 14 | } 15 | 16 | //gives the length of a list of character (strlen) 17 | int ft_strlen(char *str) 18 | { 19 | int i; 20 | 21 | i = 0; 22 | while (str[i] != '\0') 23 | i++; 24 | return (i); 25 | } 26 | 27 | //similar to (atoi() in stdlib.h) 28 | int ft_atoi(char *str) 29 | { 30 | int i; 31 | int nbr; 32 | int nbrminus; 33 | 34 | i = 0; 35 | nbr = 0; 36 | nbrminus = 0; 37 | while ((str[i] >= 9 && str[i] <= 13) || str[i] == ' ') 38 | i++; 39 | while (str[i] == '-' || str[i] == '+') 40 | if (str[i++] == '-') 41 | nbrminus++; 42 | while (str[i] >= '0' && str[i] <= '9') 43 | nbr = nbr * 10 + (str[i++] - '0'); 44 | if (nbrminus % 2 == 1) 45 | return (nbr * -1); 46 | return (nbr); 47 | } 48 | 49 | //prints a number in the standart output 50 | void ft_putnbr(int nb) 51 | { 52 | unsigned int nbr; 53 | 54 | if (nb < 0) 55 | { 56 | ft_putchar('-'); 57 | nbr = nb * -1; 58 | } 59 | else 60 | nbr = nb; 61 | if (nbr / 10 != 0) 62 | ft_putnbr(nbr / 10); 63 | ft_putchar(nbr % 10 + 48); 64 | } 65 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include "functions.h" 2 | 3 | int solve(int tab[4][4], int entry[16], int pos) 4 | { 5 | int size; 6 | 7 | if (pos == 16) 8 | return (1); 9 | size = 0; 10 | while (++size <= 4) 11 | { 12 | //checking if the number I want to place is correct 13 | if (check_double(tab, pos, size) == 0) 14 | { 15 | tab[pos / 4][pos % 4] = size; 16 | //checking if the tab is correct with the new number 17 | if (check_case(tab, pos, entry) == 0) 18 | { 19 | //checking for next possibility 20 | if (solve(tab, entry, pos + 1) == 1) 21 | return (1); 22 | } 23 | else 24 | tab[pos / 4][pos % 4] = 0; 25 | } 26 | } 27 | //did not find any solutions 28 | return (0); 29 | } 30 | 31 | void display_solution(int tab[4][4]) 32 | { 33 | int i; 34 | int j; 35 | 36 | i = -1; 37 | while (++i < 4) 38 | { 39 | j = -1; 40 | while (++j < 4) 41 | { 42 | ft_putnbr(tab[i][j]); 43 | ft_putchar(' '); 44 | } 45 | ft_putchar('\n'); 46 | } 47 | } 48 | 49 | int main(int ac, char **av) 50 | { 51 | int tab[4][4] = { 52 | {0, 0, 0, 0}, 53 | {0, 0, 0, 0}, 54 | {0, 0, 0, 0}, 55 | {0, 0, 0, 0}, 56 | }; 57 | int *entry; 58 | 59 | if (check(ac, av) == 1) 60 | return (0); 61 | entry = get_numbers(av[1]); 62 | 63 | if (solve(tab, entry, 0) == 1) 64 | display_solution(tab); 65 | else 66 | ft_putstr("Did not find any solutions\n"); 67 | return (0); 68 | } 69 | -------------------------------------------------------------------------------- /src/parsing.c: -------------------------------------------------------------------------------- 1 | #include "functions.h" 2 | #include 3 | 4 | int check(int ac, char **av) 5 | { 6 | if (ac != 2) 7 | return (1); 8 | if (ft_strlen(av[1]) != 31) 9 | return (1); 10 | return (0); 11 | } 12 | 13 | int *get_numbers(char *str) 14 | { 15 | int i; 16 | int j; 17 | int *tab; 18 | 19 | if (!(tab = malloc(sizeof(int) * 16))) 20 | return (0); 21 | i = -1; 22 | j = 0; 23 | while (str[++i] != '\0') 24 | if (str[i] >= '0' && str[i] <= '9') 25 | tab[j++] = ft_atoi(str + i); 26 | return (tab); 27 | } -------------------------------------------------------------------------------- /src/rules.c: -------------------------------------------------------------------------------- 1 | int check_double(int tab[4][4], int pos, int num) 2 | { 3 | int i; 4 | 5 | i = -1; 6 | while (++i < pos / 4) 7 | if (tab[i][pos % 4] == num) 8 | return (1); 9 | i = -1; 10 | while (++i < pos % 4) 11 | if (tab[pos / 4][i] == num) 12 | return (1); 13 | return (0); 14 | } 15 | 16 | int check_col_up(int tab[4][4], int pos, int entry[16]) 17 | { 18 | int i; 19 | int max; 20 | int count; 21 | 22 | i = 0; 23 | max = 0; 24 | count = 0; 25 | if (pos / 4 == 3) 26 | { 27 | while (i < 4) 28 | { 29 | if (tab[i][pos % 4] > max) 30 | { 31 | max = tab[i][pos % 4]; 32 | count++; 33 | } 34 | i++; 35 | } 36 | if (entry[pos % 4] != count) 37 | return (1); 38 | } 39 | return (0); 40 | } 41 | 42 | int check_row_right(int tab[4][4], int pos, int entry[16]) 43 | { 44 | int i; 45 | int max_size; 46 | int visible_towers; 47 | 48 | i = 4; 49 | max_size = 0; 50 | visible_towers = 0; 51 | if (pos % 4 == 3) 52 | { 53 | while (--i >= 0) 54 | { 55 | if (tab[pos / 4][i] > max_size) 56 | { 57 | max_size = tab[pos / 4][i]; 58 | visible_towers++; 59 | } 60 | } 61 | if (entry[12 + pos / 4] != visible_towers) 62 | return (1); 63 | } 64 | return (0); 65 | } 66 | 67 | int check_col_down(int tab[4][4], int pos, int entry[16]) 68 | { 69 | int i; 70 | int max; 71 | int count; 72 | 73 | i = 3; 74 | max = 0; 75 | count = 0; 76 | if (pos / 4 == 3) 77 | { 78 | while (i >= 0) 79 | { 80 | if (tab[i][pos % 4] > max) 81 | { 82 | max = tab[i][pos % 4]; 83 | count++; 84 | } 85 | i--; 86 | } 87 | if (entry[4 + pos % 4] != count) 88 | return (1); 89 | } 90 | return (0); 91 | } 92 | 93 | int check_row_left(int tab[4][4], int pos, int entry[16]) 94 | { 95 | int i; 96 | int max; 97 | int count; 98 | 99 | i = 0; 100 | max = 0; 101 | count = 0; 102 | if (pos % 4 == 3) 103 | { 104 | while (i < 4) 105 | { 106 | if (tab[pos / 4][i] > max) 107 | { 108 | max = tab[pos / 4][i]; 109 | count++; 110 | } 111 | i++; 112 | } 113 | if (entry[8 + pos / 4] != count) 114 | return (1); 115 | } 116 | return (0); 117 | } 118 | 119 | int check_case(int tab[4][4], int pos, int entry[16]) 120 | { 121 | if (check_row_left(tab, pos, entry) == 1) 122 | return (1); 123 | if (check_row_right(tab, pos, entry) == 1) 124 | return (1); 125 | if (check_col_down(tab, pos, entry) == 1) 126 | return (1); 127 | if (check_col_up(tab, pos, entry) == 1) 128 | return (1); 129 | return (0); 130 | } --------------------------------------------------------------------------------