kakasoo

[node.js] 단어 수학 ( 백준 1339번) 본문

프로그래밍/알고리즘 풀이

[node.js] 단어 수학 ( 백준 1339번)

카카수(kakasoo) 2021. 7. 31. 15:59
반응형
const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});

let count;
const input = [];
let maxValue = -987654321;

rl.on("line", (line) => {
    if (!count) {
        count = Number(line);
    } else {
        input.push(line);

        if (input.length === count) {
            main();
        }
    }
});

const getPermutations = function* (elements) {
    if (elements.length === 1) {
        yield elements;
    } else {
        const [first, ...rest] = elements;

        for (const a of getPermutations(rest)) {
            for (let i = 0; i < elements.length; i++) {
                const start = a.slice(0, i);
                const ended = a.slice(i);

                yield [...start, first, ...ended];
            }
        }
    }
};

const isMax = function* (iterable) {
    for (const a of iterable) {
        const numberChanged = input
            .map((el) => {
                const arr = el.split("");
                return arr
                    .map((el) => {
                        return a.findIndex((target) => target === el);
                    })
                    .join("");
            })
            .map(Number);

        const sum = numberChanged.reduce((acc, cur) => (acc += cur), 0);

        if (sum > maxValue) {
            maxValue = sum;
            yield sum;
        }
    }
};

const main = () => {
    const alphabets = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"];

    [...isMax(getPermutations(alphabets))];
    console.log(maxValue);
};

원래는 이처럼 순열을 이용해서 풀려고 했다.
다른 언어에서도 아마 이런 방법을 사용해서 풀려고 하지 않았을까 싶었지만, 자바스크립트는 콜 스택이 터지면서 문제가 발생했다.
그래서 메모리와 스택의 소모를 줄이기 위해서 제너레이터를 만들어 적극 활용하기로 했다.
결과적으로 시간초과가 발생했다...
Lazy하게 함수를 만드는 것은 좋지만, 이로 인해 지연 함수는 더 느리다는 단점이 부각된 것으로 보인다.
원래대로면 불필요한 연산을 줄임으로써 빨라지기도 하지만, 이 경우에는 어차피 모든 경우를 탐색해야 함에도 불구하고, Lazy를 썼으니 메모리를 아끼고자 성능을 줄인 것에 불과했을 것이다.

const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});

// 2
// AAA
// AAA    => { A: 222 }
// 위와 같은 형태로, 자릿수에 맞게 사용된 횟수를 기록한 후, 높은 자릿수부터 큰 수를 대입해본다.
const makeAlphabetObj = (input) => {
    const obj = {};
    input.slice(1).map((str) => {
        str.split("")
            .reverse()
            .forEach((el, i) => {
                obj[el] = !obj[el] ? 10 ** i : obj[el] + 10 ** i;
            });
    });
    return obj;
};

const solution = (input) => {
    const obj = makeAlphabetObj(input);
    const objToArr = Object.entries(obj).sort((a, b) => b[1] - a[1]);

    let number = 9;
    let sum = 0;
    for (const a of objToArr) {
        sum += a[1] * number--;
    }

    return sum;
};

const input = [];

rl.on("line", (line) => {
    input.push(line);
}).on("close", () => {
    console.log(solution(input));
    process.exit();
});

그래서 자료구조를 적극 활용하는 방법을 사용했다.
이 코드는 다른 분의 블로그를 참고해서 작성한 것인데, 내 나름대로 코드를 수정해보았다.
( 핵심이 되는 생각은, 그 분의 생각을 참고했다. )
자바스크립트는 아직 다른 언어에 비해 불리한 점이 많은 것 같은데, 이를 어떻게 극복할지가 앞으로의 관건으로 보인다.

하면서도 스트레스를 받는 일이긴 하지만, 극복해가는 과정 속에서, 자바스크립트를 더 효율적으로 다루는 법을 알 수 있을 것 같다

반응형