https://www.acmicpc.net/problem/2164

 

2164번: 카드2

N장의 카드가 있다. 각각의 카드는 차례로 1부터 N까지의 번호가 붙어 있으며, 1번 카드가 제일 위에, N번 카드가 제일 아래인 상태로 순서대로 카드가 놓여 있다. 이제 다음과 같은 동작을 카드가

www.acmicpc.net

문제

N장의 카드가 있다. 각각의 카드는 차례로 1부터 N까지의 번호가 붙어 있으며, 1번 카드가 제일 위에, N번 카드가 제일 아래인 상태로 순서대로 카드가 놓여 있다.

이제 다음과 같은 동작을 카드가 한 장 남을 때까지 반복하게 된다. 우선, 제일 위에 있는 카드를 바닥에 버린다. 그 다음, 제일 위에 있는 카드를 제일 아래에 있는 카드 밑으로 옮긴다.

예를 들어 N=4인 경우를 생각해 보자. 카드는 제일 위에서부터 1234 의 순서로 놓여있다. 1을 버리면 234가 남는다. 여기서 2를 제일 아래로 옮기면 342가 된다. 3을 버리면 42가 되고, 4를 밑으로 옮기면 24가 된다. 마지막으로 2를 버리고 나면, 남는 카드는 4가 된다.

N이 주어졌을 때, 제일 마지막에 남게 되는 카드를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 정수 N(1 ≤ N ≤ 500,000)이 주어진다.

출력

첫째 줄에 남게 되는 카드의 번호를 출력한다.

예제 입력 1 복사

6

예제 출력 1 복사

4

 

문제풀이(1) - 실패

1. 제일 위에 있는 카드를 바닥에 버린다.
2. 제일 위에 있는 카드를 제일 아래에 있는 카드 밑으로 옮긴다.
3. 1~2를 반복한다.
4. 마지막에 남는 카드를 return 한다.
N = 4, 1234 -> 234 -> 342 -> 42 -> 24 -> 4
1부터 시작해서 홀수 일경우 제일 첫 카드 제거, 짝수 일 경우 제일위에 있는 카드를 맨밑으로 이동

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";

const input = Number(require("fs").readFileSync(filePath).toString().trim());

const shuffle = (cardCount) => {
  const arr = Array.from({ length: cardCount }, (v, i) => i + 1);

  let count = 1;
  while (arr.length > 1) {
    let popNum = arr.shift();
    if (!(count % 2)) {
      arr.push(popNum);
    }
    count++;
  }
  return arr[0];
};

console.log(shuffle(input));

 

문제풀이(2)

pop, push를 하는 과정에서 시간이 많이 소요되는 것을 알 수 있다. (O(n^2))
pop을 하지않고 push만 할 경우 O(1)로 간단해질 수 있다. -> 단점 공간복잡도 증가
메모리 28808kb, 시간 240ms

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";

const input = Number(require("fs").readFileSync(filePath).toString().trim());

const shuffle = (cardCount) => {
  const arr = Array.from({ length: cardCount }, (v, i) => i + 1);

  let count = 0;

  while (arr.length !== count) {
    if (count % 2) {
      arr.push(arr[count++]);
    } else {
      count++;
    }
  }

  return arr.at(-1);
};

console.log(shuffle(input));

 

문제풀이(3)

다른 풀이로 링크드리스트를 사용해서 풀수 있다는 것을 보게되어서 차근차근 구현해보았다.
메모리 89072kb, 시간 416ms로 2~3배가량 높은 수치가 나왔다.
중간 삽입 및 삭제가 효율적인 링크드 리스트로 사용해봤지만 좋지 않은 결과였다...
메모리, 접근시간, 구현 복잡도등이 다 높았기 때문이다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";

const input = Number(require("fs").readFileSync(filePath).toString().trim());

class Node {
  constructor(value) {
    this.value = value;
    this.next = null;
    this.prev = null;
  }
}

// push, pop, get을 구현해야함
class LinkedList {
  constructor() {
    this.head = null;
    this.tail = null;
    this.length = 0;
  }

  // 노드에 값 추가하기
  add(value) {
    const newNode = new Node(value);

    if (!this.head) {
      this.head = newNode;
    } else {
      this.tail.next = newNode;
      newNode.prev = this.tail;
    }

    this.tail = newNode;
    this.length++;

    return newNode;
  }

  // 첫 노드값 가져오기
  getHead() {
    return this.head.value;
  }

  // 첫 노드 제거하기
  removeHead() {
    this.head = this.head.next;
    this.head.prev = null;
    this.length--;
  }

  // 노드 길이 가져오기
  getLength() {
    return this.length;
  }
}

const node = new LinkedList();

for (let i = 1; i <= input; i++) {
  node.add(i);
}

while (node.getLength() !== 1) {
  node.removeHead();
  node.add(node.getHead());
  node.removeHead();
}

console.log(node.getHead());

https://www.acmicpc.net/problem/1018

 

1018번: 체스판 다시 칠하기

첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

www.acmicpc.net

문제

지민이는 자신의 저택에서 MN개의 단위 정사각형으로 나누어져 있는 M×N 크기의 보드를 찾았다. 어떤 정사각형은 검은색으로 칠해져 있고, 나머지는 흰색으로 칠해져 있다. 지민이는 이 보드를 잘라서 8×8 크기의 체스판으로 만들려고 한다.

체스판은 검은색과 흰색이 번갈아서 칠해져 있어야 한다. 구체적으로, 각 칸이 검은색과 흰색 중 하나로 색칠되어 있고, 변을 공유하는 두 개의 사각형은 다른 색으로 칠해져 있어야 한다. 따라서 이 정의를 따르면 체스판을 색칠하는 경우는 두 가지뿐이다. 하나는 맨 왼쪽 위 칸이 흰색인 경우, 하나는 검은색인 경우이다.

보드가 체스판처럼 칠해져 있다는 보장이 없어서, 지민이는 8×8 크기의 체스판으로 잘라낸 후에 몇 개의 정사각형을 다시 칠해야겠다고 생각했다. 당연히 8*8 크기는 아무데서나 골라도 된다. 지민이가 다시 칠해야 하는 정사각형의 최소 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

출력

첫째 줄에 지민이가 다시 칠해야 하는 정사각형 개수의 최솟값을 출력한다.

예제 입력 1 복사

8 8
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBBBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW

예제 출력 1 복사

1

예제 입력 2 복사

10 13
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
WWWWWWWWWWBWB
WWWWWWWWWWBWB

예제 출력 2 복사

12

 

문제풀이(1)

8x8의 체스판은 흰색과 검은색으로 칠하는데 번갈아서 칠해져 있어야 한다.
다시 칠했을 경우 8x8의 정사각형의 최소 개수를 구하는 문제.

정상적인 체스판을 시작이 검은색인것 하나 흰색인거 하나 총 2개를 만든다.
8x8의 체스판으로 쪼개서 확인했을 때 변경해야할 부분이 몇개인지 찾는 로직을 구현한다.
주어진 체스판 내에서 반복순회한다. (브루트포스 문제)

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";

const input = require("fs").readFileSync(filePath).toString().trim().split("\n");

const [N, M] = input.shift().split(" ").map(Number);

const whiteStartBoard = [
  "WBWBWBWB",
  "BWBWBWBW",
  "WBWBWBWB",
  "BWBWBWBW",
  "WBWBWBWB",
  "BWBWBWBW",
  "WBWBWBWB",
  "BWBWBWBW",
];

const blackStartBoard = [
  "BWBWBWBW",
  "WBWBWBWB",
  "BWBWBWBW",
  "WBWBWBWB",
  "BWBWBWBW",
  "WBWBWBWB",
  "BWBWBWBW",
  "WBWBWBWB",
];

const answer = [];

// 정상적인 보드인지 체크하는 함수
const boardCheck = (x, y, colorBoard) => {
  let count = 0;

  for (let i = y; i < y + 8; i++) {
    for (let j = x; j < x + 8; j++) {
      if (input[i][j] !== colorBoard[i - y][j - x]) {
        count++;
      }
    }
  }

  return count;
};

for (let i = 0; i + 7 < N; i++) {
  for (let j = 0; j + 7 < M; j++) {
    answer.push(boardCheck(j, i, whiteStartBoard));
    answer.push(boardCheck(j, i, blackStartBoard));
  }
}

console.log(Math.min(...answer));

 

문제풀이(2)

whiteStartBoard, blackStartBoard를 직접적으로 정의하지 않고 구현하는 코드를 작성한다.
임의로 사용자가 지정했을 경우 반복되는 알파벳이기 때문에 오류가 생길수 있다. 이를 방지하기 위한 코드를 추가하는 방법이다.
속도는 당연히 풀이1번보다는 느릴 수 있다. 하지만, 그 차이가 적을 것이라 생각해 보드를 생성하는 함수를 추가했다.
실행속도 차이 = 192ms -> 196ms

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";

const input = require("fs").readFileSync(filePath).toString().trim().split("\n");

const [N, M] = input.shift().split(" ").map(Number);

const generateStartBoard = (word1, word2) => {
  const startBoard = [];
  const colors = [word1, word2];

  for (let i = 0; i < 8; i++) {
    const row = [];

    for (let j = 0; j < 8; j++) {
      // 보드의 색깔을 번갈아가며 채우기
      const colorIndex = (i + j) % 2;
      row.push(colors[colorIndex]);
    }

    startBoard.push(row.join(""));
  }

  return startBoard;
};

const whiteStartBoard = generateStartBoard("W", "B");
const blackStartBoard = generateStartBoard("B", "W");

const answer = [];

// 정상적인 보드인지 체크하는 함수
const boardCheck = (x, y, colorBoard) => {
  let count = 0;

  for (let i = y; i < y + 8; i++) {
    for (let j = x; j < x + 8; j++) {
      if (input[i][j] !== colorBoard[i - y][j - x]) {
        count++;
      }
    }
  }

  return count;
};

for (let i = 0; i + 7 < N; i++) {
  for (let j = 0; j + 7 < M; j++) {
    answer.push(boardCheck(j, i, whiteStartBoard));
    answer.push(boardCheck(j, i, blackStartBoard));
  }
}

console.log(Math.min(...answer));

https://www.acmicpc.net/problem/1920

 

1920번: 수 찾기

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들

www.acmicpc.net

문제

N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 -231 보다 크거나 같고 231보다 작다.

출력

M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.

예제 입력 1 복사

5
4 1 5 2 3
5
1 3 7 9 5

예제 출력 1 복사

1
1
0
0
1

 

문제풀이(1)

4번째 줄에 나온 수들이 2번째 줄에 나온 수들 중에 존재하는지 여부를 판단하는 문제이다.
-2^31 ~ 2^31까지 범위가 정해져 있기 때문에 include를 사용할 경우 시간초과가 나올 것이라 생각해서 이진탐색으로 풀었다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";

const input = require("fs").readFileSync(filePath).toString().trim().split("\n");
const [N, A, M, B] = input.map((line) => line.split(" ").map(Number));
A.sort((a, b) => a - b); // 탐색 대상 정렬

const answer = [];

const binarySearch = (list, target) => {
  let low = 0;
  let high = A.length - 1;
  let result = 0;

  while (low <= high) {
    let mid = Math.floor((low + high) / 2); // 중간점

    if (list[mid] < target) {
      low = mid + 1;
    } else if (list[mid] > target) {
      high = mid - 1;
    } else {
      result = 1;
      break;
    }
  }

  return result;
};

B.forEach((num) => {
  answer.push(binarySearch(A, num));
});

console.log(answer.join("\n"));

 

문제풀이(2)

1. B배열의 값들이 A배열에 값이 있을 경우 1을 아닐경우 0을 추출하는 문제인데 만약, A에 같은 값이 [1, 1, 1, 1]로 되어 있는 경우를 생각해 중복된 값을 제거함.
2. 코드의 가독성을 위해 result 대신 0과 1로 결과값을 반환.
3. mid값은 while문을 순회하는 동안 변하지 않는 값이므로 let -> const로 변경.

메모리와 실행시간이 풀이(1)보다 더 높게 나왔다.
수정내용 1번이 중복을 제거해야한다면 괜찮을 수 있지만 중복을 제거하는 과정이 들어가기 때문에 더 높게 나왔다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";

const input = require("fs").readFileSync(filePath).toString().trim().split("\n");
const [N, A, M, B] = input.map((line) => line.split(" ").map(Number));
const uniqueSetA = Array.from(new Set(A)).sort((a, b) => a - b);

const answer = [];

const binarySearch = (list, target) => {
  let low = 0;
  let high = uniqueSetA.length - 1;

  while (low <= high) {
    const mid = Math.floor((low + high) / 2); // 중간점

    if (list[mid] < target) {
      low = mid + 1;
    } else if (list[mid] > target) {
      high = mid - 1;
    } else {
      return 1;
    }
  }

  return 0;
};

B.forEach((num) => {
  answer.push(binarySearch(uniqueSetA, num));
});

console.log(answer.join("\n"));

10월에 퇴사하고 11월까지 한동안은 못했던 공부와 개인적인 일을 정리하는 시간을 가졌다.

최대한 많은 강의를 보고 프로젝트를 기획하며 다시 취업을 위해 준비하고 싶었지만 해낸게 별로 없는 것같다....

12월부터는 시간 계획표를 세워서 조금더 구체적으로 준비를 해야겠다.

 

10월 11일에 회사의 사정으로 권고사직을 받고 실업급여를 받기 위한 서류를 정리하고, 인수인계 자료를 작성하고 전달하는 작업을 진행했다. 

실업 급여를 타기위한 조건과 서류들이 은근히 많이 있었고, 강의도 시청해야했다. 강의 내용은 실업 급여를 지급받을 때 해야하는 일과 하지 말아야 하는 일에 대해서만 적혀있었다.

인수인계 자료를 작성하는데 운영하는 내용을 다른 사람이 볼 수 있도록 최대한 자세히 노션에 기록하고, 파일들을 정리하여 대표님께 전달하는 작업이었다. 함수 하나하나 알려주는 내용을 담고 싶었지만 9개월간 작업한 내용이 방대했고, 스타트업의 여건상 빠른 개발을 목표로 진행했기 때문에 간단한 함수들은 제외하고 컴포넌트를 재활용할 때 유의할점 필요한 인자값들에 대해 정리하고 컴포넌트가 어떤것인지 정리하는 작업을 했다.

 

그뒤로는 현 시점 프론트엔드 개발자 주니어 취업시장을 분석하는 시간을 가졌다. 

내가 첫 취업을 하기 전에는 React, Javascript가 대부분이었는데 현재는 Next.js와 Typescript가 기본 베이스로 알고 가야하는 것이었다. 전 회사에서 Next.js로 홈페이지를 제작하고 SEO를 설정하여 실 방문자수를 늘리는 작업을 했었기 때문에 이력서에 잘 녹아내야 할 것 같다. 또한, 이전에는 React Native를 사용한 앱개발이 많이 보였었는데 Flutter가 대부분 시작을 장악하고 있었기 때문에 Flutter에 대해서도 학습해야 함을 느끼게 되었다.

 

이렇게 시장을 분석했을 때 내가 부족한 부분은 Typescript와 React Native, Flutter와 같은 앱개발 부분이었다. 그리고 요즘은 풀스택개발자를 더 뽑는 추세라고 느꼇기 때문에 풀스택으로 기획, 디자인, 개발을 한 프로젝트를 진행해봐야 겠다고 생각했다.

 

이처럼 많은 것을 넘어야 다시 취업할 수 있을 것 같았고, 취업을 했을 때에도 회사에 민폐가 되지 않고 한명의 팀원, 개발자로서 회사와 팀에 도움이 되는 개발자가 되기 위해 학습할 동기부여를 갖게되었다.

 

우선 내가 해야할 일들을 정리해보았다.

1. 이력서 수정

2. 경력서 작성

3. 취업공고 확인

4. CS 및 개발 지식 학습

5. Next.js v13, Typescript, nodejs, express 등과 같은 것을 사용한 프로젝트 개발

6. 알고리즘 문제풀이

 

10월에는 이력서, 경력서를 작성하는 시간으로 대부분을 할애했고, 취업공고는 하루 한시간정도 확인하고 CS 및 개발 지식 습득과 기술면접을 위해 학습했던 것 같다.

 

쏘카 프론트엔드 개발자를 뽑는다는 얘기를 듣고 서류를 접수하고 코딩테스트를 봤지만... 아쉽게도 탈락했다.... 코딩테스트는 많은 문제를 풀어보고 사고하는 방식을 가지고 문제를 세세하게 분석하고 예외처리를 잘 할 수 있도록 하는것이 답인것 같다.

 

11월에는10월에 접수한 SQLD 자격증 시험이 11월18일에 있었기 때문에 대부분을 SQL을 학습하는데 시간을 할애했다. SQL의 필요성을 느겼던 것으로는 프론트엔드 개발자 이지만 실무에서 SQL을 확인해야하는 일도 간혹 있었는데 이때 확인할때 시간이 다소 소모됐던것이 있어서 이번 기회에 학부생때 배웠던 SQL을 조금 더 심화적으로 학습하는 시간을 가졌다. 결과는 12월 8일에 임시로 나온다고 한다.

 

끝나고 나서는 우아한형제들에서 새로 출시한 '우아한 타입스크립트 with 리액트' 책을 보면서 Typescript와 실제 사용하는 코드, 우아한형제들에서 개발자가 개발하는 방법등과 같은 내용을 알 수 있다고 하여 하루 2시간씩 책을 보고 있으며, 원래 프로그래머스 Level 2,3을 하루 한문제 풀고 오답을 작성하는 시간을 가졌었는데 문제의 유형은 다양하지만 유형별 문제수는 적었기 때문에 백준 실버 4부터 차근차근 다시 하루 2문제 이상씩 풀어보려 하고 있다. 이때, 이전과는 다르게 한번 풀고 끝나는 것이 아닌 리팩토링 하는 과정을 가지며 조금더 클린코드를 작성하고 실행시간을 줄일수 있도록 코드 리팩토링을 하고 있다.

 

 

 

https://www.acmicpc.net/problem/11047

 

11047번: 동전 0

첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 10, 1 ≤ K ≤ 100,000,000) 둘째 줄부터 N개의 줄에 동전의 가치 Ai가 오름차순으로 주어진다. (1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수)

www.acmicpc.net

문제

준규가 가지고 있는 동전은 총 N종류이고, 각각의 동전을 매우 많이 가지고 있다.

동전을 적절히 사용해서 그 가치의 합을 K로 만들려고 한다. 이때 필요한 동전 개수의 최솟값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 10, 1 ≤ K ≤ 100,000,000)

둘째 줄부터 N개의 줄에 동전의 가치 Ai가 오름차순으로 주어진다. (1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수)

출력

첫째 줄에 K원을 만드는데 필요한 동전 개수의 최솟값을 출력한다.

예제 입력 1 복사

10 4200
1
5
10
50
100
500
1000
5000
10000
50000

예제 출력 1 복사

6

 

문제풀이(1)

동전의 가치를 내림차순 정렬하여 가치의 합을 을 가치로 나눴을 때의 몫이 1이상인 것을 count한다.
몫이 1 이상인 값이 나왔을 경우 K에 해당 가치*개수 만큼 빼주는 것을 반복한다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";

const input = require("fs").readFileSync(filePath).toString().trim().split("\n");
let [N, K] = input.shift().split(" ").map(Number);

const coins = input.map(Number).sort((a, b) => b - a); // 내림차순

let count = 0;

for (let i = 0; i < N; i++) {
  let division = Math.floor(K / coins[i]);
  if (division) {
    count += division;
    K -= division * coins[i];
  }
}

console.log(count);

https://www.acmicpc.net/problem/11399

 

11399번: ATM

첫째 줄에 사람의 수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어진다. (1 ≤ Pi ≤ 1,000)

www.acmicpc.net

문제

인하은행에는 ATM이 1대밖에 없다. 지금 이 ATM앞에 N명의 사람들이 줄을 서있다. 사람은 1번부터 N번까지 번호가 매겨져 있으며, i번 사람이 돈을 인출하는데 걸리는 시간은 Pi분이다.

사람들이 줄을 서는 순서에 따라서, 돈을 인출하는데 필요한 시간의 합이 달라지게 된다. 예를 들어, 총 5명이 있고, P1 = 3, P2 = 1, P3 = 4, P4 = 3, P5 = 2 인 경우를 생각해보자. [1, 2, 3, 4, 5] 순서로 줄을 선다면, 1번 사람은 3분만에 돈을 뽑을 수 있다. 2번 사람은 1번 사람이 돈을 뽑을 때 까지 기다려야 하기 때문에, 3+1 = 4분이 걸리게 된다. 3번 사람은 1번, 2번 사람이 돈을 뽑을 때까지 기다려야 하기 때문에, 총 3+1+4 = 8분이 필요하게 된다. 4번 사람은 3+1+4+3 = 11분, 5번 사람은 3+1+4+3+2 = 13분이 걸리게 된다. 이 경우에 각 사람이 돈을 인출하는데 필요한 시간의 합은 3+4+8+11+13 = 39분이 된다.

줄을 [2, 5, 1, 4, 3] 순서로 줄을 서면, 2번 사람은 1분만에, 5번 사람은 1+2 = 3분, 1번 사람은 1+2+3 = 6분, 4번 사람은 1+2+3+3 = 9분, 3번 사람은 1+2+3+3+4 = 13분이 걸리게 된다. 각 사람이 돈을 인출하는데 필요한 시간의 합은 1+3+6+9+13 = 32분이다. 이 방법보다 더 필요한 시간의 합을 최소로 만들 수는 없다.

줄을 서 있는 사람의 수 N과 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어졌을 때, 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 사람의 수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어진다. (1 ≤ Pi ≤ 1,000)

출력

첫째 줄에 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값을 출력한다.

예제 입력 1 복사

5
3 1 4 3 2

예제 출력 1 복사

32
 

문제풀이(1)

둘째 줄에 입력받는 수를 정렬한 후 누적으로 합계를 계산하면 될 것이라 생각한다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";

const input = require("fs").readFileSync(filePath).toString().trim().split("\n");

const N = Number(input.shift());
const numbers = input
  .shift()
  .split(" ")
  .map(Number)
  .sort((a, b) => a - b);	// 오름차순 정렬

let sum = 0;

for (let i = 0; i < N; i++) {
  let acc = numbers.slice(0, i + 1).reduce((a, b) => a + b, 0);
  sum += acc;
}

console.log(sum);

 

문제풀이(2) - 리팩토링

문제풀이(1)과 같이 풀었을 경우 사용하지 않아도 되는 메소드를 줄여서 메모리와 실행시간을 단축시킬 수 있을 것이라 생각해서 slice, reduce를 제거했다.

메모리는 11840kb -> 9632kb, 실행시간은 204ms -> 132ms로 단축된 것을 확인할 수 있었다.

오랜만에 낮은 레벨부터 다시 차근차근 풀어보는데 이런식으로 문제를 한번 풀어보고 리팩토링 할 수 있는 부분을 찾아내는 것이 좋다고 메모리와 코드 가독성을 올릴수 있는 부분이라고 생각하여 앞으로는 2번씩 풀어볼 예정이다.

누군가는 간단하다고 생각할 수 있으나 한번더 사고하는 것이 나에겐 더욱 도움이 될 것이라 생각한다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";

const input = require("fs").readFileSync(filePath, "utf8").trim().split("\n");
const N = Number(input[0]);
const numbers = input[1]
  .split(" ")
  .map(Number)
  .sort((a, b) => a - b);

let sum = 0;
let acc = 0;

for (let i = 0; i < N; i++) {
  acc += numbers[i];
  sum += acc;
}

console.log(sum);

+ Recent posts