241106 TIL - 우리의 타워디펜스 온라인 3

LIHA·2일 전
0

내일배움캠프

목록 보기
103/105
post-thumbnail

알고리즘

약수를 그냥 구하니 시간초과가 뜬다 - 좀더 간단한 방법 없을까? 절반과 제곱근

대충 기사단원이 무기를 구매할거니까, 거기에 맞게 무기제작할 철들의 무게를 미리 계산하고 싶다는 것.
로직은 어느정도 구현해 놓았었는데, 약수의 개수 = 무게다 보니 약수의 개수 구하는 로직에서 시간초과가 떴다. 흠... 🤔

처음 구현했던 코드는 다음과 같다.

// 각 기사는 자신의 기사 번호의 약수 개수에 해당하는 공격력을 가진 무기를 구매
// 단, 제한수치 있고 제한수치보다 큰 공격력을 가진 무기를 구매해야 하는 기사는 협약 공격력 무기 구매 강제
// 무기를 모두 만들기 위해 필요한 철의 무게를 구하고 싶음

function getIronMass (number, limit, power) {
    let divisor = 0;
    let totalIronMass = 0;
    for (let i = 1; i <= number; i++) {
        divisor = 0;
        for(let j = 1; j <= i; j++) {
            if (i % j === 0) 
                ++divisor;
        }
        // 약수 갯수가 한계보다 크면 지정된 공격력으로 구매하니 지정공격력만큼의 철 무게 필요
        divisor > limit ? totalIronMass += power : totalIronMass += divisor; 
    }
    return totalIronMass;
}

function solution(number, limit, power) {
    var answer = getIronMass (number, limit, power);
    return answer;
}

약수를 좀더 간단하게 구하는 방법에는 크게 두가지가 있다고 한다. 수의 절반까지만 약수를 구하는 방법과 수의 제곱근까지만 약수를 구하는 방법.
수의 절반까지만 구하는 방법은 예시를 잘못 든건지 12를 예로 들어 생각해보니 뭔가 뾰족하게 나와지지가 않았다.
제곱근을 이용해서 거기까지만 약수 개수를 구해놓고 *2 - 1을 하니 테스트를 통과해서, 제출해보니 모든 TC를 통과했다. 야호

아래는 통과된 코드.

// 각 기사는 자신의 기사 번호의 약수 개수에 해당하는 공격력을 가진 무기를 구매
// 단, 제한수치 있고 제한수치보다 큰 공격력을 가진 무기를 구매해야 하는 기사는 협약 공격력 무기 구매 강제
// 무기를 모두 만들기 위해 필요한 철의 무게를 구하고 싶음

function getIronMass (number, limit, power) {
    let divisor = 0;
    let totalIronMass = 0;
    for (let i = 1; i <= number; i++) {
        divisor = 0;
        // 약수 갯수를 그냥 구하니 시간초과가 뜬다 - 좀더 간단히 해볼수 없을까?
        for(let j = 1; j <= Math.sqrt(i); j++) {
            if (i % j === 0) 
                ++divisor;
        }
        // 제곱수인 경우 약수가 1, 제곱근, 자기자신이므로 *2 후 1을 빼주어야 함
        Number.isInteger(Math.sqrt(i)) ? divisor = divisor * 2 - 1 : divisor *= 2
        // 약수 갯수가 한계보다 크면 지정된 공격력으로 구매하니 지정공격력만큼의 철 무게 필요
        divisor > limit ? totalIronMass += power : totalIronMass += divisor; 
    }
    return totalIronMass;
}

function solution(number, limit, power) {
    var answer = getIronMass (number, limit, power);
    return answer;
}

우리의 타워디펜스 온라인

socket.on('data', onData(socket))은 함수를 결과로 내뱉는 것

currying은 (arg1) => (arg2) => {} 형식으로 콜백이 되어 있는데, 이건 arg1을 실행한 결과로 (arg2) => {} 라는 함수를 내뱉는 것.

if(socket.buffer.length >= length) 가 조건인 이유 - 버퍼의 특징 때문

socket.buffer.length >= length 조건 만족되지 않으면 버퍼에 데이터 덜 쌓인 것이다.
-> 이게 왜 덜 쌓인거냐면 버퍼는 할당된 사이즈가 가득 차야만 작동하는 애라 전체길이 이상으로 들어와야 썰어서 쓸 수 있다 - 가득 안차면 못 쓴다.
그래서 버퍼 안에 청크 덜 쌓였으니까 아직 못쓴다 - break 걸고 concat 되는 데이터를 더 기다리는 것.

Object.freeze() - 객체를 동결하는 법

도와줘요 MDN

VS Code에서 파일 경로를 이동시킬 때 import가 자동으로 수정되게 하고 싶다면 - update imports on file move를 해주자

언제 한번 창이 떴을 때 import 자동 반영에 아니오를 눌러버렸더니 이후로 디렉토리 이동만 하면 import를 반영을 못하고 코드가 터져나가서 수동으로 고치다가 서러움이 몰려오던 차였다. 😭
구글링을 해도 제대로 나오지도 않기에 import 관련해서 설정을 검색해보다가 겨우겨우 찾아냈다.

JavaScript > Update Imports On File Move 설정을 Prompt로 해주면 매번 물어본다.
Always로 하면 항상 자동적용!

type = message 이름! '어떤 메시지 타입' 인지 추출해 주는 것

위의 for문이 뭘 가져오는지 정확히 잘 모르겠어서 콘솔을 찍어보았다. 그랬더니 아래처럼 나왔다.

우리는 packetName.js에서 JS가 .proto 파일을 읽을 수 있도록 맵핑해 주었다. 구조는 다음과 같다.

이 맵핑 구조가 패키지 이름 : { 메시지 이름 : '패키지이름.메시지이름(풀네임)'} 형식으로 되어있다.

message의 이름을 왜 갑자기 typeName이라고 하냐면, protoMessages를 콘솔 찍으면 아래처럼 나오기 때문.

무튼, packetName 이라고 쓰니 뭔지 헷갈려서 강의 속 튜터님 조언대로 그냥 packageName으로 바꿨다. (package는 예약어라 쓸 수 없었음)

핸들러 생성 시 해줘야 할 작업들

  • handlers > index.js에 핸들러를 맵핑 해준다
    -> 이 맵핑은 constants 폴더의 handlerIds.js에 상수화 시킨 핸들러 ID를 가져와 대괄호 안에 넣어주는 식으로 한다.
    -> 맵핑 시 핸들러 ID : { 객체 } 형태로 맵핑하는데, 객체 안에는 핸들러와 프로토버프의 타입이름(그 packetName.js의 풀네임)을 맵핑해준다.

그러면 대강 이런식으로 나온다.

  • protobuf의 packetNames.js에 프로토버프 타입 이름을 맵핑해준다.

profile
갑자기 왜 춤춰?

0개의 댓글