이번에 미* 라는 스타트업에서 코딩테스트를 떨어졌다!
부들부들 하지만, 내가 낸 코드 결과물을 보니 그럴만도 하다.
코딩테스트는 못하는 사람들을 걸러내는 시험이라고 생각한다. 어렵고 복잡한 문제를 내서 구직자를 곤란하게 하는것이 아니라, 평소에 이 사람이 어떤식으로 코드를 짜고 테스트하고 관리하는지, 이해는 잘 되는지, 클린한지,
나라면 그런걸 검토할 것이다.
단순히 코딩테스트로 역량을 알아내는건 한계가 있지만, 코드짜는 스타일은 닦아온 그대로 보여줄 수 밖에 없지 않을까
다음 코테에서는 이렇게 생각없이 문제풀이위주로 짜지 않으려고 검토할겸 기록을 남긴다.
두문제 다섯시간, 난이도 쉬움을 왜 다 풀지도 못했을까 싶지만, 반성할겸 코드 스타일 점검할겸 복기해보자
처음 풀때는 CLI 프로그램을 Stdin 로 인풋받는 프로그램인줄 알고 readline 라이브러리를 사용해서 테스트 환경을 구축했다.
const question = function () {
rl.question('give me a number1: ', (val1) => {
rl.question('give me a number2: ', (val2) => {
const result = sum_Of_BigInt(translate(val1), translate(val2));
console.log(toHan(result))
rl.close()
})
})
}
그런데 이게 절대 아닌거같다.
커맨드로 실행할 수 만 있으면 되는거 아닐까?
두번 풀때는 함수와, 테스트케이스를 받아 테스트를 돌리는 util 함수를 사용했다.
exports.runTest = (f, testCase) => {
time("time");
const testResult = testCase.map((tc, index) => {
const result = { index, ...tc };
const { args, target } = result;
try {
const expect = f(...args);
result.expect = expect;
result.ok = compareAnswer(expect, target);
} catch (error) {
result.error = error;
}
return result;
});
timeEnd("time");
testResult.map(makeResultString).forEach(str => log(str));
log(analyzeTestResult(testResult));
};
다른분에 코드를 상당부분 가져왔다. 나중에는 내 입맛에 맞게 adapt 해야할것같다.
문제로 들어가보자
1번은, 큰 정수를 문자열로 입력을 받아 더한 후 다시 문자열로 반환해주어야한다.
어떻게 풀어야 할까
두가지 함수를 만들어서 풀자.
처음 푼 코드는 아래와 같다.
function BigInt(string) {
const result = []
if (!string) result.push('0')
for (let i = 0; i < string.length; i++) {
result.push(string[i])
}
// console.log(result);
return result
}
function sum_Of_BigInt(a, b) {
const val1 = new BigInt(a)
const val2 = new BigInt(b)
const result = []
const diff = val1.length - val2.length
if (diff < 0) {
for (let i = 0; i < diff * -1; i++) {
val1.unshift('0')
}
}
else {
for (let i = 0; i < diff; i++) {
val2.unshift('0')
}
}
let up = 0
for (let i = val1.length - 1; i >= 0; i--) {
let v1 = val1[i] * 1
let v2 = val2[i] * 1
// result.unshift(v1 + v2)
let temp = v1 + v2 + up
if (temp >= 10) {
result.unshift(temp - 10);
up = 1
}
else {
result.unshift(temp)
up = 0
}
}
if (up) result.unshift(up)
// console.log(result)
// console.log('answer : ', result.join(''))
return (result.join(''))
}
352 를 넣으면 ["3", "5", "2"] 가 되고
21 을 넣으면 ["2", "1"] 가 된다.
두 수를 더할때 ["2", "1"]을 ["0", "2", "1"] 로 자릿수를 맞춰주고 마지막부터 같은 줄끼리 더하고 올림값이 있으면 추가로 더해주는 식으로 구현했다.
구현자체가 틀리지는 않았지만,
깔끔하게 바꾸려면 어떻게 해야할까...
람다식을 최대한 활용하고, If문을 최대한 줄이려고 했다.
그 결과 이렇게 바뀌었다.
const { log, error, time, timeEnd } = console;
const BigInt = (num: string): Array<string> => {
const result: string[] = [];
num.split('').forEach((val) => {
result.unshift(val);
})
return result;
}
const ArrSum = (arr1: Array<string>, arr2: Array<string>): Array<string> => {
if (arr1 === [] || arr2 === []) return arr1[0] && arr1 || arr2;
const len = arr1.length > arr2.length && arr1.length || arr2.length;
const result = [];
let ceil = 0;
for (let i = 0; i < len; i++) {
let num1 = Number(arr1[i]) || 0;
let num2 = Number(arr2[i]) || 0;
let val = num1 + num2 + ceil;
if (val >= 10) {
val = val - 10;
ceil = 1;
}
else {
ceil = 0;
}
result.push(String(val));
}
if (ceil) result.push('1');
result.reverse()
log(result)
return result;
}
다시 더 어떻게 개선할 수 있을까?
일단 두 함수는 무조건 독립적이어야 할것이다.
처음 풀때는 두번째함수에서 첫번째 함수를 사용하는 이런 부분은 무조건 빼줘야 할 것이고,
자릿수를 맞추는 부분을 BigInt로 옮기는것도 고려해봄직한가?
더할때 자릿수 맞추는 부분이 필요한거니까 이부분은 그대로 가야할까?
타입스크립트는 굳이 일단 필요가 없을것같아보이기도 한다.
const { log, error, time, timeEnd } = console;
const sum = (arg1, arg2) => {
const StrtoArr = (str) => str.split('').reverse();
const ArrSum = (arr1, arr2) => {
const len = arr1.length > arr2.length && arr1.length || arr2.length;
const result = [];
let ceil = 0;
for (let i = 0; i < len; i++) {
let num1 = Number(arr1[i]) || 0;
let num2 = Number(arr2[i]) || 0;
let val = num1 + num2 + ceil;
if (val >= 10) {
val = val - 10;
ceil = 1;
}
else {
ceil = 0;
}
result.push(String(val));
}
if (ceil) result.unshift('1');
return result.join('');
}
return ArrSum(arg1, arg2)
}
const runTest = (f, testCase) => {
const result = testCase.map((ele, index) => {
const { args, answer } = ele;
const expect = f(...args);
return ({ index, result: (answer === expect), answer, expect });
})
log(result)
}
const data = [
[["123", "456"], "579"],
[["99", "1"], "100"],
[["1", "999"], "1000"],
]
const testCase = (data) => {
return data.map((ele, index, arr) => {
const args = ele[0];
const answer = ele[1];
return { args, answer };
})
}
runTest(sum, testCase(data))
테스트하는 함수도 새로 작성해보고
Bigint 함수도 한줄로 줄였다.
또한 메인함수안에서 함수를 표현식으로 선언해서 사용했다.
ArrSum 함수내 for 문을 줄여보고 싶어서
map 함수로 해봤는데 아직은 잘안된다. 방법이 있을까 싶어진다..