React

튜플 https://programmers.co.kr/learn/courses/30/lessons/64065

문제 설명

셀수있는 수량의 순서있는 열거 또는 어떤 순서를 따르는 요소들의 모음을 튜플(tuple)이라고 합니다. n개의 요소를 가진 튜플을 n-튜플(n-tuple)이라고 하며, 다음과 같이 표현할 수 있습니다.
(a1, a2, a3, ..., an)
튜플은 다음과 같은 성질을 가지고 있습니다.
1.
중복된 원소가 있을 수 있습니다. ex : (2, 3, 1, 2)
2.
원소에 정해진 순서가 있으며, 원소의 순서가 다르면 서로 다른 튜플입니다. ex : (1, 2, 3) ≠ (1, 3, 2)
3.
튜플의 원소 개수는 유한합니다.
원소의 개수가 n개이고, 중복되는 원소가 없는 튜플 (a1, a2, a3, ..., an)이 주어질 때(단, a1, a2, ..., an은 자연수), 이는 다음과 같이 집합 기호 '{', '}'를 이용해 표현할 수 있습니다.
{{a1}, {a1, a2}, {a1, a2, a3}, {a1, a2, a3, a4}, ... {a1, a2, a3, a4, ..., an}}
예를 들어 튜플이 (2, 1, 3, 4)인 경우 이는
{{2}, {2, 1}, {2, 1, 3}, {2, 1, 3, 4}}
와 같이 표현할 수 있습니다. 이때, 집합은 원소의 순서가 바뀌어도 상관없으므로
{{2}, {2, 1}, {2, 1, 3}, {2, 1, 3, 4}}
{{2, 1, 3, 4}, {2}, {2, 1, 3}, {2, 1}}
{{1, 2, 3}, {2, 1}, {1, 2, 4, 3}, {2}}
는 모두 같은 튜플 (2, 1, 3, 4)를 나타냅니다.
특정 튜플을 표현하는 집합이 담긴 문자열 s가 매개변수로 주어질 때, s가 표현하는 튜플을 배열에 담아 return 하도록 solution 함수를 완성해주세요.

[제한사항]

s의 길이는 5 이상 1,000,000 이하입니다.
s는 숫자와 '{', '}', ',' 로만 이루어져 있습니다.
숫자가 0으로 시작하는 경우는 없습니다.
s는 항상 중복되는 원소가 없는 튜플을 올바르게 표현하고 있습니다.
s가 표현하는 튜플의 원소는 1 이상 100,000 이하인 자연수입니다.
return 하는 배열의 길이가 1 이상 500 이하인 경우만 입력으로 주어집니다.

[입출력 예]

Search
s
result
"{{1,2,3},{2,1},{1,2,4,3},{2}}"
"{{20,111},{111}}"
"{{123}}"
"{{4,2,3},{3},{2,3,4,1},{2,3}}"

입출력 예에 대한 설명

입출력 예 #1

문제 예시와 같습니다.

입출력 예 #2

문제 예시와 같습니다.

입출력 예 #3

(111, 20)을 집합 기호를 이용해 표현하면 {{111}, {111,20}}이 되며, 이는 {{20,111},{111}}과 같습니다.

입출력 예 #4

(123)을 집합 기호를 이용해 표현하면 {{123}} 입니다.

입출력 예 #5

(3, 2, 4, 1)을 집합 기호를 이용해 표현하면 {{3},{3,2},{3,2,4},{3,2,4,1}}이 되며, 이는 {{4,2,3},{3},{2,3,4,1},{2,3}}과 같습니다.

My solution

일단 이차원 배열화해서 각 요소의 순서를 정렬한다.
이후 방식은 여러가지가 있는데,
1.
count를 세서 해당 인덱스에 넣은 객체를 각각 만들어 놓고, Object.keys(객체).sort((a,b)⇒ count[a]-count[b]).map(v⇒v) 이렇게 하면 더 많은 것 순서대로 a,b를 정렬 후, 배열로 반환할 수 있다.
2.
이차원 배열을 평탄화해서 각 요소의 개수를 구한 다음 그 개수를 전체 요소의 개수에서 빼준 것을 인덱스로 사용해서 배열에 넣어주거나,
3.
평탄화해서 Set에 담아서 중복된 요소를 자동으로 제거 후 배열로 만드는 방식이다.
나는 2번으로 해놓고 설명했는데 성능이 40ms대가 나오고 가독성도 좋지 않았다. 다른 사람의 풀이가 3번으로 하는 방식이어서 그 방식으로 변경해 30ms대로 개선할 수 있었다.
정규표현식으로 {{ }}를 모두 벗길 수 있는 식을 만드는 방식도 있는데, 결국에 이차원 배열로 만드는 것은 동일했다. 정규표현식을 날 잡고 좀더 익숙해지게 할 필요가 있다고 느꼈다.
더 깔끔한 코드 참조

소스코드

function solution(s) { // & : 튜플을 이차원 배열로 변환 및 정렬 const re = /},/g; const sorted2dArr = s .slice(1, s.length - 1) .split(re) .map(row => row .replace(/{|}/g, '') .split(',') .map(el => +el) ) .sort((a, b) => a.length - b.length); // console.log(sorted2dArr); // & : Set으로 넣으면 순서대로 들어감(중복 추가X) return [...new Set(sorted2dArr.flat())]; // // & : 이차원 배열을 평탄화하고, 객체에 요소별 개수를 세서 넣음 <= 성능 손해 // const elementSet = sorted2dArr.flat().reduce((acc, n) => { // acc[n] = (acc[n] || 0) + 1; // return acc; // }, {}); // // & : "arr.el.len - 요소의 개수" = 그 요소의 인덱스, 맨 마지막 배열을 가지고 키를 줘서 확인 // const elementTuple = sorted2dArr[sorted2dArr.length - 1].reduce((acc, v) => { // acc[sorted2dArr.length - elementSet[v]] = v; // return acc; // }, []); // console.log(elementTuple); // return elementTuple; } test('TC1', () => { expect(solution('{{2},{2,1},{2,1,3},{2,1,3,4}}')).toStrictEqual([2, 1, 3, 4]); }); test('TC2', () => { expect(solution('{{1,2,3},{2,1},{1,2,4,3},{2}}')).toStrictEqual([2, 1, 3, 4]); }); test('TC3', () => { expect(solution('{{20,111},{111}}')).toStrictEqual([111, 20]); }); test('TC4', () => { expect(solution('{{123}}')).toStrictEqual([123]); }); test('TC5', () => { expect(solution('{{4,2,3},{3},{2,3,4,1},{2,3}}')).toStrictEqual([3, 2, 4, 1]); });
JavaScript
복사