[CodeWars] 알고리즘 Snail

Sal Jeong·2022년 5월 17일
0

Snail sort kata 4

https://www.codewars.com/kata/521c2db8ddc89b9b7a0000c1/train/javascript

문제 자체는 어렵지 않았지만, 꽤 어려운 문제였다.

1. 문제 정보

  1. 데이털형은 매트릭스 형 어레이의 집합이다.
  2. 모든 값은 숫자이다.
  3. 스네일 소트란 매트릭스를 시계방향으로 값을 flatten한다.

e.g.)
1 2 3
4 5 6
7 8 9

의 매트릭스 형 어레이가 있다면,

리턴값은 [1,2,3,6,9,8,7,4,5] 이다.

2. 해결 방법

두 가지 방법으로 해결할 수 있을 것 같다.

  1. 위 정보 대로하면 달팽이는 시계방향으로, 왼쪽, 아래, 오른쪽, 위로 움직인다. 이에 맞춰서 for loop을 만든다.
  2. 매트릭스 자체를 회전시킨다.
  3. 주의, 기존 매개변수의 값을 계속해서 빼줘야 추가적인 for loop 실행을 막을 수 있을 것이다.

3. 해결한 코드

snail = function(array) {
  const order = ['left', 'down', 'right', 'up'];
  
  // 달팽이의 움직임 순서를 먼저 정한다.
  
  let i = 0;
  
  // 위 i값은 계속해서 초기화된다.(모든 숫자가 소팅될 때 까지)
  
  let factor = array.slice();
  let result = [];
  
  if(array.length <= 1){
    return array[0]
  }
  
  // while loop를 통해 계속해서 달팽이가 움직이게 해준다.
  
  while(true){
    if(factor.length <= 0){
          break;
    }
    
    // switch 문을 사용해서, 위 지정해놓은 방향을 돌아가게 해준다.
    // 방향에 따라 function을 작성하고, 소팅된 어레이와 남은 매트릭     // 스를 리턴하게끔 한다.
    
    switch(order[i]){
        default: return result;
        case 'left':
          const left = goLeft(result, factor)
          result = left[0]
          factor = left[1]
          i = i + 1
          continue
        case 'right':
          const right = goRight(result, factor)
          result = right[0]
          factor = right[1]
          i +=1
          continue
        case 'down':
          const down = goDown(result, factor)
          result = down[0]
          factor = down[1]
          i +=1
          continue
        case 'up':
          const up = goUp(result, factor)
          result = up[0]
          factor = up[1]
          i = 0;
          continue
        
    }
  }
  return result;
}

// 방향을 돌아갈 때 잡아주는 펑션들

function goLeft(result, factor){
  const output = (factor[0].map((item) => item))
  const leftover = factor.filter((item, index) => index !== 0)
  return [result.concat(output), leftover];
}

// 왼쪽의 경우. 첫번째 어레이 전체를 순서대로 소팅함.

function goDown(result, factor){
  const output = (factor.map((item) => (item[item.length -1])))
  const leftover = factor.map((item) => item.slice(0,-1))
  return [result.concat(output), leftover];
}

// 아래의 경우. 모든 어레이의 맨 마지막 값을 위에서 아래로 소팅함.

function goRight(result, factor){
  const output = factor[factor.length -1].reverse().map((item) => item)
  const leftover = factor.filter((item, index) => index !== factor.length -1 )
  return [result.concat(output), leftover ];
}

// 오른쪽의 경우, 맨 마지막 어레이를 반대 순서로 소팅한다.

function goUp(result, factor){
  const output = factor.reverse().map((item) => (item[0]))
  const leftover = factor.reverse().map((item, index) => item.slice(1))
  return [result.concat(output), leftover]
}

// 위의 경우, 매트릭스 어레이의 첫번째 값을 아래에서 위 순서로 소팅한다.

개념이 어렵다기 보단 어떻게 코딩할까가 어려운 문제였다...
아니 이게 어려운 개념인것일 수도 있겠다.
실제로 다른 사람의 답안을 보니 아주 간결하고 멋있더라.

const snail = function(array) {
  const list = [];

  while(array.length) {
    list.push(...array.shift(), ...array.map(row => row.pop()));
    
     array.reverse().map(row => row.reverse());
  }

  return list;
}

이런식으로 실제로 매트릭스를 돌려가며 풀 수도 있었다.
코딩의 세계는 어렵다...

profile
Can an old dog learn new tricks?

0개의 댓글