coding 연습/프로그래머스

프로그래머스 level1 문제들(정답률50%~60%)

blackbearwow 2023. 9. 24. 18:10

- [1차] 다트 게임

숫자가 한자리가 아닌것을 처리하는것. 특수문자에서 nums 길이가 1인것을 고려해야한다.

def solution(dartResult):
    import re
    nums = []
    before = '' #한자리 숫자가 아닌것을 처리
    for x in dartResult:
        #숫자라면 nums에 저장
        if re.match('[0-9]', x):
            if before == 'num':
                nums[len(nums)-1] = nums[len(nums)-1] * 10 + int(x)
            else:
                nums.append(int(x))
            before = 'num'
        #S D T 라면 마지막 nums에 배수.
        elif re.match('[SDT]', x):
            before = 'pow'
            if x == 'D':
                nums[len(nums)-1] **= 2
            elif x == 'T':
                nums[len(nums)-1] **= 3
        #* #이라면 특수
        elif re.match('[*#]', x):
            before = "special"
            if x == '*':
                nums[len(nums)-1] *= 2
                if len(nums)-2 >= 0:
                    nums[len(nums)-2] *= 2
            elif x == '#':
                nums[len(nums)-1] *= -1
    return sum(nums)

- 로또의 최고 순위와 최저 순위

이제 슬슬 감이 잡히는것 같기도??

문제에서 무엇을 요구하는지 정확히 분석해야 한다.

로또의 최고 등수와 최저 등수를 구하는데, 0이라는 값이 사용되었고 이것을 어떻게 잘 정의하는것이 중요하다.

lottos와 win_nums를 비교해서 나올 수 있는 결과는 correct(맞은 개수), wrong(틀린 개수), zero(맞을수도 틀릴수도 있는 개수)를 알 수 있다. 그러면 여기서 맞은 개수 최대와 최소는 어떻게 구할까? 맞은 개수 최대는 correct + zero이고 최소 개수는 correct이다. wrong은 필요하지 않은 변수이다. 

def solution(lottos, win_nums):
    # step1 correct, wrong, zero 개수 구하기
    correct = 0
    wrong = 0
    zero = 0
    for x in lottos:
        # 0이라면 zero개수 증가
        if x == 0:
            zero += 1
        # win_nums에 해당되면 correct개수 증가
        elif x in win_nums:
            correct += 1
        # win_nums에 해당되지 않으면 wrong개수 증가
        else:
            wrong += 1
    answer = [ranking(correct+zero), ranking(correct)]
    return answer

def ranking(correctNum):
    ranking = 7-correctNum
    if ranking == 7:
        ranking = 6
    return ranking

print(solution([44, 1, 0, 0, 31, 25], [31, 10, 45, 1, 6, 19]))
print(solution([0, 0, 0, 0, 0, 0], [38, 19, 20, 40, 15, 25]))

- 체육복

분명히 테스트케이스로 코드 실행 할 때는 문제가 없었지만 제출 후 채점하기에서 문제가 무더기로 발생했다.

첫번째 문제는 lost와 reserve가 정렬되어 주어지지 않을 수 있다는것이었다. 이것은 sort()메소드를 사용해서 해결.

두번째 문제는 여벌 체육복을 가진 학생이 도난당했을 경우의 처리였다. 테스트케이스에 충분한 예제가 나와있지 않아서 질문하기 포럼을 살펴보니 여벌 체육복이 있지만 도난당한경우에는 lost와 reserve에서 제거하여 연산해야 한다는 것이다. 그런데 여기서 아무생각없이 그냥 for문을 사용하여 코드를 짠다면 1번과 7번이 오류가 난다.

    for i in reserve:
        if i in lost:
            lost.remove(i)
            reserve.remove(i)

이렇게 짜면 틀린것이다. 왜냐? 중간에 print해보면 알겠지만 [1, 2, 3] [2, 3]을 매개변수로 전달했을 때 1, 2만 검사하고 for문을 빠져나간다. 2를 검사하면 remove로 지워지고 3이 검사되야겠지만, reserve가 [3]이 되고 길이가 1이되므로 반복문을 빠져나가는것 같다. https://stackoverflow.com/questions/25903919/indexerror-list-index-out-of-range-when-removing-duplicates 그러면 해결 방법은 1. while문을 사용해 같은값은 제거하고 i -= 1, 반복될때마다 len값을 검사해 루프를 빠져나가는 방법과 2. 중복되는 것들만 리스트로 저장해두었다가 나중에 따로 제거하는것이다. 후자의 방법으로 진행했다. 

def solution(n, lost, reserve):
    lost.sort()
    reserve.sort()
    duplicated = []
    for x in lost:
        if x in reserve:
            duplicated.append(x)
    for x in duplicated:
        lost.remove(x)
        reserve.remove(x)
        
    answer = n - len(lost)
    for x in lost:
        if x-1 in reserve:
            reserve.remove(x-1)
            answer += 1
        elif x+1 in reserve:
            reserve.remove(x+1)
            answer += 1
    return answer

print(solution(5, [1, 2, 3, 4], [2, 3, 4]))
print(solution(5, [2, 4], [1, 3, 5]))
print(solution(5, [2, 4], [3]))
print(solution(3, [3], [1]))

- 완주하지 못한 선수

그냥 쉬운 문제인지 알았다. 그런데 이게 웬걸? 효율성 테스트에서 0점이다.

s.count(x)를 사용했다가 시간초과로 실패했다. 

다른사람 질문의 힌트를 봤더니 딕션어리를 이용해서 했다고 해서 dictionary를 사용해 풀었다.

def solution(participant, completion):
    runnerDict = {}
    for x in participant:
        if x not in runnerDict:
            runnerDict[x] = 1
        else:
            runnerDict[x] += 1
    for x in completion:
        runnerDict[x] -= 1
        if runnerDict[x] == 0:
            del runnerDict[x]
    return list(runnerDict.keys())[0]

print(solution(["leo", "kiki", "eden"], ["eden", "kiki"]))
print(solution(["mislav", "stanko", "mislav", "ana"], ["stanko", "ana", "mislav"]))

- 크레인 인형뽑기 게임

처음 문제를 제출했을 때는 basket을 모두 구한 후 deleteDuplicatedNumber함수를 재귀적으로 실행하여 중복된것을 구했다. 그런데 그런 방법 말고, basket에 숫자가 추가될 때마다 중복된것이 있는지 확인한다면 재귀함수를 사용하지 않아도 된다.

def solution(board, moves):
    answer = 0
    basket = []
    for move in moves:
        for y in board:
            if y[move -1] != 0:
                basket.append(y[move -1])
                y[move -1] = 0

                if len(basket) > 1:
                    if basket[-1] == basket[-2]:
                        basket.pop()
                        basket.pop()
                        answer += 2
                break
    return answer
    
print("answer:", solution([[0,0,0,0,0],[0,0,1,0,3],[0,2,5,0,1],[4,2,4,4,2],[3,5,1,3,1]], [1,5,3,5,1,2,1,4]))

- [카카오 인턴] 키패드 누르기

문제분석:

현재 왼손 오른손이 어디에 있는지, 주어진 숫자와 왼손과 오른손이 얼마만큼의 거리가 있는지, 왼손키패드와 오른손키패드에 해당하는 번호 리스트를 저장하여야한다.

왼손키패드 숫자라면 왼손으로 누르고

오른손키패드 숫자라면 오른손으로 누르고

가운데 숫자라면 왼손과 오른손의 거리를 각각 구한다. (거리는 행렬을 이용해 행의 거리 차와 열의 거리 차를 합해 구했다)

구한 거리가 같다면 손잡이를 구분해 키패드를 누르고

구한 거리가 다르다면 가까운 거리의 손으로 키패드를 누른다.

def solution(numbers, hand):
    answer = ''

    lefthand = '*'
    righthand = '#'
    # 어느 위치에 있는지 저장하는 변수
    leftDistance = 0
    rightDistance = 0
    # 가운데 숫자와 얼마나 거리가 떨어져있는지 저장하는 변수
    leftnumbers = [1, 4, 7]
    rightnumbers = [3, 6, 9]
    # 키패드 번호 저장 리스트

    for x in numbers:
        # x가 leftnumbers라면 왼손으로 누르기
        if x in leftnumbers:
            lefthand = x
            answer += "L"
        # x가 rightnumbers라면 오른손으로 누르기
        elif x in rightnumbers:
            righthand = x
            answer += "R"
        # 가운데 숫자라면 해당 숫자와 왼손과 오른손의 거리를 구함
        else:
            leftDistance = keypadDistance(x, lefthand)
            rightDistance = keypadDistance(x, righthand)
            # 거리가 같다면 손잡이 손으로 번호를 누른다
            if leftDistance == rightDistance:
                if hand == "left":
                    lefthand = x
                    answer += "L"
                else:
                    righthand = x
                    answer += "R"
            # 거리가 다르다면 가까운 손으로 누른다.
            else:
                if leftDistance < rightDistance:
                    lefthand = x
                    answer += "L"
                else:
                    righthand = x
                    answer += "R"

    return answer

def keypadDistance(num1, num2):
    rowColumn ={
        1 : [0,0],
        2 : [0,1],
        3 : [0,2],
        4 : [1,0],
        5 : [1,1],
        6 : [1,2],
        7 : [2,0],
        8 : [2,1],
        9 : [2,2],
        '*' : [3,0],
        0 : [3,1],
        '#' : [3,2]
    }
    num1rowColumn = rowColumn[num1]
    num2rowColumn = rowColumn[num2]
    return abs(num1rowColumn[0] - num2rowColumn[0]) + abs(num1rowColumn[1] - num2rowColumn[1])

print(solution([1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5], "right"))
print(solution([7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2], "left"))
print(solution([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], "right"))

- 옹알이 (2)

function solution(babbling) {
    let answer = 0;
    let before, after;
    for(let babble of babbling) {
        babble = babble.replaceAll('aya', 0);
        babble = babble.replaceAll('ye', 1);
        babble = babble.replaceAll('woo', 2);
        babble = babble.replaceAll('ma', 3);
        before = babble[0];
        if(/[a-zA-Z]/.test(babble[0])) 
            continue;
        let flag = false;
        for(let i=1; i<babble.length; i++) {
            after = babble[i];
            if(/[a-zA-Z]/.test(babble[i]) || before == after) {
                flag = true;
                continue;
            }
            before = after;
        }
        if(flag == false)
            answer += 1;
    }
    return answer;
}

- 숫자 짝꿍

function solution(X, Y) {
    var answer = '';
    let xInt = {0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0};
    let yInt = {0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0};
    let overlapInt = {};
    for(const x of X) {
        xInt[x]+=1;
    }
    for(const y of Y) {
        yInt[y]+=1;
    }
    for(let i=9; i>=0; i--) {
        overlapInt[i] = Math.min(xInt[i], yInt[i]);
        if(overlapInt[i] != 0)
            answer += i.toString().repeat(overlapInt[i]);
    }
    if(answer == '')
        answer = '-1';
    else if(Number(answer)==0)
        answer = '0';
    return answer;
}

- 문자열 나누기

function solution(s) {
    let answer = 0;
    let first;
    let same = 0;
    let notSame = 0;
    for(let i=0; i<s.length; i++) {
        if(first === undefined)
            first = s[i];
        if(first == s[i])
            same++;
        else
            notSame++;
        if(same==notSame && same != 0) {
            answer++;
            same=0; notSame=0;
            first = undefined;
        }
        else if(i == s.length -1) {
            answer++;
        }
    }
    return answer;
}

- 대충 만든 자판

function solution(keymap, targets) {
    var answer = [];
    let minPress = {};
    //알파벳마다 최소로 눌러야 하는 값을 알아낸다.
    for(const map of keymap) {
        for(let i=0; i<map.length; i++) {
            if(minPress[map[i]] === undefined)
                minPress[map[i]] = i+1;
            else
                minPress[map[i]] = Math.min(minPress[map[i]], i+1);
        }
    }
    //target마다 하나라도 undefined라면 -1이고, 아니라면 값을 모두 더한다.
    for(const target of targets) {
        if(target.split('').some((val)=>minPress[val]===undefined))
            answer.push(-1);
        else
            answer.push(target.split('').map((val)=>minPress[val]).reduce((total, val)=>total+val));
    }
    return answer;
}

- 둘만의 암호

function solution(s, skip, index) {
    let answer = '';
    let alphabet = "abcdefghijklmnopqrstuvwxyz";
    for(const x of skip) {
        alphabet = alphabet.replace(x, '');
    }
    alphabet = alphabet.split('');
    for(const c of s) {
        let idx = alphabet.findIndex((val)=>val === c);
        idx = (idx + index) % alphabet.length;
        answer += alphabet[idx];
    }
    return answer;
}

- [PCCE 기출문제] 9번 / 이웃한 칸

def solution(board, h, w):
    answer = 0
    dh = [0, 1, -1, 0]
    dw = [1, 0, 0, -1]
    for i in range(4):
        nh = h + dh[i]
        nw = w + dw[i]
        if 0 <= nh and nh <len(board) and 0 <= nw and nw < len(board[0]):
            if board[h][w] == board[nh][nw]:
                answer+=1
    return answer

- [PCCE 기출문제] 10번 / 데이터 분석

def solution(data, ext, val_ext, sort_by):
    d = {"code":0, "date":1, "maximum":2, "remain":3}
    answer = list(filter(lambda x:x[d[ext]]<val_ext, data))
    answer.sort(key=lambda x:x[d[sort_by]])
    return answer