Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions 백하연/24주차/달리기 경주.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/** 달리기 경주
*
* 얀에서는 매년 달리기 경주가 열립니다.
* 해설진들은 선수들이 자기 바로 앞의 선수를 추월할 때 추월한 선수의 이름을 부릅니다.
* 예를 들어 1등부터 3등까지 "mumu", "soe", "poe" 선수들이 순서대로 달리고 있을 때, 해설진이 "soe"선수를 불렀다면 2등인 "soe" 선수가 1등인 "mumu" 선수를 추월했다는 것입니다.
* 즉 "soe" 선수가 1등, "mumu" 선수가 2등으로 바뀝니다.
*
* 선수들의 이름이 1등부터 현재 등수 순서대로 담긴 문자열 배열 players와 해설진이 부른 이름을 담은 문자열 배열 callings가 매개변수로 주어질 때, 경주가 끝났을 때 선수들의 이름을 1등부터 등수 순서대로 배열에 담아 return 하는 solution 함수를 완성해주세요.
*/
function solution(players, callings) {
const map = new Map();
for (let i = 0; i < players.length; i++) {
map.set(players[i], i);
}

// 1. callings를 순회하며 불린 이름을 하나씩 가져온다.
for (let i = 0; i < callings.length; i++) {
// 2. map에서 불린 선수의 현재 등수(idx)를 찾는다.
const playerIdx = map.get(callings[i]);
console.log(playerIdx);

// 3. 바로 앞 선수의 등수(idx - 1)와 그 이름을 알아낸다.
const frontPlayer = players[playerIdx - 1];
console.log(frontPlayer);

// 4. players 배열에서 두 선수의 위치를 서로 바꾼다.
players[playerIdx - 1] = callings[i];
players[playerIdx] = frontPlayer;
console.log(players);

// 5. map에서도 두 선수의 바뀐 등수를 갱신한다. (map.set 이용)
map.set(callings[i], playerIdx - 1);
map.set(frontPlayer, playerIdx);
}

console.log(map);
return players;
}

// 개선
function solution(players, callings) {
const map = new Map();
players.forEach((player, idx) => map.set(player, idx));

for (const calling of callings) {
const playerIdx = map.get(calling);
const frontPlayer = players[playerIdx - 1];

players[playerIdx - 1] = calling;
players[playerIdx] = frontPlayer;

map.set(calling, playerIdx - 1);
map.set(frontPlayer, playerIdx);
}

console.log(map);

return players;
}

console.log(solution(['mumu', 'soe', 'poe', 'kai', 'mine'], ['kai', 'kai', 'mine', 'mine'])); // ["mumu", "kai", "mine", "soe", "poe"]
69 changes: 69 additions & 0 deletions 백하연/24주차/소수 찾기.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/* 소수 찾기
* 1부터 입력받은 숫자 n 사이에 있는 소수의 개수를 반환하는 함수, solution을 만들어 보세요.
* 소수는 1과 자기 자신으로만 나누어지는 수를 의미합니다.
* (1은 소수가 아닙니다.)
*/
// 효율성 테스트 실패 (시간 초과)
function solution(n) {
let count = 0;

function isPrime(x) {
if (x < 2) return false;

for (let i = 2; i <= Math.sqrt(x); i++) {
if (x % i === 0) return false;
}
return true;
}

for (let i = 2; i <= n; i++) {
if (isPrime(i)) count++;
}
return count;
}

function solution(n) {
let arr = [];
for (let i = 2; i <= n; i++) {
arr.push(i);
}

return arr.filter((v) => v === 2 || v % 2 !== 0).filter((v) => v === 3 || v % 3 !== 0).length;
}

function solution(n) {
const isPrime = new Array(n + 1).fill(true);
isPrime[0] = false;
isPrime[1] = false;

for (let i = 2; i <= Math.sqrt(n); i++) {
if (isPrime[i]) {
for (let j = i * i; j <= n; j += i) {
isPrime[j] = false;
}
}
}

return isPrime.filter(Boolean).length;
}

// 다른 사람의 풀이
function other(n) {
const s = new Set();
for (let i = 1; i <= n; i += 2) {
s.add(i);
}
s.delete(1);
s.add(2);
for (let j = 3; j <= Math.sqrt(n); j++) {
if (s.has(j)) {
for (let k = j * 2; k <= n; k += j) {
s.delete(k);
}
}
}
return s.size;
}

console.log(other(10));
console.log(other(5));
39 changes: 39 additions & 0 deletions 백하연/24주차/시저 암호.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* 시저 암호
*
* 어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다.
* 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다.
* 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.
*
* 제한 조건
* 공백은 아무리 밀어도 공백입니다.
* s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
* s의 길이는 8000이하입니다.
* n은 1 이상, 25이하인 자연수입니다.
*/

// 핵심 패턴 : 문자열 처리 - split → map(아스키코드 변환 + % 26으로 범위 순환) → join
// 복기 : split → map → join 문자열을 하나씩 변환할 때, % N (나머지 연산)으로 범위를 순환이 필요할 때 (범위를 벗어나면 처음으로 돌아가야 할 때) 자주 나오는 패턴입니다. 이번 문제에서는 알파벳이 26글자이므로 % 26을 활용해서 범위를 순환할 수 있습니다.
function solution(s, n) {
const ALPHABET_SIZE = 26;
const UPPERCASE_BASE = 65;
const LOWERCASE_BASE = 97;

return s
.split('')
.map((char) => {
const code = char.charCodeAt(0);

if (char === ' ') return ' ';

if (char === char.toUpperCase()) {
return String.fromCharCode(((code - UPPERCASE_BASE + n) % ALPHABET_SIZE) + UPPERCASE_BASE);
} else {
return String.fromCharCode(((code - LOWERCASE_BASE + n) % ALPHABET_SIZE) + LOWERCASE_BASE);
}
})
.join(''); // 5. 바뀐 문자들을 모두 합쳐서 문자열로 리턴한다.
}

console.log(solution('AB', 1));
console.log(solution('z', 1));
console.log(solution('a B z', 4));
26 changes: 26 additions & 0 deletions 백하연/24주차/약수의 합.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* 약수의 합
* 정수 n을 입력받아 n의 약수를 모두 더한 값을 리턴하는 함수, solution을 완성해 보세요.
*/
function solution(n) {
const result = [];
for (let i = 0; i <= n; i++) {
if (n % i === 0) result.push(i);
else continue;
}
return result.reduce((acc, cur) => acc + cur, 0);
}

// 풀이 개선
function solution(n) {
let result = 0;
for (let i = 1; i <= n; i++) {
if (n % i === 0) result += i;
else continue;
}
return result;
}
console.log(solution(12));
console.log(solution(5));

// 핵심 패턴 : 1부터 n까지 완전탐색 + 조건 만족할 때 누적
// 약수 찾기, 소수 찾기, 특정 배수 합산
75 changes: 75 additions & 0 deletions 백하연/24주차/중요한 단어를 스포 방지.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* 중요한 단어를 스포 방지
*
* 카카오톡은 메시지의 일부를 가려두었다가, 클릭했을 때만 공개되는 스포 방지 기능을 제공합니다. 이 기능을 활용하면 중요한 정보를 가리고 보낼 수 있습니다.
*
* 무지는 이 기능을 이용해 하나의 메시지 곳곳에 스포 방지 기능을 적용해 당신에게 보냈습니다.
* 당신은 메시지 시작부터 왼쪽 → 오른쪽 순서로 스포 방지 구간을 하나씩 클릭해 공개되는 단어들 중, 중요한 단어가 몇 개인지 확인하려 합니다.
*
* 단어 및 중요한 단어 규칙
*
* 단어는 공백으로 구분되며, 알파벳 소문자와 숫자로만 구성된 연속된 문자열입니다.
* 단어를 구성하는 문자들의 인덱스 중 하나 이상이 스포 방지 구간에 포함될 경우, 해당 단어는 스포일러 방지 단어로 간주합니다.
* 즉, 단어 내 일부 문자에만 스포일러 방지 기능이 적용되더라도, 해당 단어 전체를 스포일러 방지 단어로 간주합니다.
* 한 단어가 여러 개의 스포 방지 구간에 걸쳐 있을 수 있으며, 하나의 스포 방지 구간에 여러 단어가 포함될 수 있습니다.
* 스포 방지 구간을 클릭해 단어의 모든 문자가 공개되었을 때, 그 단어가 아래 조건을 모두 만족하면 중요한 단어입니다.
* 스포 방지 단어여야 합니다.
* 메시지의 스포 방지 구간이 아닌 구간(= 어떤 스포 방지 구간에도 속하지 않는 모든 구간: 각 구간의 앞·사이·뒤 포함)에 등장한 적이 없어야 합니다.
* 이전에 공개된 스포 방지 단어와 중복되지 않아야 합니다.
* 여러 단어가 동시에 공개된 경우, 왼쪽부터 순서대로 하나씩 중요한 단어인지 판단합니다.
* 무지가 당신에게 보내온 메시지를 나타내는 문자열 message와 스포 방지가 적용된 구간을 나타내는 2차원 정수 배열 spoiler_ranges가 매개변수로 주어질 때, 스포 방지 단어 중 중요한 단어의 수를 return 하도록 solution 함수를 완성해 주세요.
*
*
*/
// 문제 요약 : 스포방지구간에 등장한 적 없고 중복되지 않은 스포 방지 단어 중 중요한 단어의 수를 찾는 문제
function solution(message, spoiler_ranges) {
let important = 0;

const words = [...message.matchAll(/[a-z0-9]+/g)].map((match) => {
const [word] = match;
const start = match.index;
const end = start + word.length - 1;

return { word, start, end };
});

// 각 단어가 스포 방지 구간에 걸리는지 확인
const spoiler = words.filter((word) =>
spoiler_ranges.some(([start, end]) => !(word.start > end || word.end < start)),
);

// 스포 방지 구간 밖에 등장한 단어
const nonSpoiler = words.filter((word) =>
spoiler_ranges.every(([start, end]) => word.start > end || word.end < start),
);

// 스포 방지 단어 중 3번 목록에 없고 이전에 공개된 적 없으면 중요한 단어 카운트 + 1
const seen = new Set();

for (const [start, end] of spoiler_ranges) {
const spoilerWords = spoiler.filter((w) => !(w.start > end || w.end < start));

spoilerWords.forEach((w) => {
if (!nonSpoiler.some((n) => n.word === w.word) && !seen.has(w.word)) {
important++;
seen.add(w.word);
}
});
}

return important;
}

console.log(
solution('here is muzi here is a secret message', [
[0, 3], // 'here'
[23, 28], // 'secret'
]),
); // 1
console.log(
solution('my phone number is 01012345678 and may i have your phone number', [
[5, 5], // o
[25, 28], // 567
[34, 40], // may i
[53, 59], // one num
]),
); // 4
24 changes: 17 additions & 7 deletions 백하연/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,22 @@
| 260316 | LV1 | [중요한 단어를 스포 방지](https://school.programmers.co.kr/learn/courses/30/lessons/468370) | 25% | |
| 260316 | LV1 | [(공통문제) 노란불 신호등](https://school.programmers.co.kr/learn/courses/30/lessons/468371) | 30% | |

### 24주차

| **날짜** | **난이도** | **문제 이름** | **정답률** | **문제 유형** |
| :------: | :--------: | :----------------------------------------------------------------------------------------------------: | :--------: | :-----------: |
| 260322 | LV1 | [달리기 경주](https://school.programmers.co.kr/learn/courses/30/lessons/178871) | 50% | |
| 260322 | LV1 | [소수 찾기](https://school.programmers.co.kr/learn/courses/30/lessons/12921) | 64% | |
| 260322 | LV1 | [시저 암호](https://school.programmers.co.kr/learn/courses/30/lessons/12926) | 74% | |
| 260322 | LV1 | [약수의 합](https://school.programmers.co.kr/learn/courses/30/lessons/12928) | 88% | |
| 260322 | LV1 | [(공통문제) 중요한 단어를 스포 방지](https://school.programmers.co.kr/learn/courses/30/lessons/468370) | 25% | |

### N주차

| **날짜** | **난이도** | **문제 이름** | **정답률** | **알고리즘** |
| :------: | :--------: | :-----------: | :--------: | :----------: |
| | LV | []() | % | |
| | LV | []() | % | |
| | LV | []() | % | |
| | LV | []() | % | |
| | LV | []() | % | |
| **날짜** | **난이도** | **문제 이름** | **정답률** | **문제 유형** |
| :------: | :--------: | :-----------: | :--------: | :-----------: |
| | LV | []() | % | |
| | LV | []() | % | |
| | LV | []() | % | |
| | LV | []() | % | |
| | LV | []() | % | |