[ 정규식 ] - 2019 카카오 블라인드 채용 1차 "매칭 점수"
이 문제또한 프로그래머스에 존재한다
코딩테스트 연습 - 매칭 점수
매칭 점수 프렌즈 대학교 조교였던 제이지는 허드렛일만 시키는 네오 학과장님의 마수에서 벗어나, 카카오에 입사하게 되었다. 평소에 관심있어하던 검색에 마침 결원이 발생하여, 검색개발팀
programmers.co.kr
문제의 내용을 요약해보자면, 주어진 배열중 매칭점수가 가장높은 배열의 인덱스를 찾는것이다
점수를 주어지는 방법은 총 4가지이다
일반점수 ( 주어진 단어가 일치하는 횟수 ) , 링크점수 ( 내가 링크건 횟수 ) , 외부링크점수 ( 외부사이트 별 - 나를 링크건 횟수 / 외부사이트에서 링크건 모든 횟수를 모두 더한다) , 매칭점수 ( 일반점수 + 외부링크점수 합 )
이런상황에서 문자열 정규식을 통해 주어진 단어 가 몇번들어갔는지 , 내가 링크건 횟수를 구할 수 있엇다.
사용한 방식의 큰 틀은 아래와 같다.
Pattern pattern = Pattern.complie("정규식");
Matcher matcher = pattern.matcher("주어진 지문");
int count=0;
String url="";
while(matcher.find()){
count++;
url = matcher.group();
}
주어진 정규식을 지문에서 찾아 matcher.find()로 일치하는것을 찾을때마다 count를 +1 씩하였고, 찾는 텍스트를 저장할대에는 matcher.group()을 통해 url에 저장하였다.
수정된 전체 코드
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.HashMap;
class Solution {
public int solution(String word, String[] pages) {
//일반점수(map) ,자신의 URL (map) , 외부 링크 점수(map) , 외부 링크 URL(array((map))) , 링크 점수(map) , 매치점수(map) , 토탈 점수(map) ;
ArrayList<HashMap<String,Object>> tArray = new ArrayList<HashMap<String,Object>>();
//토탈점수(int)
ArrayList<Integer> lankArray = new ArrayList<Integer>();
//지문 마다 반복
for(String page : pages ) {
//일반 점수 구하기
HashMap<String,Object> resultMap = new HashMap<String,Object>(); //각 결과 담을 map
String reg=word; //주어진 단어 대문자 변형
Pattern pattern = Pattern.compile("\\b(?i)"+word+"\\b"); // 단어 기준
Matcher matcher = pattern.matcher(page.replaceAll("[0-9]"," ")); // 지문 대문자 변형
int normalCount=0; //일반점수 카운트용
while(matcher.find()){
normalCount++;
}
resultMap.put("normalP",normalCount);
// 일반 점수 구하기 종료
//자신의 url 찾기
reg = "<meta property=\"og:url\" content=\"(https://\\S*)\"";
pattern = Pattern.compile(reg); // 정규식
matcher = pattern.matcher(page); //지문
String myUrl="";
while(matcher.find()){
myUrl=matcher.group(1).replaceAll("\"", "");; //찾은 자신의 url
}
resultMap.put("myUrl",myUrl);
//자신의 url 찾기 종료
//외부링크 찾기
reg="<a href=\"(https://\\S*)\"";
pattern = Pattern.compile(reg); // 정규식
matcher= pattern.matcher(page); //지문
int outLinkCount=0; //찾은 외부링크 수
String otherUrl=""; //찾은 외부링크 주소
ArrayList<String> otherUrlList= new ArrayList<String>(); //찾은 외부링크 주소 담는 list
while(matcher.find()){
outLinkCount++; //찾은 외부링크 수 카운팅
otherUrl= matcher.group(1);
otherUrlList.add(otherUrl); //찾은 외부링크 list에 저장
}
resultMap.put("outLinkCount",outLinkCount);
resultMap.put("otherUrlList",otherUrlList);
//외부링크 찾기 종료
tArray.add(resultMap);
//여기까지 일반/외부링크 점수 계산
}
//추출한 점수를 가지고 링크 점수와 매칭점수를 구하여야한다.
//필요한 부분 자신을 제외한 인덱스에서 otherUrlList 에 자신의 URL 이 있는지 확인하고 있는 경우 상대방 기본점수 / 외부링크 점수를 하여 내 linkP에 더한다.
// 그다음 linkp + normalP 를 합해 matchP 에 저장한다
// 마지막으로 자신의 점수 , 외부링크점수 , 링크점수 , 매칭점수를 합해 totalP로 저장하고 lankList에 담는다
// Lanklist는 max값 index 찾기방법을 사용하여 max값의 인덱스를 구한다 .
for(HashMap<String,Object> result : tArray){
int nomalP = (int) result.get("normalP"); // 내 일반점수
int outLinkCount = (int) result.get("outLinkCount"); //내 외부링크 점수
String myUrl = (String) result.get("myUrl"); // 내 url
double linkP=0; // 내 링크 점수
double matchP=0; //내 매치점수
double totalP=0; // 내 토탈 점수
for(HashMap<String,Object> result1 : tArray){
//이중배열을 사용하고 자신이 아닐경우에만 계산
if(result!=result1){
double other_to_me_URL = 0; //링크 점수 계산시 상대방 외부링크에 내링크가 있는지를 확인하기위함
ArrayList<String> otherUrlList1 =(ArrayList) result1.get("otherUrlList"); //상대방 외부링크 URL LIST
int outLinkCount1 =(int) result1.get("outLinkCount"); //상대방 외부링크 수
int otherNormalP =(int) result1.get("normalP"); // 상대방 기본점수
// 상대방 외부링크 URL LIST 에 내 URL 있는지 검사
for(String url : otherUrlList1){
if(url.contentEquals(myUrl)) {
// System.out.println("url " +url);
other_to_me_URL++;
}
}
// 상대방 외부링크 URL LIST 에 내 URL 있는지 검사 종료
// 상대방 외부링크 URL LIST 에 내 URL 있는경우
if(other_to_me_URL!=0){
// 내 링크점수에 더한다 . (double)붙여줘야 소수점 계산이됨
linkP+=otherNormalP/(double)outLinkCount1;
}
// 상대방 외부링크 URL LIST 에 내 URL 있는경우 종료
}
}
matchP = nomalP+linkP;//내 매칭 점수
totalP= nomalP + outLinkCount + linkP + matchP; //내 토탈점수
result.put("linkP",linkP);
result.put("matchP",matchP);
result.put("totalP",totalP);
lankArray.add((int) totalP);
}
int maxIndex=0; // 쵀대같 인덱스
int init= 0; //시작값
//값을 하나씩꺼내 이전의 max값보다 값이 클경우만 인덱스와 init값을 수정
for(int i=0;i<lankArray.size();i++) {
if(init<lankArray.get(i)) {
init = lankArray.get(i);
maxIndex=i;
}
}
for(HashMap<String,Object> result : tArray){
System.out.println("결과보기 ");
System.out.println("normalP :"+result.get("normalP"));
System.out.println("myUrl :" +result.get("myUrl"));
System.out.println("outLinkCount :" +result.get("outLinkCount"));
ArrayList<String> tmpList=(ArrayList)result.get("otherUrlList");
for(int i = 0 ; i < tmpList.size();i++){
System.out.println("otherUrlList : " +result.get(i));
}
System.out.println("linkP :" +result.get("linkP"));
System.out.println("matchP :" +result.get("matchP"));
System.out.println("totalP :" +result.get("totalP"));
}
int answer = maxIndex;
return answer;
}
}
위 코드를 돌려보면 기본점수 (내가 검색한 단어가 지문에 몇번있는지 ) , 링크점수 ( 내가 외부 링크를 몇번 걸었고 , 그 주소는 먼지 ) 를 알수 있고 , 외부링크 점수를 찾기위해 내 url 도 알수 있다.
이제 남은 부분은 이렇게 찾은 데이터를 어떻게 저장하여 외부링크점수와 , 매칭점수를 줄지에대한 부분이다.
남은부분은 지금 당장 어떻게든 저장해서 풀면 풀겟지만 , 좀더 공부를 해본후 다른방법이 있는지 찾아봐야 겠다.
- 다른방법이나 더 좋은 방법이있으면 댓글이나 링크 주시면 감사하겠습니다.
============수정 ===============
퇴근하고 와서 문제를 끝까지 풀어봤는데.. 쉽지않았다. ( 코드도 수정했습니다 )
그것보다 두번째 지문 (Muzi 찾기 )의 값이 나는 계속 틀리다고 나오는데
#!MuziMuzi!)jayg07con&& 텍스트가있으면 , 기본점수가 2점아닌가..? 이게 왜 0점인지 이해를 못햇다...
============수정 ===============
음 다른 문제 풀이를 보니까 단어라는 부분을 체크하기위해서 word 를 찾을떄 "\\b(?i)"+word+"\\b" 를 사용하여야 한다 .. 그리고 "검색어 word는 하나의 영어 단어로만 주어지며 알파벳 소문자와 대문자로만 이루어져 있다. " 이 지문떄문이지 지문의 숫자를 지워주는 replaceAll("[0-9]"," ") 을 추가해주면 테스트 문제는 패스한다..
어차피 채점하기에서 70 점밖에안나옴 .. 다시 해야함
============수정 ===============
두번쨰 수정 url을 찾을 때 \"(https://.+)\"> 이렇게 찾던 부분을 \"(https://\S*)\" 로 변경하였습니다
\s는 탭 , 줄바꿈, 공백 등을 의미하는데 url 중간에 띄어쓰기나 개행 문자가 올수도 없고 ,
지문상에는 a태그에는 다른attribute를 안준다고하지만 다른사람들 후기 읽어보면 다른 attribute도 줄수 있기때문에 이부분을 수정하니 70->80으로 오름.,, 나머지 2,9,17,19는 나중에... 풀어야겟다. 아시는분 댓글좀 부탁드려요 ^^