반응형
문제 출처
https://school.programmers.co.kr/learn/courses/30/lessons/42893
문제 풀이 힌트
01. /[\d|\W]/
- [] : 문자 클래스를 정의 . 문자 클래스는 대괄호 안에 있는 문자들 중 하나와 일치하는지 검사
- \d : 숫자를 의미. [0-9]와 동일하게 작동, 숫자 하나와 일치.
- | : 또는 을 의미하는 논리 연산자 인데, 문자 클래스 내에서 사용되었기 때문에 단순히 문자 '|' 자체로 간주됨.
- \W: 비문자 (숫자, 영문자, 밑줄이 아닌 문자). [^a-zA-Z0-9]와 동일
결론)
숫자 또는 특수 문자 또는 '|'를 찾는다.
02. /<a href="https:\S*"/gi;
- <a href="https: 문자열과 정확히 일치하는 부분을 찾는다.
- \S* : \S는 비공백 문자를 의미하고, *는 0번 이상 반복을 의미한다.
- 플래그 부분
- g: 전체 문자열 탐색
- i: 대소문자 구분 안함
비공백 문자란? :\S
: 공백 문자가 아닌 모든 문자
ex) 알파벳 문자, 숫자, 특수문자, 기타 모든
공백 문자란? : \s
ex) ' ', 탭 \t, 줄바꿈 \n,
03. flatMap
let numbers = [1, 2, 3, 4];
let doubledNumbers = numbers.map(x => [x * 2]);
console.log(doubledNumbers);
// 결과: [[2], [4], [6], [8]]
let flatMappedNumbers = numbers.flatMap(x => [x * 2]);
console.log(flatMappedNumbers);
// 결과: [2, 4, 6, 8]
정답 풀이 코드
function solution(word, pages) {
let map = new Map();
word = word.toLowerCase();
pages.forEach((page, idx) => {
let pageArr = page.split('\n');
let urlIdx = pageArr.findIndex(p => p.match(/<meta property/))
let url = pageArr[urlIdx].match(/https:\S*/)[0].slice(0,-3); //자기 자신 링크
let startBodyIdx = pageArr.findIndex(p => p.match(/<body>/))
let endBodyIdx = pageArr.findIndex(p => p.match(/<\/body>/))
let body = pageArr.slice(startBodyIdx+1, endBodyIdx)
let wordCnt = body.flatMap(el => el.toLowerCase().split(/[\d|\W]/)).filter(e => e === word).length; //기본점수 : word 랑 일치하는 단어 수
let aLink = body.flatMap(el => el.match(/<a href="https:\S*"/gi)).filter(e => e !== null).map(el => el.slice(9,-1))//외부 링크
let point = wordCnt/aLink.length //기본점수/외부 링크수
map.set(url, {idx, wordCnt, point, aLink, linkPoint:0, matchPoint:0})
})
for(let [key, value] of map.entries()){//각 링크 점수를 채우기
let cnt = 0;
value.aLink.forEach(link => {
if(map.has(link)){
map.get(link).linkPoint += map.get(key).point
}
})
}
let answer = [0,0];
for(let [key, value] of map.entries()){
value.matchPoint = value.wordCnt + value.linkPoint
if(answer[1] < value.matchPoint){
answer[0] = value.idx
answer[1] = value.matchPoint
}
}
return answer[0]
}
//기본점수 : 검색어 등장 회수
//외부 링크 수 : 해당 => 외부 링크 수
//링크점수 : 해당 웹페이지로 링크 걸린 웹페이지들 (기본점수/외부 링크 수) 총합
//매칭점수 : 기본점수 + 링크점수
//return 매칭점수 가장 높은 웹페이지 index 구해라.
Only 정답 코드
function solution(word, pages) {
let map = new Map();
word = word.toLowerCase();
pages.forEach((page, idx) => {
let pageArr = page.split('\n');
let urlIdx = pageArr.findIndex(p => p.match(/<meta property/));
let url = pageArr[urlIdx].match(/https:\S*/)[0].slice(0,-3);
let startBodyIdx = pageArr.findIndex(p => p.match(/<body>/));
let endBodyIdx = pageArr.findIndex(p => p.match(/<\/body>/));
let body = pageArr.slice(startBodyIdx + 1, endBodyIdx);
let wordCnt = body.flatMap(el => el.toLowerCase().split(/[\d|\W]/)).filter(e => e === word).length;
let aLink = body.flatMap(el => el.match(/<a href="https:\S*"/gi)).filter(e => e !== null).map(el => el.slice(9, -1));
let point = wordCnt / aLink.length;
map.set(url, { idx, wordCnt, point, aLink, linkPoint: 0, matchPoint: 0 });
});
for (let [key, value] of map.entries()) {
value.aLink.forEach(link => {
if (map.has(link)) {
map.get(link).linkPoint += map.get(key).point;
}
});
}
let answer = [0, 0];
for (let [key, value] of map.entries()) {
value.matchPoint = value.wordCnt + value.linkPoint;
if (answer[1] < value.matchPoint) {
answer[0] = value.idx;
answer[1] = value.matchPoint;
}
}
return answer[0];
}
다른 정답 풀이 코드 02.
function solution(word, pages) {
// 검색할 단어를 소문자로 변환합니다.
word = word.toLowerCase();
// 정규 표현식 상수 정의
const REGEX_WORD = /[\d|\W]/; // 단어를 분리하는 정규식
const REGEX_URL = /<a href="https:\S*"/gi; // URL을 찾는 정규식
const META_URL = 'meta property'; // 메타 태그를 찾기 위한 문자열
// 각 페이지의 정보를 저장할 Map 객체를 생성합니다.
const pageInfo = new Map();
// 각 페이지를 순회하면서 필요한 정보를 추출합니다.
pages.forEach((page, idx) => {
const pageArr = page.split('\n'); // 페이지를 줄 단위로 나눕니다.
const urlIdx = pageArr.findIndex(el => el.includes(META_URL)); // 메타 태그가 있는 줄의 인덱스를 찾습니다.
const pageURL = pageArr[urlIdx].match(/"https:\S*"/gi)[0]; // 페이지의 URL을 추출합니다.
const bodyStart = pageArr.findIndex(el => el.includes("<body>")); // 본문 시작 태그를 찾습니다.
const bodyEnd = pageArr.findIndex(el => el.includes("</body>")); // 본문 종료 태그를 찾습니다.
const body = pageArr.slice(bodyStart + 1, bodyEnd); // 본문 내용을 추출합니다.
// 본문에서 검색어가 등장하는 횟수를 계산합니다.
const point = body.flatMap(str => str.toLowerCase().split(REGEX_WORD)).filter(e => e === word).length;
// 본문에서 외부 링크를 추출합니다.
const outLinks = body.flatMap(str => str.match(REGEX_URL)).filter(e => e).map(e => e.substr(8, e.length));
// 페이지 정보를 Map 객체에 저장합니다.
pageInfo.set(pageURL, { point, outLinks, idx, matchPoint: 0 });
});
// 각 페이지의 링크 점수를 계산합니다.
for (const [key, value] of pageInfo) {
const linkPoint = value.point / value.outLinks.length; // 링크 점수를 계산합니다.
// 각 외부 링크를 순회하며 링크 점수를 추가합니다.
for (const link of value.outLinks) {
if (pageInfo.has(link)) {
const origin = pageInfo.get(link);
const calculatedPoint = origin.matchPoint
? origin.matchPoint + linkPoint
: origin.point + linkPoint;
pageInfo.set(link, { ...origin, matchPoint: calculatedPoint });
}
}
}
// 최종 점수를 계산하여 결과를 정렬합니다.
const answer = [];
for (const [key, value] of pageInfo) {
const { point, idx, matchPoint } = value;
const finalPoint = matchPoint ? matchPoint : point;
answer.push([idx, finalPoint]);
}
// 점수 기준으로 내림차순 정렬, 점수가 같으면 인덱스 기준으로 오름차순 정렬합니다.
answer.sort((a, b) => a[1] === b[1] ? a[0] - b[0] : b[1] - a[1]);
// 가장 높은 점수를 가진 페이지의 인덱스를 반환합니다.
return answer[0][0];
}
Only 정답 코드 02.
function solution (word, pages) {
word = word.toLowerCase();
const REGEX_WORD = /[\d|\W]/;
const REGEX_URL = /<a href="https:\S*"/gi;
const META_URL = 'meta property';
const pageInfo = new Map();
pages.forEach((page, idx) => {
const pageArr = page.split('\n');
const urlIdx = pageArr.findIndex(el => el.includes(META_URL));
const pageURL = pageArr[urlIdx].match(/"https:\S*"/gi)[0];
const bodyStart = pageArr.findIndex(el => el.includes("<body>"));
const bodyEnd = pageArr.findIndex(el => el.includes("</body>"));
const body = pageArr.slice(bodyStart+1, bodyEnd);
const point = body.flatMap(str => str.toLowerCase().split(REGEX_WORD)).filter(e => e === word).length;
const outLinks = body.flatMap(str => str.match(REGEX_URL)).filter(e => e).map(e => e.substr(8, e.length));
pageInfo.set(pageURL, { point, outLinks, idx, matchPoint : 0 });
});
for(const [key, value] of pageInfo) {
const linkPoint = value.point / value.outLinks.length;
for(const link of value.outLinks) {
if(pageInfo.has(link)) {
const origin = pageInfo.get(link);
const calculatedPoint = origin.matchPoint
? origin.matchPoint + linkPoint
: origin.point + linkPoint;
pageInfo.set(link, { ...origin, matchPoint: calculatedPoint });
}
}
}
const answer = [];
for(const [key, value] of pageInfo) {
const { point, idx, matchPoint } = value;
const finalPoint = matchPoint ? matchPoint : point;
answer.push([ idx, finalPoint ]);
};
answer.sort((a, b) => a[1] === b[1] ? a[0] - b[0] : b[1] - a[1]);
return answer[0][0];
}
내 틀린 풀이 코드
function solution(word, pages) {
let map = new Map();
let idxMap = new Map();
//해당 웹 페이지 url과 idx 설정
//기본점수랑, 외부 링크수 정리하기
pages.forEach((page,idx) => {
let url = page.match(/^ <meta property="og:url" content="https:\/\/.*/m)
idxMap.set(url, idx);
let basicScore = page.match(/\bword\b/g)[0].length;
let alinks = page.match(/^a/g)[0]
map.set(idx, {basicScore, links:alinks}])
})
//각 링크가 몇개 다른 웹페이지에서 언급됐는지 count++
let linkScore = new Array(pages.length).fill(0);
for(let value of map.values()){
value[1].forEach((link) => {
let countIdx = idxMap(link)
linkScore[countIdx]++;
})
}
//기본점수 + 링크 점수 = 매칭점수 구하기
let answer=[0,0]; //idx, 매칭점수
for(let [key, value] of map.entries()){
let matchingScore = value[0] + linkScore[idxMap.get(key)];
if(answer[1] < matchingScore) answer = [idxMap.get(key),matchingScore];
else if(answer[1] === matchingScore && answer[0] > idxMap.get(key)){
answer[0] = idxMap.get(key)
}
}
return answer[0]
}
//검색 개발팀 웹 페이지의 매칭점수
//기본점수, 외부 링크수, 링크점수, 매칭점수
//-기본점수: 텍스트 중 검색어 등장 횟수 (대소문자 무시)
//외부 링크수: 다른 외부 페이지로 연결된 링크 개수
//링크점수: 해당 웹페이지가 링크가 걸림 (다른 웹페이지의 기본점수 /외부링크 수 총합)
//매칭점수:기본점수 + 링크점수
//정규식 표현으로 얼마나 문자열을 원하는 만큼 가져오냐?
//긴 문장을 어떻게 요약 정리하나?
//각 모든 pages를 반복문으로 돈다.
//idxMap 객체로
//Map 객체로 정리한다.
//기본점수: word가 몇개인지 센다.
//외부 링크수: 다른 웹 페이지 링크가 몇개인지 센다.
//Map객체를 돌면서 계산한다.
//링크 점수: 다른 페이지에서 걸린 점수
//매칭 점수를 구한다.
//return 매칭 점수 가장 높은 웹페이지 index
반응형
'알고리즘 문제 풀기' 카테고리의 다른 글
프로그래머스- 신규 아이디 추천 (정규식) (0) | 2024.07.28 |
---|---|
프로그래머스:주사휘 고르기 - javascript(조합, 백트래킹, 구현) (0) | 2024.07.21 |
프로그래머스: 산 모양 타일링 - javascript(dp) (0) | 2024.07.15 |
프로그래머스: [1차] 추석 트래픽- javascript(시간함수, 구간 최대값) (0) | 2024.07.14 |
프로그래머스:코딩테스트 공부 - javascript(dp) (0) | 2024.07.13 |