문제

Given a function fn, an array of arguments args, and a timeout t in milliseconds, return a cancel function cancelFn.

After a delay of cancelTimeMs, the returned cancel function cancelFn will be invoked.

setTimeout(cancelFn, cancelTimeMs)
Initially, the execution of the function fn should be delayed by t milliseconds.

If, before the delay of t milliseconds, the function cancelFn is invoked, it should cancel the delayed execution of fn. Otherwise, if cancelFn is not invoked within the specified delay t, fn should be executed with the provided args as arguments.

 

예제

 

풀이

/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function(fn, args, t) {
    const timeout = setTimeout(function () {
        fn(...args);
    }, t)
    
    return function() {
        clearTimeout(timeout);
    }
};

/**
 *  const result = [];
 *
 *  const fn = (x) => x * 5;
 *  const args = [2], t = 20, cancelTimeMs = 50;
 *
 *  const start = performance.now();
 *
 *  const log = (...argsArr) => {
 *      const diff = Math.floor(performance.now() - start);
 *      result.push({"time": diff, "returned": fn(...argsArr)});
 *  }
 *       
 *  const cancel = cancellable(log, args, t);
 *
 *  const maxT = Math.max(t, cancelTimeMs);
 *           
 *  setTimeout(cancel, cancelTimeMs);
 *
 *  setTimeout(() => {
 *      console.log(result); // [{"time":20,"returned":10}]
 *  }, maxT + 15)
 */

먼저, setTimeout 함수를 이용하여 t 밀리초 후에 fn 함수가 실행되게끔 만든다. 하지만 주석 코드에서 cancelTimeMs 밀리초가 지나면 `setTimeout(cancel, cancelTimeMs);` 코드에 의해 cancel 함수가 실행되는데, 이 때 cancellable 함수의 return 문에 의해 기존에 진행시켰던 setTimeout 함수를 clear시킨다.

따라서 t 밀리초보다 cancelTimeMs 밀리초가 더 짧을 경우 정상적으로 setTimeout 함수가 t 밀리초 후 fn 함수를 호출하게 되지만 그렇지 않을 경우에는 clearTimeout이 먼저 실행되어 fn 함수를 호출하지 않게 된다.

'Algorithm' 카테고리의 다른 글

[LeetCode] 2704. To Be Or Not To Be  (0) 2024.02.05
[LeetCode] 2695. Array Wrapper  (0) 2024.01.31
[LeetCode] 2677. Chunk Array  (0) 2024.01.31
[BOJ] 4779. 칸토어 집합  (1) 2024.01.30
[SWEA] 1230. 암호문3  (1) 2024.01.29

문제

Write a function expect that helps developers test their code. It should take in any value val and return an object with the following two functions.

toBe(val) accepts another value and returns true if the two values === each other. If they are not equal, it should throw an error "Not Equal".
notToBe(val) accepts another value and returns true if the two values !== each other. If they are equal, it should throw an error "Equal".

 

예제

 

풀이

/**
 * @param {string} val
 * @return {Object}
 */
var expect = function(val) {
    return {
        toBe: function(compVal) {
            if (val === compVal) {
                return true
            } else throw new Error('Not Equal')
        },
        
        notToBe: function(compVal) {
            if (val === compVal) {
                throw new Error('Equal')
            } else return true
        }
    }
};

/**
 * expect(5).toBe(5); // true
 * expect(5).notToBe(5); // throws "Equal"
 */

처음 주어지는 값인 val과 메소드 내에 주어지는 값인 compVal에 대하여 비교할 것인데, toBe 메소드의 경우 val 값과 compVal 값이 같다면 true를 반환하고, 그렇지 않을 시 'Not Equal'이라는 메세지와 함께 에러를 반환합니다. notToBe의 경우 val 값과 compVal 값이 다를 경우 true를 반환하고, 같을 시에는 'Equal'이라는 메세지와 함께 에러를 반환합니다.

'Algorithm' 카테고리의 다른 글

[LeetCode] 2715. Timeout Cancellation  (0) 2024.02.05
[LeetCode] 2695. Array Wrapper  (0) 2024.01.31
[LeetCode] 2677. Chunk Array  (0) 2024.01.31
[BOJ] 4779. 칸토어 집합  (1) 2024.01.30
[SWEA] 1230. 암호문3  (1) 2024.01.29

문제

Create a class ArrayWrapper that accepts an array of integers in its constructor. This class should have two features:

When two instances of this class are added together with the + operator, the resulting value is the sum of all the elements in both arrays.
When the String() function is called on the instance, it will return a comma separated string surrounded by brackets. For example, [1,2,3].

 

예제

 

접근

해당 함수의 인스턴스를 호출할 시 자동으로 nums.prototype.valueOf() 메소드가 실행된다. 따라서 ArrayWrapper 함수 내에서 sumNums 변수에 reduce 메소드를 이용하여 배열 내 원소의 합을 구해주고 valueOf() 메소드 호출 시 해당 값을 반환해준다.

마찬가지로 String(nums) 실행 시에는 nums.prototype.toString() 메소드가 실행된다. 따라서 join 메소드를 활용하여 배열이 String으로 변환된 값을 저장해둔 뒤 toString() 메소드 호출 시 해당 값을 반환해 줄 수 있도록 했다.

 

코드

/**
 * @param {number[]} nums
 * @return {void}
 */
var ArrayWrapper = function(nums) {
    this.sumNums = nums.reduce((acc, val) => acc + val, 0);
    this.arrToStr = "[" + nums.join(",") + "]";
};

/**
 * @return {number}
 */
ArrayWrapper.prototype.valueOf = function() {
    return this.sumNums;
}

/**
 * @return {string}
 */
ArrayWrapper.prototype.toString = function() {
    return this.arrToStr;
}

/**
 * const obj1 = new ArrayWrapper([1,2]);
 * const obj2 = new ArrayWrapper([3,4]);
 * obj1 + obj2; // 10
 * String(obj1); // "[1,2]"
 * String(obj2); // "[3,4]"
 */

'Algorithm' 카테고리의 다른 글

[LeetCode] 2715. Timeout Cancellation  (0) 2024.02.05
[LeetCode] 2704. To Be Or Not To Be  (0) 2024.02.05
[LeetCode] 2677. Chunk Array  (0) 2024.01.31
[BOJ] 4779. 칸토어 집합  (1) 2024.01.30
[SWEA] 1230. 암호문3  (1) 2024.01.29

문제

Given an array arr and a chunk size size, return a chunked array. A chunked array contains the original elements in arr, but consists of subarrays each of length size. The length of the last subarray may be less than size if arr.length is not evenly divisible by size.

You may assume the array is the output of JSON.parse. In other words, it is valid JSON.

Please solve it without using lodash's _.chunk function.

 

예제

 

접근

size만큼 증가하는 for문을 돌면서 answer 배열에 i번째 원소부터 i + size번째 원소만큼의 배열을 slice로 복사하여 추가해주었다. 만약 배열의 끝부분에서 slice한 배열이 size보다 작아도, slice는 에러를 반환하지 않고 만들 수 있는 크기만큼의 배열을 생성해준다.

코드

/**
 * @param {Array} arr
 * @param {number} size
 * @return {Array}
 */
var chunk = function(arr, size) {
    const answer = [];
    
    for (let i = 0; i < arr.length; i+= size) {
        answer.push(arr.slice(i, i + size));
    }
    
    return answer;
};

 

'Algorithm' 카테고리의 다른 글

[LeetCode] 2704. To Be Or Not To Be  (0) 2024.02.05
[LeetCode] 2695. Array Wrapper  (0) 2024.01.31
[BOJ] 4779. 칸토어 집합  (1) 2024.01.30
[SWEA] 1230. 암호문3  (1) 2024.01.29
[SWEA] 10726. 이진수 표현  (0) 2024.01.29

문제

칸토어 집합은 0과 1사이의 실수로 이루어진 집합으로, 구간 [0, 1]에서 시작해서 각 구간을 3등분하여 가운데 구간을 반복적으로 제외하는 방식으로 만든다.

전체 집합이 유한이라고 가정하고, 다음과 같은 과정을 통해서 칸토어 집합의 근사를 만들어보자.

1. -가 3N개 있는 문자열에서 시작한다.

2. 문자열을 3등분 한 뒤, 가운데 문자열을 공백으로 바꾼다. 이렇게 하면, 선(문자열) 2개가 남는다.

3. 이제 각 선(문자열)을 3등분 하고, 가운데 문자열을 공백으로 바꾼다. 이 과정은 모든 선의 길이가 1일때 까지 계속 한다.

예를 들어, N=3인 경우, 길이가 27인 문자열로 시작한다.

---------------------------

여기서 가운데 문자열을 공백으로 바꾼다.

---------         ---------

남은 두 선의 가운데 문자열을 공백으로 바꾼다.

---   ---         ---   ---

한번 더

- -   - -         - -   - -

모든 선의 길이가 1이면 멈춘다. N이 주어졌을 때, 마지막 과정이 끝난 후 결과를 출력하는 프로그램을 작성하시오.

입력

입력을 여러 줄로 이루어져 있다. 각 줄에 N이 주어진다. 파일의 끝에서 입력을 멈춘다. N은 0보다 크거나 같고, 12보다 작거나 같은 정수이다.

출력

입력으로 주어진 N에 대해서, 해당하는 칸토어 집합의 근사를 출력한다.

 

예제 입력 1

0
1
3
2

예제 출력 1

-
- -
- -   - -         - -   - -
- -   - -

 

EOF(End Of File)

기존의 백준 문제는 항상 입력 문장의 개수를 파악할 수 있었는데, 이번 문제는 파일의 끝에서 입력을 멈추어야 해서 당황했다. 구글링해보니 다양한 방법이 있었는데, 그 중 EOF를 사용하는 방법으로 해결했다.

 

EOF란, End Of File의 줄임말로, 파일의 끝을 나타낸다, 이는 사용자가 더 이상 데이터를 읽을 수 없는 지점으로, 이 곳에 도달하게 되면 빈문자열이 출력으로 반환된다.

EOF를 사용하기 위해 무한으로 반복되는 while문 안에 try와 except를 사용하여 예외 처리를 진행할 것이다.

입력이 있을 땐 try문에 있는 코드들을 실행시키고, 입력이 없을 경우 break를 통해 while 문의 반복을 멈춘다.

 

풀이 1 - 메모리 초과

- 분할 정복(Divide and Conquer) 알고리즘의 재귀 방식을 이용하여 해결해보려고 했다.

// [BOJ] 4779. 칸토어 집합

import java.io.*;

// public
class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            try {
                int N = Integer.parseInt(br.readLine());
                String answer = divideAndConquer(N);

                System.out.println("answer : " + answer);
            } catch (Exception e) {
                break;
            }
        }
    }

    public static String divideAndConquer(int n) {
        if (n == 0) return "-";

        String blanks = "";
        for (int i = 0 ; i < Math.pow(3, n - 1); i++) {
            blanks += " ";
        }

        return divideAndConquer(n - 1) + blanks + divideAndConquer(n - 1);
    }
}

해당 풀이는 메모리 초과가 났는데, 재귀를 들어가면서 반환되는 문자열들의 길이가 3^12 = 531441, 3^11 = 177147, ... 로 메모리를 많이 사용하기 때문인 것으로 추측된다.

 

풀이 2 - StringBuilder 이용

Java의 String의 경우 특정 인덱스에 위치한 원소값을 수정할 수 없지만 StringBuilder를 사용하면 setCharAt 메소드를 이용하여 수정이 가능하다고 한다. 때문에 매번 새로운 객체를 생성하는 String을 사용할 때보다 메모리를 크게 줄일 수 있다.

// [BOJ] 4779. 칸토어 집합

import java.io.*;

// public
public class Main {
    public static StringBuilder sb;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        while (true) {
            try {
                int N = Integer.parseInt(br.readLine());
                sb = new StringBuilder();
                for (int i = 0; i < (int) Math.pow(3, N); i++) {
                    sb.append("-");
                }

                divideAndConquer(0, (int) Math.pow(3, N));

                System.out.println(sb);
            } catch (Exception e) {
                break;
            }
        }
    }

    public static void divideAndConquer(int start, int size) {
        if (size == 1) return;

        int newSize = size / 3;
        for (int i = start + newSize; i < start + 2 * newSize; i++) {
            sb.setCharAt(i, ' ');
        }

        divideAndConquer(start, newSize);
        divideAndConquer(start + 2 * newSize, newSize);
    }
}

'Algorithm' 카테고리의 다른 글

[LeetCode] 2695. Array Wrapper  (0) 2024.01.31
[LeetCode] 2677. Chunk Array  (0) 2024.01.31
[SWEA] 1230. 암호문3  (1) 2024.01.29
[SWEA] 10726. 이진수 표현  (0) 2024.01.29
[SWEA] 1288. 새로운 불면증 치료법  (0) 2024.01.29

문제

https://swexpertacademy.com/main/solvingProblem/solvingProblem.do

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

접근 방식

1. 암호문의 중간에서 삽입 혹은 삭제하는 명령어가 있기 때문에 삽입 및 삭제 연산이 자주 발생할 때 유리한 LinkedList 자료구조를 사용한다.

2. 각 명령어들을 `switch case`문을 사용하여 적절하게 분기 처리한다.

 

// [SWEA] 1230. 암호문3

import java.util.*;
import java.io.*;

// public
class Solution {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;

        int T = 10;

        for (int tc = 1; tc <= T; tc++) {
            int N = Integer.parseInt(br.readLine());
            st = new StringTokenizer(br.readLine());
            LinkedList<String> passwords = new LinkedList<>();
            
            for (int i = 0; i < N; i++) {
                passwords.add(st.nextToken());
            }

            int M = Integer.parseInt(br.readLine());
            st = new StringTokenizer(br.readLine());
            int x, y;
            for (int i = 0; i < M; i++) {
                char command = st.nextToken().charAt(0);
                x = Integer.parseInt(st.nextToken());

                // 각 명령어에 따라 제어 과정을 나눈다.
                switch (command) {

                    // 명령어가 I(삽입)일 경우
                    case 'I':

                        // 앞에서부터 X번째 암호문 바로 다음에 y개의 암호문을 삽입한다.
                        y = Integer.parseInt(st.nextToken());
                        for (int j = 0; j < y; j++) {
                            String password = st.nextToken();
                            passwords.add(x, password);
                            x += 1;
                        }
                        break;
                    
                    // 명령어가 D(삭제)인 경우
                    case 'D':

                        // 앞에서부터 x번째 암호문 바로 다음부터 y개의 암호문을 삭제한다.
                        y = Integer.parseInt(st.nextToken());
                        for (int j = 0; j < y; j++) {
                            passwords.remove(x);
                        }
                        break;

                    // 명령어가 A(추가)인 경우
                    case 'A':

                        // 암호문 뭉치 맨 뒤에 x개의 암호문을 덧붙인다.
                        for (int j = 0; j < x; j++) {
                            passwords.add(st.nextToken());
                        }
                        break;
                    
                    default:
                        break;
                }
            }

            sb.append("#").append(tc).append(" ");

            // 수정된 결과의 처음 10개 암호문을 출력한다.
            for (int i = 0; i < 10; i++) {
                sb.append(passwords.get(i)).append(" ");
            }

            sb.append("\n");
        }

        System.out.println(sb);
    }
}

'Algorithm' 카테고리의 다른 글

[LeetCode] 2677. Chunk Array  (0) 2024.01.31
[BOJ] 4779. 칸토어 집합  (1) 2024.01.30
[SWEA] 10726. 이진수 표현  (0) 2024.01.29
[SWEA] 1288. 새로운 불면증 치료법  (0) 2024.01.29
[LeetCode] 2667. Create Hello World Function  (0) 2024.01.29

문제 

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AXRSXf_a9qsDFAXS

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

접근 방법

1. M의 이진수 표현의 마지막 N개의 비트가 모두 켜져 있다면, (M + 1)는 2^N의 배수이다.

2. 따라서 (M + 1)가 2^N으로 나누어 떨어진다면 "ON"을 출력하고, 그렇지 않다면 "OFF"를 출력한다.

 

풀이

// [SWEA] 10726. 이진수 표현

import java.util.*;
import java.io.*;

// public
class Solution {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;

        int T = Integer.parseInt(br.readLine());

        for (int tc = 1; tc <= T; tc++) {
            st = new StringTokenizer(br.readLine());
            int N = Integer.parseInt(st.nextToken());
            int M = Integer.parseInt(st.nextToken());
            
            sb.append("#").append(tc).append(" ").append((M + 1) % (1 << N) == 0 ? "ON" : "OFF").append("\n");
        }
        
        System.out.println(sb);
    }
}

'Algorithm' 카테고리의 다른 글

[BOJ] 4779. 칸토어 집합  (1) 2024.01.30
[SWEA] 1230. 암호문3  (1) 2024.01.29
[SWEA] 1288. 새로운 불면증 치료법  (0) 2024.01.29
[LeetCode] 2667. Create Hello World Function  (0) 2024.01.29
[LeetCode] 2666. Allow One Function Call  (0) 2024.01.26

문제

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV18_yw6I9MCFAZN

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

접근 방법

// [SWEA] 1288. 새로운 불면증 치료법

import java.util.*;
import java.io.*;

// public
class Solution {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        
        // 테스트 케이스의 수
        int T = Integer.parseInt(br.readLine());
        
        for (int tc = 1; tc <= T; tc++) {
            int N = Integer.parseInt(br.readLine());

            // k번째에 센 양의 횟수
            int accNum = 0;

            // 비트연산을 통해 각 숫자가 저장되었는지를 확인할 수 있는 변수
            int numCnt = 0;

            // 0 ~ 9까지 모든 숫자를 탐색하였다면 numCnt는 1111111111(2)로, 1023이 될 것이다.
            // 즉 numCnt 값이 1023이 될 때까지 반복
            while (numCnt < 1023) {

                // accNum에 N을 더함.
                accNum += N;

                // curNum에 현재 누적값 추가
                int curNum = accNum;

                // 각 자리수를 순회하며
                while (curNum > 0) {

                    // 해당 자리수의 숫자에 해당하는 비트 위치와 numCnt를 OR 연산시킨다.
                    numCnt = numCnt | (1 << (curNum % 10));

                    curNum /= 10;
                }
            }
            
            // 0 ~ 9까지의 모든 숫자가 나왔을 때의 accNum을 출력한다.
            sb.append("#").append(tc).append(" ").append(accNum).append("\n");
        }

        System.out.println(sb);
    }
}

'Algorithm' 카테고리의 다른 글

[SWEA] 1230. 암호문3  (1) 2024.01.29
[SWEA] 10726. 이진수 표현  (0) 2024.01.29
[LeetCode] 2667. Create Hello World Function  (0) 2024.01.29
[LeetCode] 2666. Allow One Function Call  (0) 2024.01.26
[LeetCode] 2665. Counter II  (0) 2024.01.25

+ Recent posts