728x90

https://programmers.co.kr/learn/courses/30/lessons/67256

 

코딩테스트 연습 - 키패드 누르기

[1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5] "right" "LRLLLRLLRRL" [7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2] "left" "LRLLRRLLLRR" [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] "right" "LLRLLRLLRL"

programmers.co.kr

 

def solution(numbers, hand):
    answer = ''
    left_finger = 10 # 왼손 처음 * 위치
    right_finger = 12 # 오른손 처음 #위치, 0은 11로 변경하기
    
    for n in numbers:
        if n in [1,4,7]: # 왼손 영역
            answer += 'L'
            left_finger = n
        elif n in [3,6,9]: # 오른손 영역
            answer += 'R'
            right_finger = n
            
        else: # 2 5 8 0 일 때
            if n == 0: # 0은 11로
                n = 11
            
            # 왼손과 오른손과 눌러야 할 n 거리를 각각 구해준다.
            left_dis = abs(n-left_finger)
            right_dis = abs(n-right_finger)
            left_dis = left_dis//3 + left_dis%3
            right_dis = right_dis//3 + right_dis%3
            # print("l",left_dis)
            # print("r",right_dis)
            if left_dis == right_dis: # 눌러야 할 거리가 왼손 오른손이 같으면 손잡이대로
                if hand == "right": # 오른손 잡이는 오른손
                    answer += 'R'
                    right_finger = n
                if hand == "left": # 왼손 잡이는 왼손
                    answer += 'L'
                    left_finger = n

            elif left_dis < right_dis: # 왼손과 거리가 더 가까우면 왼손
                answer += 'L'
                left_finger = n
            else: # 오른손이 더 가까우면 오른손
                answer += 'R'
                right_finger = n

    return answer

풀이 1

2, 5, 8, 0 일 때 거리를 구하는 것에서 쫌 헷갈렸다.

처음에 abs(현재 손가락//3 -눌러야 할 손가락//3) + abs(현재 손가락%3 -눌러야 할 손가락%3) 이렇게 풀었더니 틀려서 규칙을 다시 찾았다.

 

abs(현재 손가락-눌러야 할 손가락)를 먼저 구해주고

이 값에서 3으로 나눈 값과 3으로 나눈 나머지를 더해줘서 비교해야 하는 것이었다.


def solution(numbers, hand):
    answer = ''
    left_finger = '*' # 왼손 처음 * 위치
    right_finger = '#' # 오른손 처음 #위치
    phone_num = {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)}

    for n in numbers:
        if n in [1,4,7]: # 왼손 영역
            answer += 'L'
            left_finger = n
        elif n in [3,6,9]: # 오른손 영역
            answer += 'R'
            right_finger = n

        else: # 2 5 8 0 일 때
            # 왼손과 오른손과 눌러야 할 n 거리를 각각 구해준다.
            cur = phone_num[n]
            left_cur = phone_num[left_finger]
            right_cur = phone_num[right_finger]
            left_dis = abs(cur[0]-left_cur[0]) + abs(cur[1]-left_cur[1])
            right_dis = abs(cur[0]-right_cur[0]) +  abs(cur[1]-right_cur[1])

            if left_dis == right_dis: # 눌러야 할 거리가 왼손 오른손이 같으면 손잡이대로
                if hand == "right": # 오른손 잡이는 오른손
                    answer += 'R'
                    right_finger = n
                if hand == "left": # 왼손 잡이는 왼손
                    answer += 'L'
                    left_finger = n

            elif left_dis < right_dis: # 왼손과 거리가 더 가까우면 왼손
                answer += 'L'
                left_finger = n
            else: # 오른손이 더 가까우면 오른손
                answer += 'R'
                right_finger = n

    return answer

풀이 2

핸드폰의 버튼의 좌표를 정해서 딕셔너리로 관리해줬다.

더 직관적이고 깔끔한 것 같다.

728x90

https://programmers.co.kr/learn/courses/30/lessons/72410

출처 : 프로그래머스

 

코딩테스트 연습 - 신규 아이디 추천

카카오에 입사한 신입 개발자 네오는 "카카오계정개발팀"에 배치되어, 카카오 서비스에 가입하는 유저들의 아이디를 생성하는 업무를 담당하게 되었습니다. "네오"에게 주어진 첫 업무는 새로

programmers.co.kr

def solution(new_id):
    answer = ''
    # 1단계 모든 대문자를 소문자로
    new_id = new_id.lower()
    id_must = ['-','_','.']

    # 2단계 알파벳 소문자, 숫자, 필요한 기호 빼고 삭제
    for i in new_id:
        if i in id_must or i.isalpha() or i.isdigit():
            answer += i

    # 3단계 연속된 . 하나의 .로
    cnt = 0
    for i in answer:
        if i == id_must[2]:
            cnt += 1
            if cnt == 2:
                answer = answer.replace("..", ".")
                cnt = 0

    # 4단계 .가 처음이나 마지막이면 제거
    if answer[0] == id_must[2]: # 처음
        if len(answer)>1: # 지울게 있어야 지움
            answer = answer[1:]
        else:
            answer = '.'
            
    if answer[-1] == id_must[2]: # 마지막
        answer = answer[:-1]

    # 5단계 빈 문자열이라면 a삽입
    if answer == "":
        answer += 'a'

    # 6단계 아이디 길이가 16자리 이상이면, 첫 15개 제외한 나머지 문자 제거
    if len(answer) >= 16:
        answer = answer.replace(answer[15:],"")
        if answer[-1] == id_must[2]: # 제거 후 마지막에 .이 있다면 제거
            answer = answer[:-1]

    # 7단계 아이디 길이가 2자 이하면 마지막 문자를 길이가 3될 떄까지 반복
    while len(answer) < 3:
        answer += answer[-1]
    # print(answer)
    return answer

풀이

문자열 단계별 구현만 해주면 된다.

 

참고로 3단계는 이렇게 while 문으로도 가능하다.

while '..' in answer:
        answer = answer.replace('..', '.')

정규식으로 푸는 방법도 존재한다.

 

728x90

https://programmers.co.kr/learn/courses/30/lessons/81301

출처 : 프로그래머스

 

코딩테스트 연습 - 숫자 문자열과 영단어

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

programmers.co.kr

def solution(s):
    word = ['zero','one','two','three','four','five','six','seven','eight','nine']
    answer = ""
    alp = ""
    for i in s:
        if i.isdigit(): # 숫자인지
            answer += i
        else:
            alp += i
            if alp in word:
                answer += str(word.index(alp))
                alp = ""

    return int(answer)

풀이 1

숫자면 그냥 답에 추가해준다.

숫자가 아니라면 영문자 문자열에 넣다가 word에 저장해둔 값과 같은 값이 나온다면 word의 인덱스를 답에 넣어주고 영문자 리셋 ""한다.


def solution(s):
    words = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']

    for i in range(len(words)):
        s = s.replace(words[i], str(i))

    return int(s)

풀이 2

이건 다른 사람들 풀이이다..

replace를 썼다..

ㅠㅠ 대단한 사람들..

 


2021 카카오 채용연계형 인턴쉽 코딩테스트 문제다. 

728x90

출처 : 프로그래머스

 

https://programmers.co.kr/learn/courses/30/lessons/77484

 

코딩테스트 연습 - 로또의 최고 순위와 최저 순위

로또 6/45(이하 '로또'로 표기)는 1부터 45까지의 숫자 중 6개를 찍어서 맞히는 대표적인 복권입니다. 아래는 로또의 순위를 정하는 방식입니다. 1 순위 당첨 내용 1 6개 번호가 모두 일치 2 5개 번호

programmers.co.kr

def solution(lottos, win_nums):
    ranking = [6, 6, 5, 4, 3, 2, 1] # 순위가 인덱스인 일치하는 개수 배열
    cnt = 0 # 당첨 개수
    for i in lottos:
        if i in win_nums:
            cnt += 1
    count0 = lottos.count(0) # 0 의 개수

    return [ranking[cnt+count0], ranking[cnt]]

풀이1

로또번호와 일치하는 개수 배열 ranking  : 순위를 인덱스로 한다.

 

def solution(lottos, win_nums):
    rank = {
        0: 6,
        1: 6,
        2: 5,
        3: 4,
        4: 3,
        5: 2,
        6: 1
    }
    return [ rank[len(set(lottos) & set(win_nums)) + lottos.count(0)], rank[len(set(lottos) & set(win_nums))]]

풀이2

딕셔너리를 활용한다.

두 배열의 공통값을 빠르게 구하는 방법

set(list1) & set(list2)

728x90

출처: 프로그래머스

https://programmers.co.kr/learn/courses/30/lessons/92334

 

 

코딩테스트 연습 - 신고 결과 받기

문제 설명 신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다. 각 유저는 한 번에 한 명의

programmers.co.kr

def solution(id_list, report, k):
    answer = [0] * len(id_list)
    cnt = {id:0 for id in id_list} # id 별 신고된 횟수
    d = {id:[] for id in id_list} # 이용자 id 가 신고한 id들 딕셔너리

    for repo in set(report):
        rep = repo.split(' ') # 이용자id와 신고한 id 분리
        d[rep[0]].append(rep[1]) # 딕셔너리에서 이용자 id 키에 신고한 id들 추가
        cnt[rep[1]] += 1 # 신고횟수

    # print(d)
    for key,values in d.items():
        for val in values:
            if cnt[val] >= k: # 신고횟수가 k번 이상이면
                answer[id_list.index(key)] += 1
    # print(answer)
    return answer

풀이 

딕셔너리를 사용해 풀이했다.

문제 풀이에 필요한 딕셔너리와 답 배열이다.

이용자와 신고한 id가 같아서 헷갈리기에 정리를 잘 하고 코딩을 하자.

 

  • d = { 이용자 id : [신고한 id들...]}
  • cnt = { 신고당한 id : 신고당한 횟수 }
  • answer = [ id_list 순서대로 k번 이상 신고당한 유저를 신고한 회원들에게 메일 보낸 횟수 +1 ]

 

  • 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
    • 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
    • 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.

이 조건에서 한 유저가 한 유저를 계속 신고하는 것은 1회로 처리하기에 set(report)를 해준다.

이는 테스트케이스2를 보고 이해하면 된다.

 

공백 기준으로 set(report)를 잘라주고 만들어둔 d 딕셔너리에 삽입한다.

또, cnt 딕셔너리에 신고당한 id 별 신고 횟수를 적는다.

모두 딕셔너리에 넣고, cnt 딕셔너리에서 k번 이상 신고당한 유저들을 신고한 유저인 d 딕셔너리의 key를

answer에서 메일 보낸 횟수 +=1 해준다. 

 


* 딕셔너리 작성

cnt = {id:0 for id in id_list} # id 별 신고된 횟수
d = {id:[] for id in id_list} # 이용자 id 가 신고한 id들 딕셔너리

말이 쫌 길긴 하지만, 충분히 풀 수 있다.

카카오 2022 블라인드 코딩테스트 채용 문제라고 한다. 

728x90

출처 : 프로그래머스

https://programmers.co.kr/learn/courses/30/lessons/42626

 

코딩테스트 연습 - 더 맵게

매운 것을 좋아하는 Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들고 싶습니다. 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 Leo는 스코빌 지수가 가장 낮은 두 개의 음식을 아래와 같

programmers.co.kr

#include <string>
#include <vector>
#include <queue>
using namespace std;

int solution(vector<int> sco, int K) {
    int answer = 0;
    //우선순위큐 minheap생성
    priority_queue<int, vector<int>, greater<int>> pq(sco.begin(), sco.end());
    
    while(pq.size()>1 && pq.top()<K){
        //큐에 음식 2개이상있고, 가장 작은 스코빌 지수가 k보다 작을때
        int tmp1 = pq.top();
        pq.pop();
        int tmp2 = pq.top();
        pq.pop();
        int tmp3 = (tmp1+ (tmp2*2));
        pq.push(tmp3);
        answer ++; // 섞어주기
    }
    if (pq.top()>=K)
        return answer;
    else
        return -1;
}

 

 

1. 힙에 음식 넣고 오름차순 정렬한다.

2. 가장 작은 두 음식을 뽑고, 규칙에 맞게 섞는다. 섞은 음식을 다시 넣고 정렬한다.

3. 음식이 2개 이상 있고, 가장 작은 음식이 k보다 작을 때 계속 진행한다.

 

이는 우선순위 큐를 이용해 풀었다.

우선순위 큐를 이용하면 알아서 정렬된다.

 

곧... 12시 지났으니까 오늘 보는 코테만 끝나면 다시 파이썬으로 코테 준비하련다... c++ 좋은데 파이썬으로 계속 준비했어서 헷갈린다 ㅡㅡ

 


c++에서의 우선순위큐

priority_queue<int, vector<int>, greater<int>> pq; //minheap

priority_queue<int> pq; //maxheap

 

 

728x90

https://programmers.co.kr/learn/courses/30/lessons/43163

출처: 프로그래머스

 

코딩테스트 연습 - 단어 변환

두 개의 단어 begin, target과 단어의 집합 words가 있습니다. 아래와 같은 규칙을 이용하여 begin에서 target으로 변환하는 가장 짧은 변환 과정을 찾으려고 합니다. 1. 한 번에 한 개의 알파벳만 바꿀 수

programmers.co.kr

#include <string>
#include <vector>
#include <algorithm>
using namespace std;

int answer = 50;
bool visited[50]; //방문words

//begin과 한 글자만 다른 words 찾는 함수
bool oneDiff(string a, string b){
    int cnt_diff = 0;
    for(int i=0; i<b.size(); i++){
        if(a[i]!=b[i]){
            cnt_diff ++;
        }
    }
    if(cnt_diff == 1) //하나만 다르면
        return true;
    else
        return false;
}

void dfs(string begin, string target, vector<string> words, int idx){
   
    if(begin == target){ //종료조건
        answer = min(idx, answer);
        return; //종료
    }
    
    for(int i=0; i<words.size(); i++){
        //한글자만 다르고 아직 방문하지 않았으면
        if(oneDiff(begin, words[i]) && !visited[i]){
            visited[i] = true;
            dfs(words[i], target, words, idx+1);
            visited[i] = false; //dfs종료 후 돌아오면, 백트래킹
        }
    }
    return;
}

int solution(string begin, string target, vector<string> words) {

    dfs(begin, target, words,0);
    if(answer == 50){ //변환할 수 없으면 0
        answer = 0;
    }
    return answer;
}

최대 words의 길이가 50이니까 answer도 50, visited크기도 50으로 맞춘다.

이 말은 최대로 50번 변환할 수 있다는 것이다.

우리는 최단 횟수를 구해야 하기에 횟수 0부터 시작해서 50이랑 비교해서 최솟값을 구해낸다.

 

dfs로 풀이했다.

begin과 words에 있는 단어를 비교했을 때, 한 글자만 다른 단어만 방문 가능하다.

한 글자만 다른 것을 판별하는 함수를 따로 oneDiff()로 만들었다.

 

아직 방문하지 않았고 한 글자만 다른 단어만 방문 표시하고 다음 단계인 dfs 진행한다.

dfs가 종료되었을 때, 다시 백트래킹으로 visited [i]= true 했던 것을 visited[i] = false 처리해준다.


백트래킹...............

연습하자

+ Recent posts