(막간 보충 공부중)
오늘 한 일
- 프로그래머스 30분 - 옹알이(1)
- 프로그래머스 30분 - 특정 문자 제거하기
- 푼 문제 코드 리뷰 및 리팩토링
- ‘여태 푼 문제 파일 중 랜덤으로 불러오기’ 프로그램 구상 및 개발 중 - fs 모듈 공부중
특정 문자 제거하기
특정 문자 제거하기
문자열 replaceAll 이용
function solution1(my_string, letter) {
return my_string.replaceAll(letter, '');
}
배열 이용
// replaceAll 없이
function solution2(my_string, letter) {
return my_string.split(letter).join('');
}
배열 내장 함수 없이 (내장 함수를 쓰지 않은 이 방식이 코딩 테스트에서는 가장 좋다...)
function solution3(my_string, letter) {
let newStr = ''
for (let char of my_string) {
if (char !== letter) {
newStr += char;
}
}
return newStr;
}
정규식 이용:
// RegExp으로
function solution4(my_string, letter) {
// 1. 'haha'에서 모든 a를 매치하고 싶다:
// const regex = /a/g; // haha => hh
// 2. 문자열 a 말고 모든 변수 letter를 매치하고 싶다:
// const regex = new RegExp(`${letter}/g`)
// 3. new RegExp로 만들 때엔 슬래시(/)를 빼야 함. => 그러면 g나 i같은 플래그는 어떻게? => 제 2의 인수로 넣어주면 됨:
// const regex = new RegExp(letter, 'g');
const re = new RegExp(letter, 'g');
return my_string.replace(re, '');
}
배운 점:
- 정규식에서,
/ha/g
는new RegExp(’ha’, ‘g’)
와 같다. (플래그를 2번째 인수로 보내줌)
- 정규식에서, 변수를 패턴으로 받으려면 /ha/g 방식으로는 안되고 객제 선언 방식으로 해줘야 한다 :
const letter = 'ha'; const regex = new RegExp(letter, 'g');
옹알이 (1)
옹알이 (1)
(혼자) 처음에 푼 방식:
function solution1(babblingArray) {
const possibles = ["aya", "ye", "woo", "ma"];
let count = 0;
for (let i = 0; i < babblingArray.length; i++) {
let word = babblingArray[i];
word = word.replace("aya", " ")
.replace("ye", " ")
.replace("woo", " ")
.replace("ma", " ")
.trim();
if (word === "") {
count++;
}
}
return count;
}
⇒ possibles를 사용하지 않고 있다. 나중에 할 수 있는 옹알이가 더 많아지게 될 때를 대비해 .replace()를 계속 추가해야 하는 지금의 상황보다 possibles 객체를 이용해 거기에만 추가해도 되게끔 만드는 것이 좋겠다.
⇒ 또 replace를 한 번 할 때마다 O(N)을 한 번 도는 것과 같다. 사실 nO(N)은 O(N)과 같다고 취급되므로 별 문제는 없지만, 그래도 replace를 네 번, 다섯번 돌게 되는 것을 방지할 수 있다면 더 좋을 것이다.
(Mob programming으로) 리팩토링 이후:
const POSSIBLES = ["aya", "ye", "woo", "ma"];
function solution(arr) {
let count = 0;
arr.forEach((word) => {
let j = 0;
let k = 0;
while (k !== word.length) {
const subString = word.slice(j, k + 1);
if (POSSIBLES.includes(subString)) {
// console.log(subString, " is a valid babble");
j = k + 1;
k = k + 1;
} else {
k++;
}
}
if (j === k) {
count++;
}
});
return count;
}
배운 점:
- Sliding Window 기법 : 루프 한 번에 인덱스 두 개를 놀리는 방식. 코테용 풀이법으로 좋다. 중상 정도의 풀이 점수를 받을 수 있을 것임.
⇒ 사실 sliding window 테크닉은 ‘같은 대상을 순회할 때’, 2중 for문을 만들 것을 단일 for문으로 만들 수 있는 기법이라 사용되는 것이다. 이 문제같은 경우엔 순회해야 하는 대상이 가능한 발음
POSSIBLES
와 주어진 옹알이arr
로 서로 달라, 결국 둘 다 검사하려면 nested 반복문이 될 수밖에 없는 구조이다. sliding window 테크닉을 쓴다고 하더라도 효용이 없어지게 되는 것이다. 시간복잡도로 따지면 forEach 문 안에 다시 while문이 있으므로 이중 for문, O(N^2)이게 되는 것은 sliding window 방식을 사용하지 않은 풀이와 같게 된다. 다만 sliding window라는 기법을 연습해 볼 수 있었다는 데에 의의를 두자.
Sliding Window 테크닉을 쓸 수 있는 문제는?
문제에서 객체나 배열, 문자열같이 iterable한 데이터 타입이 주어지고 다음과 같은 리턴값을 요구하는 경우:
- Minimum value
- Maximum value
- Longest value
- Shortest value
- K-sized value
‘연속된’이라는 키워드가 들어가는 경우.
ex) 주어진 숫자 배열에서, 연속된 두 개의 숫자 쌍 중 합이 가장 큰 쌍을 배열로 반환하기. ⇒ 2-sized value와 maximum value가 모두 요구되는 케이스.
ex) 주어진 문자열에서, 중복된 문자가 없는 가장 긴 부분 문자열(=연속됨)의 길이를 찾기. ⇒ longest value를 요구하는 케이스.
(참조: https://levelup.gitconnected.com/an-introduction-to-sliding-window-algorithms-5533c4fe1cc7)
매일 품새를 연습하기 위해 ‘여태 푼 문제 파일 중 하나를 랜덤으로 불러와주는 프로그램’을 만들고 싶다 (미완)(구상중):
매일 품새를 연습하기 위해 ‘여태 푼 문제 파일 중 하나를 랜덤으로 불러와주는 프로그램’을 만들고 싶다 (미완)(구상중):
FS
동기와 비동기. 모든 비동기 메소드는 뒤에 ‘Sync’를 달고 있는 형제 동기 메소드가 있다.
예: fs.writeFile() 과 fs.writeFileSync().
파일을 처리하는 데 항상 시간이 걸릴 것이라 감안하여 언제나 비동기 메소드(Sync가 안 붙은)를 써주고 콜백으로 완료 처리를 부탁하도록 하자.
기본 CRUD 메소드:
fs.writeFile(), fs.readFile(), fs.unlink()
구현해야 하는 workflow:
- 부분 파일명으로 특정 파일 찾기 ⇒ readdir() / read() / readFile() / exists() /
- 찾은 파일에서 ‘주석’부분까지만 읽어들이기 ✔️
- 부분 파일명으로 찾은 특정 파일의 이름에서 넘버링 따오기 ⇒ fsPromises.readdir()의 .name속성 /
- +1 해서 새 파일명으로 삼아 새 파일 만들고
- 찾은 ‘주석’ 부분을 써넣기.
- 저장하기(어디에?)
- 방금 만든 새 파일 편집기로 열어두기.
아니다. …각 kata 파일들은 테스트 코드와 소스 코드가 한 쌍씩만 있는 게 더 깔끔하고 좋으려나…
한 파일 안에 날짜 구분해서 몽땅 집어넣기의 장단점:
장: 폴더 관리가 깔끔해진다.
단: 파일 하나의 구조가 지저분해진다. 어떻게 새롭게 푼 부분을 구분해 넣을 것인가?
⇒ 음. 크게 달라진 날과 날의 코드마다 마일스톤처럼 기록으로 남겨두고, 그게 그거같이 비슷비슷하게 풀린 코드는 풀고서 이전 코드를 삭제하는 식으로?
⇒ 날짜와 날짜의 구분은 그냥 /* 2023. 02. 20 (월) */ 같이 주석으로 간단히 표시하자.
여러 파일을 만들 때의 장단점:
장: 디렉토리 목록을 보고 얼마나 여러 번 반복해서 풀었는지 한 눈에 볼 수 있다. (푼 횟수만큼 파일이 생성되었을 테니) ⇒ 파일명 끝에 반복 횟수를 매번 업데이트 하는 방법으로 대체할 수 있을 것 같다.
단: 너무 많은 파일이 생성된다. 나중에는 오히려 디렉토리 구조로 한 눈에 파악하기가 더 힘들어지게 된다.
생각하다보니 여러 파일을 만드는 것은 단점이 너무 크다는 결론이 났다.
하지만 파일 모듈을 다루는 연습을 위해 한 번 원래의 계획대로 만들어보는 것도 나쁘지 않을 듯? 일단 ‘새 파일명으로 편집기를 여는 것’까지는 하고, 저장하지 않고 파괴하면 되잖아.
Uploaded by N2T