Validate Sudoku with size `NxN`

SungJunEun·2021년 11월 17일
0

Codewars 문제풀이

목록 보기
17/26
post-thumbnail

Description:

Given a Sudoku data structure with size NxN, N > 0 and √N == integer, write a method to validate if it has been filled out correctly.

The data structure is a multi-dimensional Array, i.e:

[
  [7,8,4,  1,5,9,  3,2,6],
  [5,3,9,  6,7,2,  8,4,1],
  [6,1,2,  4,3,8,  7,5,9],

  [9,2,8,  7,1,5,  4,6,3],
  [3,5,7,  8,4,6,  1,9,2],
  [4,6,1,  9,2,3,  5,8,7],

  [8,7,6,  3,9,4,  2,1,5],
  [2,4,3,  5,6,1,  9,7,8],
  [1,9,5,  2,8,7,  6,3,4]
]

Rules for validation

  • Data structure dimension: NxN where N > 0 and √N == integer
  • Rows may only contain integers: 1..N (N included)
  • Columns may only contain integers: 1..N (N included)
  • 'Little squares' (3x3 in example above) may also only contain integers: 1..N (N included)

My solution:

var Sudoku = function(data)
{
	let sortedArray = [];
  const N = data.length;
  for(l=1;l<N+1;l++) {
    sortedArray.push(l);
  }

  function notNumber(array) {
    for (k=0;k<array.length;k++) {
      if(typeof(array[k]) != "number") {
        return true;
      }
    }
    return false;
  }

  function checkDimension(data) {
    for(i of data) {
      if(i.length != N) {
        return false;
      } else if(i == 0) {
        return false;
      } else if(notNumber(i)) {
        return false;
      }
    }
    return true;
  }

  function ifIncludes(a, b) {
    return a.every(element=>b.includes(element)) && b.every(element=>a.includes(element)) ;
  }

  function checkRow(data) {
    for(i of data) {
      if(!ifIncludes(i,sortedArray)) {
        return false;
      }
    }
    return true;
  }

  let columnArray = [];
  function checkColumn(data) {
    for(i of data) {
      for(j=0;j<i.length;j++) {
        if(!columnArray[j]) {
          columnArray[j] = [];
          columnArray[j].push(i[j]);
        } else {
          columnArray[j].push(i[j]);
        }
      }
    }
    for(i of columnArray) {
      if(!ifIncludes(i,sortedArray)) {
        return false;
      }
    }
    return true;

  }

  let boxArray = [];
  function checkBox(data) {
    const n = Math.sqrt(N);
    if(!Number.isInteger(n)) {
      return false;
    }
    for (let m=0;m<N;m++) {
      let q = parseInt(m / n) * n;
      let d = m % n * n;
      if(!boxArray[m]) {
        boxArray[m] = [];
      }

      for(j=q;j<q+n;j++) {
        for(k=d;k<d+n;k++) {
          boxArray[m].push(data[j][k]);
        }
      }
    }

    for(i of boxArray) {
      if(!ifIncludes(i,sortedArray)) {
        return false;
      }
    }
    return true;
  }

return {
    isValid: function() {
			return (checkDimension(data) &&  checkRow(data) && checkColumn(data) && checkBox(data));
    }
  };
};

Best solutions:

길이가 N-1인 배열이 1~N을 모두 포함하는지 알아내는법

function checkArray(array){
	const copy = array.slice(0); // 1
	copy.sort(function(a,b){
		return a - b;
	}); // 2
	return copy.every(function(val,index){
		return index + 1 === val;
	}); // 3
}
  1. array.slice(begin, end)

    array의 begin부터 end까지에 대한 깊은 복사 같은 얕은 복사를 새로운 배열로 반환한다. 깊은 복사처럼 보이지만, 중첩된 구조를 변경하게 되면 원본도 함께 변한다.

    const arr = [1, 2, [3, 4]];
    const copied = arr.slice();
    copied.push(6);
    console.log(copied == array); // false (깊은 복사됨)
    copied[2].push(5);
    console.log(copied == array); // false (실제로는 얕은 복사임)
  • end

    생략되면 자동으로 배열의 끝까지 추출한다.

    이러한 이유로 array.slice(0)을 하게 되면 array의 처음부터 끝까지 얕은 복사를 하게 된다.

  • 번외; 깊은 복사는?

    추후 공부가 필요함!

  1. array.sort(compareFunction)

    배열의 요소를 적절한 위치에 정렬한 후 배열을 반환한다.

    • compareFunction

      compareFunction이 주어지지 않았을 때는 default값으로 유니코드 코드 포인트 값을 따른다.

      배열을 오름차순으로 정렬하려면 다음과 같이 작성한다.

        function compareNumber(a,b) {
        	return a-b;
        }
  1. array.every(callbackFn)

    callbackFn이 배열 안의 모든 요소에 대하여 true이면 true를 반환한다.

    • callbackFn(element, index, array)

      index와 array는 optional이다.

profile
블록체인 개발자(진)

0개의 댓글