├── 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 | }
--------------------------------------------------------------------------------