CS Hiring Assessments 코드 분석

nyongho·2020년 12월 19일
0

내용 정리

목록 보기
3/6
post-thumbnail

CS Hiring Assessments 레퍼런스 코드 분석


1) DS-QUEUE

queue 구조는 선입선출 (First In First Out) 구조 이다.

1) 내가 푼 방식

1. Queue

배열과 객체 중 나는 좀 더 쉽게 구현할 수 있는 배열을 선택했다.

2. Queue.prototype.add

선입선출의 구조를 띄고 있으므로 먼저 들어온 요소를 기준으로 그 뒤에 요소들이 추가 되어야 한다.

따라서 Array.prototype.push 메소드를 사용했다.

3. Queue.prototype.remove

삭제 될 때는 먼저 들어온 요소 순서대로 삭제되야 한다.

따라서 Array.prototype.shift 메소드를 사용했다.

❗️ 단, shift 한 최종 arr 을 리턴해야 해서 return 을 사용해줬다.


2) 레퍼런스 방식

객체를 이용해 자바스크립트에 이미 존재하는 메소드들을 사용하지 않고 새로운 메소드를 만든 모습이다.

아예 모든 메소드들을 구현 할 생각을 하다니.. 나의 생각에서 두 발짝은 더 나아간 코드들이다.

Queue.prototype.add = function(item) {
  this.storage[this.length + this.firstIndex] = item;
  // storage ({}) 에 ? : item 할당
  this.length++;
  // 하나 추가 했으니 Queue 길이 ++
};

Queue.prototype.remove = function() {
  if (this.length <= 0) {
    return undefined;
    // 더이상 지울게 없으면 undefined 리턴
  }

  let rmvItem = this.storage[this.firstIndex];
  // rmvItem 에 지우기 전 값 저장
  delete this.storage[this.firstIndex];
  // 그 다음 지우고
  this.firstIndex++;
  // 하나 지워줬으니 첫 인덱스는 다음 값으로 지정
  this.length--;
  // 하나 삭제 했으니 Queue 길이 --
  return rmvItem;
  // 미리 저장한 rmvItem을 리턴함으로써 해당 값을 삭제했다고 말해준다.
};

let queue = new Queue;
queue.add(1)
queue.add(2)
queue.remove()
console.log(queue)

2) JS-Inheritance-pseudo-classical

Functional 패턴으로 작성 된 것을 Pseudoclassical 패턴으로 리팩토링 해야 한다.

1. 내가 푼 방식

이건 레퍼런스랑 내 코드가 거의 동일해서 그냥 내 코드와 각 주석들을 첨부하겠다.


// FlyingHorse 의 prototype 을 object.create() 를 통해 부모의 프로토타입으로 변경 후
// constructor 를 자기 자신으로 바꿈으로써 원하는 프로토타입 체인을 명확하게 해준다.

// Horse 와 FlyingHorse 에 각각 goSomewhere 메소드 추가

// functional 에서 oldGoSomewhere(destination); 은 부모의 메소드를 호출한 것.
// 따라서 pseudoclasscial 에서는 Horse 에서 call 을 통해 goSomewhere 메소드를 불러온다


var Horse = function(name) {
  this.name = name;
};

Horse.prototype.goSomewhere = function (destination){
  return this.name + ' is galloping to ' + destination + '!';
}

var FlyingHorse = function(name, color) {
  this.name = name;
  this.color = color;
};

FlyingHorse.prototype = Object.create(Horse.prototype);
FlyingHorse.prototype.constructor = FlyingHorse;
// 사실 위의 consturctor 를 명확하게 해주는 작업은 '불필요'하다고 볼 수 있다.
// constructor 생성자를 굳이 재설정하지 않아도 우리가 원하던 결과는 그대로 나오게 된다.
// FlyingHorse 의 constructor 를 재설정하지 않으면 constructor 는 Horse 를 가리키지만
// 위와 같이 바꿔준다면 constructor 는 FlyingHorse 를 가리킨다.
// 하지만 굳이 해주는 이유는 우리는 다른 변화 없이 오직 "Horse 의 프로토타입만을 받아오길 원하기 때문이다." 라고 할 수 있겠다.


FlyingHorse.prototype.goSomewhere = function (destination, milesToDestination) {
  if (milesToDestination < 10) {
    return Horse.prototype.goSomewhere.call(this, destination);
  } else {
    return this.name + ' is flying to ' + destination + '!';
  }
};

3) Recursion-Print-Array

배열을 입력받아 배열의 요소 하나하나를 console.log 를 통해 리턴해야 한다.

나는 테스트케이스에 [1,2,3,4,5] 를 입력받으면 12345 를 리턴해야 한다고 써있길래 그냥 다음과 같이 작성했다.

1. 내가 푼 방식

var printArray = function(arr) {
  let arrToStr = arr.toString(); // 우선 문자로 바꿔주고
  let joinBeforeSplit = arrToStr.split(',').join(''); // , 기준으로 나누고 합쳐줬다.
  console.log(joinBeforeSplit); // 그리고 이 값을 console.log 해줬다.
};

2. 레퍼런스 방식

근데 사실 코드스테이츠는 이러한 결과를 원한게 아니었다는걸 레퍼런스 보고 알았다 ㅋㅋㅋㅋㅋㅋㅋ 그니까 문제의 뜻 그대로 재귀를 통해 배열의 요소를 하나하나씩 출력하는걸 원한 것 이다.

예를 들어 [1,2,3,4,5] 를 입력받으면

1
2
3

이런식으로 콘솔에 찍히길 원한 것 같다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 어우 이렇게 되면 나는 편법을 쓴건데... 😂

우선 코드를 하나하나 분석해보겠다.

var printArray = function() {
  function _print(targetArr) { // [1,2,3] 전달
    if (targetArr.length === 0) { // 아무것도 전달안됐으면 함수 종료
      return;
    } else { // 그 외에는
      let temp = targetArr[0]; // 우선 배열의 0번 요소를 변수에 저장

      if (Array.isArray(temp)) { // 요소가 배열인 경우
        _print(temp); // 재귀를 통해 let temp 이거 다시 해준다
        _print(targetArr.slice(1)); // 그리고 다음거 재귀!
      } else if (temp) { // 요소가 그냥 뭐 숫자거나 그러면
        console.log(temp); // 해당 요소 콘솔 로그
        _print(targetArr.slice(1)); // 그리고 다음거 재귀!
      } else { // 그 외에 애들은
        _print(targetArr.slice(1)); // 다음거 재귀!
      }
    }
  }

  _print(arguments[0]); // 함수 실행시 전달 받은 인수의 0번째를 파라미터로 전달한다.
};

printArray([1,2,3])

1
2
3

4) this-Keyword

this 키워드를 이용해 sport 객체 내에 있는 players 의 value 를 가져와
["Lebron James plays basketball", "Kevin Durant plays basketball"] 이런 식으로 리턴해라.

함수 내에서 this 는 생성자, 즉 객체 (sport)를 가리킨다. 이 점을 활용해서 풀었다.

1. 내가 푼 방식

var sport = {
  name: "basketball",
  players: [
    { name: "LeBron James", age: 31 },
    { name: "Kevin Durant", age: 28 }
  ],
  playerNames: function() {
    // 1. this 를 이용해 players 와 name 을 가져온다.
    // 2. 배열 하나 만들어줘서
    // 3. for 문을 통해 배열에 테스트에 맞는 값을 넣어줬다.
    // 4. 마지막으로 해당 배열 리턴!
  }
};

2. 레퍼런스 방식

역시.. 레퍼런스 코드는 항상 볼 때마다 참신하다. 굳이 나처럼 일일이 변수로 선언해주지도 않고 한 줄에 끝내버린다. map 을 활용해 해당 이름을 받아와 뒤에 "plays basketball" 만 붙혀준 모습이다. 이런 코드들을 보면 물론 무조건적으로 짧은 코드가 좋다고는 할 수 없단걸 알지만 그래도 뭐랄까.. 짧음에서 나오는 간지가 느껴진달까.. 하여간 그런 느낌이 든다.


5) tree-map

Tree 구조를 구현해야 하며 addChild, map 메소드를 구현해야 한다.

1) 내가 푼 방식

1. addChild

파라미터를 받으면 new Tree 를 통해 새로운 트리를 만들어 주고 기존 Tree 의 children 에 새로운 트리를 넣어줬다. 그리고 그 값을 리턴해줬다.

2. map

callback 함수에 의해 변경된 새로운 트리들을 리턴해야 한다.

따라서 새로운 트리의 value 에는 기존 value 에 callback 함수를 적용한 결과를, 새로운 트리의 children 에는 map 을 이용해 기존 children 에 callback 을 매핑한 결과를 넣어주고 새로운 트리를 리턴했다.


2) 레퍼런스 방식

1. addChild

나랑 비슷해서 넘어가겠다.

2. map

나와 다른점은 레퍼런스는 reduce 를 사용한 점이었다. 동작은 동일하게 한다.


💻 Overall

이번 CS Hiring Assessments 문제를 풀면서 느낀 것은 생각보다 문제 난이도가 어렵지 않다 라는 생각이었다. 솔직히 그전에 배운 개념들의 기초 버전이라고 생각될 정도였고 각 문제들을 푸는데 크게 고민을 하지는 않았다. (9시에 시험을 보기 시작해서 12시 전에 끝냈으니 말 다했지) 그런데 슬랙 채널에서 다른 분들은 이번 시험이 어려웠다고 하시는 분들도 많아서 오히려 그 점이 더 의아했던 것 같다. 분명 나는 지금 IM 기수중에서 그렇게 실력이 뛰어나지 않은 편에 속한다고 생각했는데 꽤 많은 인원이 살려줘요! 라는 이모지를 단 걸 봤을 때 "그래도 내가 이전에 블로깅하면서 이해하고, 복습했던 것이 여기서 빛을 바래는구나!" 라는 생각이 들었다. 하지만 지금 당장 결과가 좋다고 해서 긴장의 끈을 놓는 것은 또 다시 나를 기수이동의 구렁텅이로 빠트릴 가능성이 크다. 따라서 현재에 안주하지 않고, 앞으로 남아있을 나머지 스프린트들을 위해 더욱 노력할 것이다.

profile
두 줄 소개

0개의 댓글