text: /* ************************************************************************** */
  /*                                                                            */
  /*                                                        :::      ::::::::   */
  /*   test_README.c                                      :+:      :+:    :+:   */
  /*                                                    +:+ +:+         +:+     */
  /*   By: evgenkarlson <RTFM@42.fr>                  +#+  +:+       +#+        */
  /*                                                +#+#+#+#+#+   +#+           */
  /*   Created: 2020/02/14 12:33:14 by evgenkarlson      #+#    #+#             */
  /*   Updated: 2021/08/12 01:58:23 by evgenkarlson     ###   ########.fr       */
  /*                                                                            */
  /* ************************************************************************** */
  
  /* ************************************************************************** */
  /*	команда для компиляции и одновременного запуска                           */
  /*                                                                            */
  /*  gcc -Wall -Werror -Wextra test.c && chmod +x ./a.out && ./a.out	   	      */
  /* ************************************************************************** */
  
  
  
  /*
  
   * Здесь мы отправляем в аргументы программе для решения судоку. И на выводе получаем решенную задачу.
  
   * One solution:
  gcc -Wall -Werror -Wextra test_README.c && chmod +x ./a.out && ./a.out "9...7...." "2...9..53" ".6..124.." "84...1.9." "5.....8.." ".31..4..." "..37..68." ".9..5.741" "47......." | cat -e
  
  OR:
  gcc -Wall -Werror -Wextra ./main.c ./sudoku.c ./display.c ./check.c && chmod +x ./a.out && ./a.out "9...7...." "2...9..53" ".6..124.." "84...1.9." "5.....8.." ".31..4..." "..37..68." ".9..5.741" "47......." | cat -e
  
  9 1 4 3 7 5 2 6 8$
  2 8 7 4 9 6 1 5 3$
  3 6 5 8 1 2 4 7 9$
  8 4 6 5 2 1 3 9 7$
  5 2 9 6 3 7 8 1 4$
  7 3 1 9 8 4 5 2 6$
  1 5 3 7 4 9 6 8 2$
  6 9 8 2 5 3 7 4 1$
  4 7 2 1 6 8 9 3 5$
  
  
  
   * Multiple Solutions:
  gcc -Wall -Werror -Wextra test_README.c && chmod +x ./a.out && ./a.out "9.6.7.4.3" "...4..2.." ".7..23.1." "5.....1.." ".4.2.8.6." "..3.....5" ".3.7...5." "..7..5..." "4.5.1.7.8" | cat -e
  
  OR:
  gcc -Wall -Werror -Wextra ./main.c ./sudoku.c ./display.c ./check.c && chmod +x ./a.out && ./a.out "9.6.7.4.3" "...4..2.." ".7..23.1." "5.....1.." ".4.2.8.6." "..3.....5" ".3.7...5." "..7..5..." "4.5.1.7.8" | cat -e
  
  9 2 6 5 7 1 4 8 3$
  3 5 1 4 8 6 2 7 9$
  8 7 4 9 2 3 5 1 6$
  5 8 2 3 6 7 1 9 4$
  1 4 9 2 5 8 3 6 7$
  7 6 3 1 4 9 8 2 5$
  2 3 8 7 9 4 6 5 1$
  6 1 7 8 3 5 9 4 2$
  4 9 5 6 1 2 7 3 8$
  
  
  
   * Expert level:
  gcc -Wall -Werror -Wextra test_README.c && chmod +x ./a.out && ./a.out ".8...3.57" "7........" "..4....86" "........." "....7.46." "629..8..." ".5...689." "........." ".....21.3"
  
  OR:
  gcc -Wall -Werror -Wextra ./main.c ./sudoku.c ./display.c ./check.c && chmod +x ./a.out && ./a.out ".8...3.57" "7........" "..4....86" "........." "....7.46." "629..8..." ".5...689." "........." ".....21.3"
  
  9 2 6 5 7 1 4 8 3$
  3 5 1 4 8 6 2 7 9$
  8 7 4 9 2 3 5 1 6$
  5 8 2 3 6 7 1 9 4$
  1 4 9 2 5 8 3 6 7$
  7 6 3 1 4 9 8 2 5$
  2 3 8 7 9 4 6 5 1$
  6 1 7 8 3 5 9 4 2$
  4 9 5 6 1 2 7 3 8$
  
  */
  
  
  
  
  # include <unistd.h>
  # include <stdio.h>
  
  
  void	ft_putchar(char c)			/* функция печати символа */
  {
  	write(1, &c, 1);
  }
  
  
  void	ft_putstr(char *str)		/* функция печати строки(массива символов) */
  {
  	while (*str)
  		ft_putchar(*str++);
  }
  
  
  /* Шаг 7 */
  /* печать решеного судоку. */
  void	display(char **tab)			/* Принимаем в "указатель на указатель" адресс
  									** массива с адрессами строк(массивами символов)) 
  									** которые мы хотим напечатать */
  {
  	int i;							/* обьявляем счетчик для перемещения от строки к строке в которых хранятся данные */
  	int j;							/* обьявляем счетчик для перемещения по самой строке(массиву символов) */
  
  	i = -1;							/* Инициализируем i единицей чтобы начать печать с этой строки
  									** по тому что если поставить ноль то мы начнем печать с имени программы:) */
  	ft_putchar('\n');			/* в конце печати массива символо делаем перенос строки на новую */
  	while (++i < 9)					/* создаем цикл для перемещения по всем девети строкам */
  	{
  		j = -1;						/* Инициализируем j нулем чтобы начать печать массива символов(строки) с нулевой позиции */
  		while (tab[i][++j])			/* Создаем цикл для печати массива символов пока не достигнем конца массива (строки) */
  		{
  			ft_putchar(tab[i][j]);	/* Печатаем символ */
  			if (j != 8)				/* если этот символ строки не последний то печатаем пробел */
  				ft_putchar(' ');
  		}
  		ft_putchar('\n');			/* в конце печати массива символо делаем перенос строки на новую */
  	}
  }
  
  
  /* ШАГ 6 */
  /* Проверка числа в блоке размером 3х3 */
  int		check_block(char **tab, int y, int x, char nb)/* Принимаем массив строк, координаты строки, координаты столбика, символ для проверки в кубе 3x3 */
  {
  	int i;										/* обьявляем переменную для счетчика координат 'y' */
  	int j;										/* обьявляем переменную для счетчика координат 'x' */
  
  	y -= (y % 3);								/* Высчитываем принадлежность 'y' к конкретному кубу из 9. И устанавливаем точку отсчета 'y' на начало этого куба */
  	x -= (x % 3);								/* Высчитываем принадлежность 'x' к конкретному кубу из 9. И устанавливаем точку отсчета 'x' на начало этого куба */
  	i = -1;										/* инициализируем счетчик количества пройденых строк куба 3x3 */
  	while (++i < 3)								/* запускаем цикл который пройдется по каждой строке куба 3x3 */
  	{
  		j = -1;									/* инициализируем счетчик количества пройденых ячеек куба 3x3 */
  		while (++j < 3)							/* запускаем цикл который пройдется по каждой ячейке каждой строки куба 3x3 */
  		{
  			if (tab[y][x++] == nb)				/* если похожий символ уже существует в кубе значит нужно искать другой */
  				return (0);						/* функция завершается возвращаая 0 */
  		}
  		x = x - 3;
  		y++;									/* если похожего символа на этой строке не нашли переходим к след строке куба и проверяем
  												** дальше пока не дойдем до конца */
  	}
  	return (1);									/* Если похожего символа по горизонтали нет значит все отлично, возвращаем 1 */
  }
  
  
  /* ШАГ 5 */
  /* Проверка числа по вертикали */
  int		check_column(char **tab, char nb, int x)/* Принимаем массив строк, символ для проверки, координаты столбика */
  {
  	int	i;										/* обьявляем переменную для счетчика */
  
  	i = -1;										/* инициализируем ее единицей т.к нужная нам строка начинаеться не с нулевой а с первой позиции и до 9 включительно */
  	while (++i < 9)								/* запускаем цикл который пройдется фиксированной нами ячейке в каждой сроке(проверив так по вертикали/столбиком) */
  	{
  		if (tab[i][x] == nb)					/* если похожий символ уже существует значит нужно искать другой */
  			return (0);							/* функция завершается возвращаая 0 */
  	}
  	return (1);									/* Если похожего символа по вертикали нет значит все отлично, возвращаем 1 */
  }
  
  
  /* ШАГ 4 */
  /* Проверка числа по горизонтали */				/* Принимаем массив строк, символ для проверки, координаты строки */
  int		check_line(char **tab, char nb, int y)
  {
  	int i;										/* обьявляем переменную для счетчика */
  
  	i = -1;										/* инициализируем ее нулем т.к нужые нам ячейки с символами начинаются с нулевой позиции и до 8 включительно */
  	while (++i < 9)								/* запускаем цикл который пройдется по каждой ячейке в зафиксированной нами строке(проверив так по горизонтали/строку) */
  	{
  		if (tab[y][i] == nb)					/* если похожий символ уже существует значит нужно искать другой */
  			return (0);							/* функция завершается возвращаая 0 */
  	}
  	return (1);									/* Если похожего символа по горизонтали нет значит все отлично, возвращаем 1 */
  }
  
  
  /* ШАГ 3 */
  /* здесь проходит решение Судоку */
  /*
  Чтобы пройти по всем ячейкам судоку 9х9 нужно вычислить координаты каждой ячейки.
  Представим судоку как массвив с 9 строками по 9 символов.
  Для этого используем переменные 'x' и 'y'.
  где 'x' будет хранить позицию нужного символа в строке(массиве символов).
  а   'y' будет хранить позицию нужной строки в массиве строк.
  а их вычислять мы будем так: 
  	y = position / 9;			так мы узнаем то какая строка нам нужна.
  	x = position % 9;			так мы узнаем какой символ в этой строке нужен.
  Так мы вычислим позицию первого символа первой строки.
  Потом мы увеличиваем position на один и снова вычисляем 'y' и 'x' уже из нового
  числа.Координаты будут указывать на след ячейку. 
  Эта система позволит нам пройтись по всем ячейкам каждой строки последовательно.
  
  ----------------------------------------------------------------------------------
  
  Пример.
  Вот что получиться при вычиследнии координат из каждого position:
  
  position 0 = array[0][0]; position 1 = array[0][1]; position 2 = array[0][2];
  position 3 = array[0][3]; position 4 = array[0][4]; position 5 = array[0][5];
  position 6 = array[0][6]; position 7 = array[0][7]; position 2 = array[0][8];
  
  position 9 = array[1][0]; position 10 = array[1][1]; position 11 = array[1][2]; 
  position 12 = array[1][3]; position 13 = array[1][4]; position 14 = array[1][5]; 
  position 15 = array[1][6]; position 16 = array[1][7]; position 17 = array[1][8]; 
  
  position 18 = array[2][0]; position 19 = array[2][1]; position 20 = array[2][2]; 
  position 21 = array[2][3]; position 22 = array[2][4]; position 23 = array[2][5]; 
  position 24 = array[2][6]; position 25 = array[2][7]; position 26 = array[2][8]; 
  
  position 27 = array[3][0]; position 28 = array[3][1]; position 29 = array[3][2]; 
  position 30 = array[3][3]; position 31 = array[3][4]; position 32 = array[3][5]; 
  position 33 = array[3][6]; position 34 = array[3][7]; position 35 = array[3][8]; 
  
  position 36 = array[4][0]; position 37 = array[4][1]; position 38 = array[4][2]; 
  position 39 = array[4][3]; position 40 = array[4][4]; position 41 = array[4][5]; 
  position 42 = array[4][6]; position 43 = array[4][7]; position 44 = array[4][8]; 
  
  position 45 = array[5][0]; position 46 = array[5][1]; position 47 = array[5][2]; 
  position 48 = array[5][3]; position 49 = array[5][4]; position 50 = array[5][5]; 
  position 51 = array[5][6]; position 52 = array[5][7]; position 53 = array[5][8]; 
  
  position 54 = array[6][0]; position 55 = array[6][1]; position 56 = array[6][2]; 
  position 57 = array[6][3]; position 58 = array[6][4]; position 59 = array[6][5]; 
  position 60 = array[6][6]; position 61 = array[6][7]; position 62 = array[6][8]; 
  
  position 63 = array[7][0]; position 64 = array[7][1]; position 65 = array[7][2]; 
  position 66 = array[7][3]; position 67 = array[7][4]; position 68 = array[7][5]; 
  position 69 = array[7][6]; position 70 = array[7][7]; position 71 = array[7][8]; 
  
  position 72 = array[8][0]; position 73 = array[8][1]; position 74 = array[8][2]; 
  position 75 = array[8][3]; position 76 = array[8][4]; position 77 = array[8][5]; 
  position 78 = array[8][6]; position 79 = array[8][7]; position 80 = array[8][8];
  
  ----------------------------------------------------------------------------------
  
  */
  int		sudoku(char **tab, int position)	/* Принимаем в "указатель на указатель" адресс
  											** массива с адрессами строк(массивами символов)) 
  											** а в переменную сохраняем число 9. Это стартовое число из
  											** которого будут высчитываться координаты отсчета для вычисления */
  {
  	int		y;								/* обьявим y который будет хранить координаты отсчета по горизонтали (position / 9 = 1)
  											** в 'y' мы будем хранит координаты нужной строки */
  	int		x;								/* обьявим x который будет хранить координаты отсчета по вертикали (position % 9 = 0)
  											** в 'x' мы будем хранит координаты нужного символа
  											** все вместе будет выглядеть так tab[y][x] */
  	char	nb;								/* обьявляем переменную для хранения символа который хотим поставить на место точки */
  
  	nb = '0';								/* Инициализируем символом '0' чтобы начать подставлять в пустую ячейку символы с 0 до 9 
  											** и проверяем верно ли найдено число с помощью функций(check_line, check_column, check_block) */
  	y = position / 9;						/* установим координаты отсчета по вертикали вниз*/ /*так мы узнаем какой символ в этой строке нужен.*/
  	x = position % 9;						/* установим координаты отсчета по горизонтали направо*/ /*так мы узнаем то какая строка нам нужна.*/
  	printf("(%d = %d x %d), ", position, y, x);
  	if (position == 80)						/* если position == 9 значит мы дошли до конца и заполнили все пустые ячейки */
  		return (1);							/* возвращаем 1 в функцию main и уже там переходим к распечатке решеного судоку */
  	if (tab[y][x] != '.')					/* Если ячейка уже заполнена переходим к следующей */
  		return (sudoku(tab, position + 1));	/* Рекурсивно вызываем снова эту функцию но уже смещая координаты на единицу */
  	while (++nb <= '9')
  	{
  		if (check_line(tab, nb, y) && check_column(tab, nb, x) && \
  			check_block(tab, y, x, nb)) 	/* проверяем есть ли совпадение этого число по горизонтали и вертикали */
  		{									/* если все отлично и таких совпадений нет то проверяем еще нет ли такого же числа в самом блоке(3x3) */
  			tab[y][x] = nb;					/* Если и тут все отлично то устанавливаем найденое нами число в эту ячейку */
  			if (sudoku(tab, position + 1))	/* И идем дальше. Снова рекурсивно вызываем эту функцию но уже смещая координаты на единицу */
  				return (1);
  		}
  	}
  	tab[y][x] = '.';						/* Если число для ячейки не найдено оставляем внутри точку */
  	return (0);								/* и возвращаем 0 завершая программу */
  }
  
  
  /* ШАГ 2 */
  /* Проверка задачи которую мы отправили на вход для решения */
  /* Проверяем все ли данные являются цифрами и не превышают они предел от 1 до 9 */
  int	check_grille(char **tab, int n)	/* Принимаем в "указатель на указатель" адресс
  									**  массива с адрессами строк(массивами символов)) 
  									** а в переменную - количество аргументов отправленное в программу через
  									** терминал. С учетом самого имени программы их должно быть ровно 10 */
  {
  	int i;							/* обьявляем счетчик для перемещения от строки к строке
  									** в которых хранятся данные задачи для проверки */
  
  	int j;							/* обьявляем счетчик для перемещения по самой строке(массиву символов) */
  
  	i = -1;							/* Инициализируем i единицей чтобы начать проверку с этой строки
  									** по тому что если поставить ноль то мы начнем с того места где 
  									** в терминале написано имя программы а нам нужны строки с данными задачи :)
  									** т.е tab[1][0]. Именно с этого места начинается строка с
  									** заданием после имени программы которую мы написали в терминале */
  	if (n != 9)						/* Проверяем равно ли десяти количество аргументов из терминала */
  		return (0);
  	while (++i < 9)					/* Создаем цикл который проходит по каждой строке начиная с первой(не нулевой!)(их 10)
  									** Получится что мы будем проходить по 9-ти ячейкам в каждой из 9-ти строк (9x9)*/
  	{
  		j = -1;						/* инициализируем счетчик для перемещения по строке и проверке каждого символа */
  		while (tab[i][++j])			/* создаем цикл который проверит каждый символ [j] каждой строки[i] 
  									** в массиве строк tab(указателе на указатели хранящем дреса строк(массивы символов)) */
  		{
  			if ((tab[i][j] < '1' || tab[i][j] > '9') && tab[i][j] != '.') /* проверяем каждый символ */
  				return (0);			/* если что то не так возвращаем ноль(т.е данные не корректны) */
  		}
  		if (j != 9)					/* если количество символов в строке не равно 9 то возвращаем ноль(т.е данные не корректны) */
  			return (0);
  	}
  	return (1);						/* если все отлично и все строки проверены и ошибок нет то возвращаем 1; */
  }
  
  
  /* ШАГ 1 */
  int		main(int argc, char **argv)
  {
  	if (check_grille(argv + 1, argc - 1))/* (Шаг 2)проверяем решетку с символами если все норм продолжаем */
  	{
  		if (sudoku(argv + 1, 0))		/* (Шаг 3)Переходим к решению Судоку, если все норм идем дальше 
  										** отправляем на заполнение в функцию массив и стартовой число для
  										** вычисления координат строк и их ячеек, чтобы пройтись по всем */
  			display(argv + 1);			/* (Шаг 7)Печатаем наше решение*/
  		else
  			ft_putstr("Error\n");		/* Если судоку не решилось выводим сообщение */
  	}
  	else
  		ft_putstr("Error\n");			/* Если решетка проверку не прошла выводим сообщение */
  	return (0);
  }
  