문제

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

문제

Write a function createHelloWorld. It should return a new function that always returns "Hello World".

 

예제

createHelloWorld 함수에 의해 만들어진 함수는 항상 "Hello World"를 반환해야 한다.

 

함수에 인자가 포함될 수 있지만 함수는 항상 "Hello World" 만을 반환해야 한다.

 


코드

/**
 * @return {Function}
 */
var createHelloWorld = function() {
    
    return function(...args) {
        return "Hello World";
    }
};

/**
 * const f = createHelloWorld();
 * f(); // "Hello World"
 */

 

함수에 어떠한 인자가 들어와도 호출 시 항상 "Hello World"를 반환한다.

문제

Given a function fn, return a new function that is identical to the original function except that it ensures fn is called at most once.

The first time the returned function is called, it should return the same result as fn.
Every subsequent time it is called, it should return undefined.

 

예제

처음 호출 시 fn에 argument 값들이 올바르게 들어가고 값을 반환한다.

하지만 두번째 호출부터는 fn 함수를 호출하지 않고 undefined를 반환한다.

마찬가지로 처음 호출 시 fn 함수에 주어진 argument 값들이 올바르게 들어간 뒤 값을 반환하지만,

이후에는 fn 함수를 호출하지 않고 undefined를 반환한다.

 

 


코드

/**
 * @param {Function} fn
 * @return {Function}
 */
var once = function(fn) {
    let isUsed = false;
    return function(...args){
        if (!isUsed) {
            isUsed = true;
            return fn(...args);
        }
    }
};

/**
 * let fn = (a,b,c) => (a + b + c)
 * let onceFn = once(fn)
 *
 * onceFn(1,2,3); // 6
 * onceFn(2,3,6); // returns undefined without calling fn
 */

 

isUsed라는 변수를 기본값 false로 초기화한 뒤, 함수가 실행되면 true로 변환한다.

함수는 isUsed가 false일 때, 즉 처음 호출 시에만 fn 함수를 실행시키고, 이후부터는 isUsed가 true이기 때문에 if 문이 실행되지 않고 undefined를 반환한다.

문제

Write a function createCounter. It should accept an initial integer init. It should return an object with three functions.

The three functions are:

increment() increases the current value by 1 and then returns it.
decrement() reduces the current value by 1 and then returns it.
reset() sets the current value to init and then returns it.

 

예제

counter 변수는 increment, decrement, reset 함수들이 들어있는 객체를 반환하는데, 각 함수를 실행시킬 때마다 counter 내에 있는 값이 함수 기능에 의해 계산된 뒤 반환됨.

 

counter 내부의 값은 보존되기 때문에, 증가하는 함수인 increment()를 여러 번 호출할 시 내부 값이 해당 횟수만큼 오르는 모습을 확인할 수 있음.

 


코드

/**
 * @param {integer} init
 * @return { increment: Function, decrement: Function, reset: Function }
 */
var createCounter = function(init) {
    let counter = init;
    
    return {
        increment() {
            counter += 1;
            return counter;
        },
        decrement() {
            counter -= 1;
            return counter;
        },
        reset() {
            counter = init;
            return counter;
        }
    }
};

/**
 * const counter = createCounter(5)
 * counter.increment(); // 6
 * counter.reset(); // 5
 * counter.decrement(); // 4
 */

 

함수 createCounter의 반환값은 3개의 함수가 들어있는 객체가 된다.

 

1. increment() : counter 값을 1 증가시킨다.

2. decrement() : counter 값을 1 감소시킨다.

3. reset() : counter 값을 init으로 초기화시킨다.

문제

Write a generator function that returns a generator object which yields the fibonacci sequence.

The fibonacci sequence is defined by the relation Xn = Xn-1 + Xn-2.

The first few numbers of the series are 0, 1, 1, 2, 3, 5, 8, 13.

 

예제

gen.next().value는 호출할 때마다 피보나치의 다음 숫자가 출력된다.

 

gen.next()가 호출되지 않았으므로 아무것도 출력되지 않는다.

 


코드

/**
 * @return {Generator<number>}
 */
var fibGenerator = function*() {
    const fib = [0, 1];
    let idx = 0;
    
    yield 0;
    idx += 1;
    
    yield 1;
    idx += 1;
    
    while (idx <= 50) {
        fib.push(fib[fib.length - 2] + fib[fib.length - 1]);
        idx += 1;
        
        yield fib[fib.length - 1]
    }
};

/**
 * const gen = fibGenerator();
 * gen.next().value; // 0
 * gen.next().value; // 1
 */

 

JavaScript의 generator는 언제든지 실행을 중지하고 재개할 수 있는 함수로, 내부의 변수 값들은 출입 과정에서 저장된 상태로 남아있습니다.

Generator 함수는 호출되어도 즉시 실행되지 않는 대신 Iterator 객체가 반환됩니다.

이후 Iterator의 next() 메서드를 호출하면 Generator 함수가 실행되어 yield 문을 만날때까지 진행하고, 반환값은 다음과 같습니다.

 

`{value: <반환값>, done: <완료 여부>}`

 

만약 정상적으로 yield문을 만났다면 해당 반환값이 value에 담기고, done에는 false가 담겨있게 됩니다. 만약 yield문을 만나지 못하고 함수가 종료되었을 경우, value 값에는 undefined가 담기고 done에는 함수 실행을 모두 완료했다는 의미로 true가 담기게 됩니다.

 

+ Recent posts