본문 바로가기
BEB/algorithm

Toy06 - Sudoku

by ddanss 2022. 11. 2.
728x90

으아... 자바스크립트... STL...해.줘...

레퍼런스 코드 분석입니다.

//대충 어떤느낌이냐면
//우리는 board에서 0인 부분만 채워넣으면 되잖아요?
//그니까 [0,0]부분부터 보면
//[0,0]부분이 4랑 5가 가능 하잖아요
//그러면 일단 [0,0]을 4로 가정하고
//이제 [0,2]로 가보는거에요
//그럼 [0,0]은 4니까 [0,2]는 5밖에 안되는거죠?
//그럼 이제 [0,0]은 4, [0,2]는 5
//이제 [0,5]로 향하는거에요
//aux가 재귀인데 이렇게 돌아간다고 생각하면 됩니다.

//근데 만~~약에 [0,0]부분이 4가 아니였어요!
//그러면 4를 사용했다는 흔적을 싹 지워버리고
//[0,0]가 5라고 생각하고 또 프로그램을 돌리는거에요

const sudoku = function (board) {
  const N = board.length;
  //boxes의 해당 값은 3*3의 자리를 표시
  const boxes = [
    [0, 0, 0, 1, 1, 1, 2, 2, 2],
    [0, 0, 0, 1, 1, 1, 2, 2, 2],
    [0, 0, 0, 1, 1, 1, 2, 2, 2],
    [3, 3, 3, 4, 4, 4, 5, 5, 5],
    [3, 3, 3, 4, 4, 4, 5, 5, 5],
    [3, 3, 3, 4, 4, 4, 5, 5, 5],
    [6, 6, 6, 7, 7, 7, 8, 8, 8],
    [6, 6, 6, 7, 7, 7, 8, 8, 8],
    [6, 6, 6, 7, 7, 7, 8, 8, 8],
  ];
  //getBoxNum = boxes의 row,col에 해당하는 값을 가져오는 함수
  //즉, 3*3의 위치를 가져옴
  const getBoxNum = (row, col) => boxes[row][col];
  const blanks = []; //0인 숫자들을 배열에 넣은것
  const rowUsed = []; //해당 행에서 숫자를 사용했는지 여부 
  const colUsed = []; //해당 열에서 숫자를 사용했는지 여부 
  const boxUsed = []; //3*3박스에서 숫자를 사용했는지 여부
  for (let row = 0; row < N; row++) {
    rowUsed.push(Array(N + 1).fill(false));
    colUsed.push(Array(N + 1).fill(false));
    boxUsed.push(Array(N + 1).fill(false));
  }
  //여기서rowUsed, colUsed, boxUsed는
  //false, true, true, true, true ~~~~  
  //false, true, true, true, true~~~~
  //이런 형식으로 됨.
  //맨앞이 false인 이유는 0은 딱히 의미가 없으니까요!

  //0인 숫자는 blanks배열에 넣어주고
  //0이 아닌 숫자는 행, 열, 박스에서 사용되었다고 true로 표시해주기
  for (let row = 0; row < N; row++) {
    for (let col = 0; col < N; col++) {
      if (board[row][col] === 0) { //입력된 배열의 값이 0이면
        blanks.push([row, col]); //0에 해당하는 row와 col을 blanks배열에 넣음
      } 
      else { //입력된 배열의 값이 0이 아니면
        const num = board[row][col]; //num에 입력된 배열에 해당하는 값 넣어주고
        const box = getBoxNum(row, col); //boxes에 해당하는 값을 넣어줌
        rowUsed[row][num] = true; //해당 행에서 숫자를 사용했다고 표시
        colUsed[col][num] = true; //해당 열에서 숫자를 사용했다고 표시
        boxUsed[box][num] = true; //3*3작은 박스 기준에서 숫자를 사용했다고 표시
      }
    }
  }

  //이 함수는 num이 사용됐는지 안됐는지 확인하는 함수
  const isValid = (row, col, num) => {
    const box = getBoxNum(row, col);
    return (
      rowUsed[row][num] === false && //해당 행에서 숫자가 사용됐는지
      colUsed[col][num] === false && //해당 열에서 숫자가 사용됐는지
      boxUsed[box][num] === false //3*3의 박스에서도 숫자가 사용됐는지 판단
      //어디서도 사용되지 않았으면 return true~
      //잘 기억하셈. !!사용되지 않았으면!! true임
    );
  };
  //단순히 배열들을 다시 초기화해주는 함수
  const toggleNum = (row, col, num) => {
    const box = getBoxNum(row, col);
    board[row][col] = num;
    rowUsed[row][num] = !rowUsed[row][num]; //행을 false <-> true
    colUsed[col][num] = !colUsed[col][num]; //열을 false <-> true
    boxUsed[box][num] = !boxUsed[box][num]; //박스를 false <-> true
  };
  
  //이 함수가 실제로 스도쿠 돌아가는 재귀함수여요
  const aux = (idx, blanks, board) => {//인덱스, 0들이 있는 배열, 입력배열
    //이 if문은 탈출문.
    //입력된 배열의 0인 숫자의 개수만큼 돌았으면 끝나게 구현됐음
    //이게 어떤 의미냐면
    //[0,0]이 4라고 가정하고, [0,2]가 5라고 가정하고~~~~
    //이걸 계속 해서 마지막 [8,8]까지 한번 다 돌았다는 뜻임.
    if (idx === blanks.length) {
      return true;
    }

    const [row, col] = blanks[idx]; //행,열은 blanks의 idx
    for (let num = 1; num <= 9; num++) { //1부터 9까지 돌면서
      if (isValid(row, col, num) === true) { //행과 열에서 숫자가 쓰이지 않았으면
        toggleNum(row, col, num); //사용되었다고 바꾸고
        //이 아래 if문과 그 밑줄의 toggleNum의 역할은
        //만약에 첫번째 예시처럼 [0,0]자리에 들어갈 수 있는 숫자가 4,5라고 치면
        //[0,0]자리를 4로 가정하고 나머지 자리를 돌린다음에
        //그게 안되면 다시 [0,0]으로 돌아와서 
        //[0,0]이 5일때를 가정하고
        //다시 들어가는 느낌임!
        if (aux(idx + 1, blanks, board) === true) {
          return true;
        }
        //이 자리가 4가 아니라면 다시 4를 사용하지 않았다고 해줘야하니까
        //이 toggleNum으로 사용하지 않았다고 바꿔주는거
        toggleNum(row, col, num);
      }
    }
    return false;
  };

  aux(0, blanks, board); //위에는 어찌보면 다 세팅이고 이게 정말 함수들을 돌리는거.
  return board;
};
반응형

'BEB > algorithm' 카테고리의 다른 글

백트래킹  (0) 2022.11.03
Toy07 - tree dfs  (0) 2022.11.02
타일링 tiling  (0) 2022.10.31
[js] 버블정렬  (0) 2022.10.28
[javaScript/자바스크립트]부분집합인지 확인  (0) 2022.10.27

댓글