TIL: 2022-05-18 알고리즘 day5

김하연·2022년 5월 19일
0

TIL: Today I Leaned

목록 보기
9/27

1. 로또의 최고 순위와 최저 순위

로또를 구매한 민우는 당첨 번호 발표일을 학수고대하고 있었습니다. 하지만, 민우의 동생이 로또에 낙서를 하여, 일부 번호를 알아볼 수 없게 되었습니다. 당첨 번호 발표 후, 민우는 자신이 구매했던 로또로 당첨이 가능했던 최고 순위와 최저 순위를 알아보고 싶어 졌습니다.
알아볼 수 없는 번호를 0으로 표기하기로 하고, 민우가 구매한 로또 번호 6개가 44, 1, 0, 0, 31 25라고 가정해보겠습니다. 당첨 번호 6개가 31, 10, 45, 1, 6, 19라면, 당첨 가능한 최고 순위와 최저 순위의 한 예는 아래와 같습니다.

예시

입출력 예

당첨 번호		31	10		45	1	6		19			결과
최고 순위 번호	31	0→10	44	1	0→6		25		4개 번호 일치, 3등
최저 순위 번호	31	0→11	44	1	0→7		25		2개 번호 일치, 5등

내가 작성한 solution.js

function solution(lottos, win_nums) {
    var answer = [];
    let unknown = 0;
    let rank = {0: 6, 1: 6, 2: 5, 3: 4, 4: 3, 5: 2, 6: 1}
    let matched = lottos.filter(item=>{
        if(item === 0) unknown+=1; 
        return win_nums.includes(item);
    })
    let max = rank[matched.length+unknown] >= 6 ? 6 : rank[matched.length+unknown];
    let min = (rank[matched.length+unknown] + unknown) >= 6 ? 6 : rank[matched.length+unknown] + unknown;
    
    return answer = [max, min];
}

ㅋㅋㅋㅋㅋ진짜.. 뭐지 코드가 좀 더러운 것 같다...
근데 이게 되네..? 싶어서 약간 웃기고 신기했던....
일단은 lottos를 filter로 돌려서 item이 0일 경우에는 unknown 변수의 값을 1씩 올려주게 하고, item이 win_nums에 포함되어 있을 경우에는 배열에 저장되도록 했다.
그래서 예상 가능한 최고 순위 번호는 일치하는 숫자 length에 알아볼 수 없는 수(unknown변수)의 length를 더해서 구했고, 최저 순위는 일치하는 숫자의 순위에 알아볼 수 없는 수 만큼 더해서 등수를 낮추어 구했다.

몇개가 일치할 때 몇등인지 출력하는 방법을 if문을 돌려서 다 써야하나 아니면 삼항연산자를 계속 이어붙여서 써야하나 하고 고민을 하다가 그냥 rank라는 오브젝트를 만들어서 key값에는 일치하는 숫자 갯수를, value값에는 그 key값에 따른 등수를 미리 작성해두고 찾도록 만들었다...ㅋㅋㅋㅋ

이게 되니까 좀 웃기기도 하고 이렇게도 풀면 풀 수는 있구나 싶었다.

let rank = [6, 6, 5, 4, 3, 2, 1]

다른 사람의 풀이를 보고 생각해보니 rank를 객체로 생서해서 굳이 key와 value값을 나누지 않아도 되는구나 싶었다. 위에 배열처럼 수정해놓고 매치되는 갯수가 0개라면 rank[0] 값을 가져오고, 매치되는 갯수가 2개라면 rank[2] 값을 가져오면 되는거였네..? 정말 똑똑한 사람들..




2. 문자열 내림차순으로 배열하기

문자열 s에 나타나는 문자를 큰것부터 작은 순으로 정렬해 새로운 문자열을 리턴하는 함수, solution을 완성해주세요.
s는 영문 대소문자로만 구성되어 있으며, 대문자는 소문자보다 작은 것으로 간주합니다.

예시

입출력 예

s			return
"Zbcdefg"	"gfedcbZ"

내가 작성한 solution.js

function solution(s) {
    var answer = '';
    let uppercase = [];
    let lowercase = [];
    for(let i=0; i<s.length; i++){
        if(s[i] === s[i].toLowerCase()) lowercase.push(s[i]);
        else uppercase.push(s[i]);
    }
    return answer = lowercase.sort().reverse().join('') + uppercase.sort().reverse().join('')
}

이 문제는 어제 최소 직사각형 사이즈 구하기에서 활용했던 방법과 같은 방식으로 풀면 될 것 같아서 비슷하게 적용해보니 금방 해결됐다.
소문자와 대문자인 문자들끼리 각 배열에 모은다음에, sort()와 reverse()를 반복해서 글자 순서가 높은것부터 나오도록했고 소문자 배열을 앞에, 대문자 배열을 뒤로 합쳐 값을 리턴하였다.




3. 숫자 문자열과 영단어

네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다.

다음은 숫자의 일부 자릿수를 영단어로 바꾸는 예시입니다.

  • 1478 → "one4seveneight"
  • 234567 → "23four5six7"
  • 10203 → "1zerotwozero3"

이렇게 숫자의 일부 자릿수가 영단어로 바뀌어졌거나, 혹은 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어집니다. s가 의미하는 원래 숫자를 return 하도록 solution 함수를 완성해주세요.

  • 1 ≤ s의 길이 ≤ 50
  • s가 "zero" 또는 "0"으로 시작하는 경우는 주어지지 않습니다.
  • return 값이 1 이상 2,000,000,000 이하의 정수가 되는 올바른 입력만 s로 주어집니다.

예시

입출력 예

s						result
"one4seveneight"		1478
"23four5six7"			234567
"2three45sixseven"		234567
"123"					123

내가 작성한 solution.js

function transferLetters(array, words, word){
    let idx = array.join('').indexOf(word);
    let lth = word.length;
    let num = words.indexOf(word);
    array.splice(idx, lth, num); 
}

function solution(s) {
    var answer = 0;
    let words = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
    
    let sArr = s.split('');
    for(let i=0; i<words.length; i++){
        while(sArr.join('').indexOf(words[i]) > -1){
            transferLetters(sArr, words, words[i]);
        }
    }
    return answer = sArr.join('')/1;
}

이 문제는.. 우선 숫자들의 텍스트 형태를 미리 배열 안에 넣어두고 하나씩 비교를 하는 방법 아니면 생각이 안나서 우선 words 배열을 만들었다.
그리고나서 words 배열을 for문으로 돌려가면서 입력된 텍스트에 words안의 요소가 포함되는지를 indexOf로 체크를 했다. words 안의 요소가 포함돌 경우 해당 index가 반환될 것이고, 포함되지 않을 경우 -1 이 나올 것이기 때문에 -1보다 큰 수가 리턴될 경우에만 텍스트를 숫자로 변환시키는 transferLetters 함수를 작동시키도록 while 조건문을 만들었다.

transferLetters 함수 안에서는 splice 를 이용해 기존 텍스트를 삭제하고 숫자로 대체시키도록 했다.

while문을 쓴 이유는 처음에 while문 없이 테스트를 해봤더니 'nine13348three02nine' 이런식으로 같은 텍스트가 두 번 이상 들어있을 경우, 앞에 있는 텍스트의 index만 인식해서 뒤에 있는 텍스트는 처리하지 않고 반환하길래.. while문을 돌려서 텍스트가 모두 제거되고 숫자만 남을때까지 변환 작업을 진행하도록 하기 위해 추가했다.

진짜.. 갈수록 문제가 복잡해지고 푸는 시간도 길어지는 것 같다. 풀어내면 그나마 다행이고 못풀어서 뒤로 미루고 넘어가는 문제가 수두룩...
이거는 그래도 혼자 해내서 좀 뿌듯하다...ㅠㅠ

다른 사람의 풀이

function solution(s) {
    let numbers = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];
    var answer = s;

    for(let i=0; i< numbers.length; i++) {
        let arr = answer.split(numbers[i]);
        answer = arr.join(i);
    }

    return Number(answer);
}

이사람은 진짜 천재인 것 같다.
전에도 split의 기발한 사용법을 봤었는데, 그 새 까먹고 있다가 이 사람의 풀이를 보고 다시 split의 엄청난 활용법을 실감했다. 입력된 텍스트 안에 글자가 있을 경우 그 글자를 기준으로 split을 하고, 그걸 다시 합칠 때 그 글자의 숫자(numbers안에서 그 글자가 포함된 index 값)을 넣어서 합쳐준 방법..
진짜 존경합니다...ㅠㅠ




0개의 댓글