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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다.

  • 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
    • 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
    • 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.
  • k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다.
    • 유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송합니다.

다음은 전체 유저 목록이 ["muzi", "frodo", "apeach", "neo"]이고, k = 2(즉, 2번 이상 신고당하면 이용 정지)인 경우의 예시입니다.

유저 ID유저가 신고한 ID설명
"muzi" "frodo" "muzi"가 "frodo"를 신고했습니다.
"apeach" "frodo" "apeach"가 "frodo"를 신고했습니다.
"frodo" "neo" "frodo"가 "neo"를 신고했습니다.
"muzi" "neo" "muzi"가 "neo"를 신고했습니다.
"apeach" "muzi" "apeach"가 "muzi"를 신고했습니다.

각 유저별로 신고당한 횟수는 다음과 같습니다.

유저 ID신고당한 횟수
"muzi" 1
"frodo" 2
"apeach" 0
"neo" 2

위 예시에서는 2번 이상 신고당한 "frodo"와 "neo"의 게시판 이용이 정지됩니다. 이때, 각 유저별로 신고한 아이디와 정지된 아이디를 정리하면 다음과 같습니다.

유저 ID유저가 신고한 ID정지된 ID
"muzi" ["frodo", "neo"] ["frodo", "neo"]
"frodo" ["neo"] ["neo"]
"apeach" ["muzi", "frodo"] ["frodo"]
"neo" 없음 없음

따라서 "muzi"는 처리 결과 메일을 2회, "frodo"와 "apeach"는 각각 처리 결과 메일을 1회 받게 됩니다.

이용자의 ID가 담긴 문자열 배열 id_list, 각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.

 

제한사항

  • 2 ≤ id_list의 길이 ≤ 1,000
    • 1 ≤ id_list의 원소 길이 ≤ 10
    • id_list의 원소는 이용자의 id를 나타내는 문자열이며 알파벳 소문자로만 이루어져 있습니다.
    • id_list에는 같은 아이디가 중복해서 들어있지 않습니다.
  • 1 ≤ report의 길이 ≤ 200,000
    • 3 ≤ report의 원소 길이 ≤ 21
    • report의 원소는 "이용자id 신고한id"형태의 문자열입니다.
    • 예를 들어 "muzi frodo"의 경우 "muzi"가 "frodo"를 신고했다는 의미입니다.
    • id는 알파벳 소문자로만 이루어져 있습니다.
    • 이용자id와 신고한id는 공백(스페이스)하나로 구분되어 있습니다.
    • 자기 자신을 신고하는 경우는 없습니다.
  • 1 ≤ k ≤ 200, k는 자연수입니다.
  • return 하는 배열은 id_list에 담긴 id 순서대로 각 유저가 받은 결과 메일 수를 담으면 됩니다.
  • 2 ≤ id_list의 길이 ≤ 1,000
    • 1 ≤ id_list의 원소 길이 ≤ 10
    • id_list의 원소는 이용자의 id를 나타내는 문자열이며 알파벳 소문자로만 이루어져 있습니다.
    • id_list에는 같은 아이디가 중복해서 들어있지 않습니다.
  • 1 ≤ report의 길이 ≤ 200,000
    • 3 ≤ report의 원소 길이 ≤ 21
    • report의 원소는 "이용자id 신고한id"형태의 문자열입니다.
    • 예를 들어 "muzi frodo"의 경우 "muzi"가 "frodo"를 신고했다는 의미입니다.
    • id는 알파벳 소문자로만 이루어져 있습니다.
    • 이용자id와 신고한id는 공백(스페이스)하나로 구분되어 있습니다.
    • 자기 자신을 신고하는 경우는 없습니다.
  • 1 ≤ k ≤ 200, k는 자연수입니다.
  • return 하는 배열은 id_list에 담긴 id 순서대로 각 유저가 받은 결과 메일 수를 담으면 됩니다.

 

발상

신고 결과를 취합하고 -> 결과를 집계해서 정지여부를 판단하고 -> 신고한 사람들에게 피드백을 주는 문제이다.

1차 자료를 가공하고 가공된 자료를 활용하여 다시 2차 결과물을 만드는데, 약간 복잡했다.

1차원의 ID 리스트를 상관계수 표처럼 2차원을 확장하고, 확장한 y축을 신고결과를 누적하게 한 뒤, 취합하면 나중에 전체순회를 여러번 하지 않고 편하게 자료를 활용할 수 있을 것 같아서 2차원 배열로 구현하였다.

의사코드

1. 초기값 선언(2차원 배열)
2. 신고 결과 배열 마킹{
	1. 신고자 배열위치 확인(스트림 인덱스)
    2. 피신고자 배열위치 확인
    3. 보드에 마킹(0일 때만 1)
}
3. 신고 결과 취합 및 정지여부 판단
4. 정지대상과 신고자 체크 후 결과값 반환

 

코드

더보기
public int[] solution(String[] id_list, String[] report, int k) {

    /*
     * 처리결과 횟수를 배열로 받음
     * nxn 배열로 확대하고, 주어진 배열 그대로의 인덱스를 사용함
     * 신고한 결과를 나중에 스트림으로 필터링하고 리턴하면 됨
     * */
    int[] reportResult = new int[id_list.length];
    int[][] reportBoard = new int[id_list.length][id_list.length];
    for (String s : report) {
        String[] reportTicket = s.split(" ");
        int reporter = IntStream.range(0, id_list.length)
                .filter(f -> reportTicket[1].equals(id_list[f]))
                .findFirst()
                .orElse(-1);
        int reportee = IntStream.range(0, id_list.length)
                .filter(f -> reportTicket[0].equals(id_list[f]))
                .findFirst()
                .orElse(-1);
        reportBoard[reporter][reportee]=1;
    }
    for (int i = 0; i < id_list.length; i++) {
        for (int j = 0; j < id_list.length; j++) {
            reportResult[i] += (reportBoard[i][j] >= 1) ? 1 : 0;
        }
    }
    for (int[] ints : reportBoard) {
        for (int anInt : ints) {
            System.out.print(anInt + ", ");
        }
        System.out.println();
    }
    System.out.println("=================================");
    int[] answer = new int[id_list.length];
    for (int i = 0; i < reportBoard.length; i++) {
        if(Arrays.stream(reportBoard[i]).sum()>=k){
            for (int j = 0; j < reportBoard.length; j++) {
                answer[j] += reportBoard[i][j] >= 1 ? 1 : 0;
            }
        }
    }

    return answer;
}

 

개선

여러 과정을 거쳐서 자료를 가공해야 하고, 방법도 굉장히 많은 방법이 있어 보여서 고민하는데 시간이 많이 걸렸다.

하지만 가장 빠른 방법은 바로 구현할 수 있는 방법이고, 너무 많은 시간을 고민에 쓰지말고 어느정도 전략이 세워지면 구현을 해야 한다.

진행하다 보면 문제점이나 개선점이 보이게 되니 일단 구현해보는 것이 좋은 것 같다.

'IT > Algorithm' 카테고리의 다른 글

[programmers] 전화번호 목록  (0) 2022.08.18
[programmers] 기능 개발  (0) 2022.07.27
[programmers] 로또의 최고 순위와 최저 순위  (0) 2022.07.17
[programmers] [1차] 비밀지도  (0) 2022.07.17
[Algorithm] RSA 암호  (0) 2022.07.17

https://school.programmers.co.kr/learn/courses/30/lessons/17681

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

tresure map

네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.

  1. 지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 "공백"(" ") 또는 "벽"("#") 두 종류로 이루어져 있다.
  2. 전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 "지도 1"과 "지도 2"라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.
  3. "지도 1"과 "지도 2"는 각각 정수 배열로 암호화되어 있다.
  4. 암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.

네오가 프로도의 비상금을 손에 넣을 수 있도록, 비밀지도의 암호를 해독하는 작업을 도와줄 프로그램을 작성하라.

발상

주어진 수를 2진수로 변환한 뒤에 or 연산을 하여 0과 1을 주어진 조건에 맞게 변환하는 문제이다.

이진수변환을 하면서 자리수가 다른 부분이나 형변환 같은 이슈를 처리하는 부분이 핵심이었다.

의사코드

1. 주어진 배열 이진수 변환
2. 반복문{
	1. 변환된 이진수 비교
    	1. 둘 다 0이면 0
        2. 아니면 #
}
3. 완성된 배열 반환

 

개선

주어진 배열을 따로따로 이진수 변환하고, 자리수 맞추고, 그 뒤에 변환하느라 고생하였다.

처음에는 Integer클래스의 toBinaryString으로 문자열로 바꾸고, 다시 숫자 세서 String클래스로 포매팅하고, 거기서 다시 문자를 추출해서 비교하였는데 케이스가 많아지니까 타임아웃이 발생하였다.

최적화를 위해 고민하여서 통과하긴 하였는데, 다른 사람들의 풀이를 보니 처음에 주어진 숫자값을 따로 가공하지 않고 바로 비트연산을 통해 원하는 값을 얻어서 많은 절차를 생략하였다.

 

데이터는 모두 0과 1의 조합으로 되어있다는 사실을 잊지 말고 비트단위 연산도 항상 염두에 두도록 하자.

'IT > Algorithm' 카테고리의 다른 글

[programmers] 신고 결과 받기  (0) 2022.07.26
[programmers] 로또의 최고 순위와 최저 순위  (0) 2022.07.17
[Algorithm] RSA 암호  (0) 2022.07.17
[programmers] 시저암호  (0) 2022.07.14
[programmers] 이상한 문자 만들기  (0) 2022.07.13

 

 

https://school.programmers.co.kr/learn/courses/30/lessons/12926

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

ASCII

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.

제한 조건

  • 공백은 아무리 밀어도 공백입니다.
  • s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
  • s의 길이는 8000이하입니다.
  • n은 1 이상, 25이하인 자연수입니다.

발상

컴퓨터 문자의 기본인 아스키코드를 알고, String을 char로 변환하여 다룰 수 있는지 묻는 문제였다.

대소문자 순환을 하기 위한 로직이 필요하였고, 공백처리탈출, 문자열을 n만큼 더하는 로직이 필요하였다.

의사코드

1. 변수값 선언(스트링빌더, char배열)
2. char배열만큼 반복{
	1. 공백일 경우 스트링빌더에 공백 추가
    2. 대문자일경우 (65+((문자-65+n)%26))
    3. 소문자일 경우 (97+((문자-97+n)%26))
}
3. 스트링빌더를 스트링으로 변환 후 반환

 

개선

String의 char변환같은 기본자료형을 다루는 방법들은 직접 구현하는 것도 좋지만, 이미 구현된 라이브러리를 사용하는 것이 더 좋은 것 같다.

바퀴를 다시 만들지 말라는 말처럼, 배울때 한번쯤은 로직을 파악하기 위해 구현하는 것 외엔 이미 구현된 함수를 사용하고 절약한 시간으로 문제를 한번 더 파악하고, 다른 접근방법을 찾는 것이 더 효과적이라 생각한다.

'IT > Algorithm' 카테고리의 다른 글

[programmers] [1차] 비밀지도  (0) 2022.07.17
[Algorithm] RSA 암호  (0) 2022.07.17
[programmers] 이상한 문자 만들기  (0) 2022.07.13
[programmers] 예산  (0) 2022.07.12
[programmers] 최대공약수와 최소공배수  (0) 2022.07.11

https://school.programmers.co.kr/learn/courses/30/lessons/12930

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

text

문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 리턴하는 함수, solution을 완성하세요.

제한 사항
  • 문자열 전체의 짝/홀수 인덱스가 아니라, 단어(공백을 기준)별로 짝/홀수 인덱스를 판단해야합니다.
  • 첫 번째 글자는 0번째 인덱스로 보아 짝수번째 알파벳으로 처리해야 합니다.

발상

일반적인 문장을 공백으로 잘라내고, 가공하는 문제인 줄 알았다.

그런데 코드를 작성하고 테스트케이스를 돌려보니 문제가 명확하지 않아 답이 맞지 않았다.

실패한 테스트케이스를 프로그래머스에선 입출력 확인도 안되어 고민하다 시간만 날리다가 결국 다른 사람들의 사례를 검색하여 이슈를 확인하고 해결하였다.

 

의사코드

1. 문자열을 1글자씩 자르기
2. 잘라진 문자열 수만큼 반복{
	1. 내부 순환을 위한 카운트 설정, 공백이면 카운트 초기화
    2. 카운트가 짝수면 대문자, 홀수면 소문자 변환
}
3. 변환된 값 반환

 

개선

문제점은 하나 이상의 공백이라는 점, 그리고 출력값도 하나 이상의 공백이 그대로 들어가야 한다는 점과

제시문이 대문자도 나올 수 있다는 점을 예시에서 보여주지 않았다는 점이다.

그때문에 소문자로 된 공백 하나로 구분된 문장이 들어오겠구나 생각하였지만 실제로 테스트케이스를 돌리니 주어진 예제케이스 말고 대부분 실패하는 상황이 발생하였다.

 

알고리즘의 정의중 하나인 `입력' 부분에서 입력이 제대로 정의되지 않아서 발생한 문제이긴 하지만

현실에서 프로그램을 통해 해결하는 문제들 대부분이 제대로 정의되지 않았다는 점에서 생각할 거리를 주는 문제이다.

내가 문제를 쉽게 해결해서 안좋은 문제가 아니라, 나의 접근과 분석방법, 예외를 생각하는 케이스가 아직 부족하다는 점을 깨달을 수 있었던 문제였다.

https://ko.wikipedia.org/wiki/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98

 

'IT > Algorithm' 카테고리의 다른 글

[Algorithm] RSA 암호  (0) 2022.07.17
[programmers] 시저암호  (0) 2022.07.14
[programmers] 예산  (0) 2022.07.12
[programmers] 최대공약수와 최소공배수  (0) 2022.07.11
[programmers] 3진법 뒤집기  (0) 2022.07.10

https://school.programmers.co.kr/learn/courses/30/lessons/68935

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

budget

S사에서는 각 부서에 필요한 물품을 지원해 주기 위해 부서별로 물품을 구매하는데 필요한 금액을 조사했습니다. 그러나, 전체 예산이 정해져 있기 때문에 모든 부서의 물품을 구매해 줄 수는 없습니다. 그래서 최대한 많은 부서의 물품을 구매해 줄 수 있도록 하려고 합니다.

물품을 구매해 줄 때는 각 부서가 신청한 금액만큼을 모두 지원해 줘야 합니다. 예를 들어 1,000원을 신청한 부서에는 정확히 1,000원을 지원해야 하며, 1,000원보다 적은 금액을 지원해 줄 수는 없습니다.

부서별로 신청한 금액이 들어있는 배열 d와 예산 budget이 매개변수로 주어질 때, 최대 몇 개의 부서에 물품을 지원할 수 있는지 return 하도록 solution 함수를 완성해주세요.

제한사항

  • d는 부서별로 신청한 금액이 들어있는 배열이며, 길이(전체 부서의 개수)는 1 이상 100 이하입니다.
  • d의 각 원소는 부서별로 신청한 금액을 나타내며, 부서별 신청 금액은 1 이상 100,000 이하의 자연수입니다.
  • budget은 예산을 나타내며, 1 이상 10,000,000 이하의 자연수입니다.

발상

자료를 정렬하고, 주어진 조건에 맞게 가공하는 문제이다.

얼마나 최적화를 잘 하느가 포인트인 문제이다.

의사코드

1. 주어진 자료 정렬
2. 예산 체크{
	1. 작은 예산순으로 더함
    2. 예산초과인지 체크
}
3. 반환

 

개선

다른사람의 풀이를 확인해보니 중복되거나 생략할 수 있는 변수가 많이 있었다.

budget변수가 주어지는데 총 예산의 합을 sum으로 더해서 비교하였는데, budget에서 빼는 방법도 있었으며

반복문을 반복한 인덱스값이 결과값과 같은데, 따로 변수를 선언해서 체크를 했었다.

문제를 다 풀고 한번 더 점검,개선하는 절차를 거쳐야겠다.

 

https://school.programmers.co.kr/learn/courses/30/lessons/12940

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

두 수를 입력받아 두 수의 최대공약수와 최소공배수를 반환하는 함수, solution을 완성해 보세요. 배열의 맨 앞에 최대공약수, 그다음 최소공배수를 넣어 반환하면 됩니다. 예를 들어 두 수 3, 12의 최대공약수는 3, 최소공배수는 12이므로 solution(3, 12)는 [3, 12]를 반환해야 합니다.

제한 사항

  • 두 수는 1이상 1000000이하의 자연수입니다.

발상

주어진 두 수의 최대공약수와 최소공배수를 구하는 문제이다.

최대공약수는 유클리드 호제법이라는 널리 알려진 알고리즘이 존재하고, 최소공배수는 최대공약수를 이용하여 간단하게 구할 수 있다.

알고리즘 공부를 하다 보면 자주 볼 수 있는 문제이기 때문에 유클리드 호제법은 기억해 두는 것이 좋을 것 같다.

간단요약

public int gcd(int p, int q){
	//0으로 나눌 수 없음
	if(q==0) return 0;
    //재귀호출
    return gcd(q, p%q);
}

추가적인 설명과 이미지를 통한 이해는 위키피디아를 활용하면 좋을 것 같다.

https://ko.wikipedia.org/wiki/%EC%9C%A0%ED%81%B4%EB%A6%AC%EB%93%9C_%ED%98%B8%EC%A0%9C%EB%B2%95

 

유클리드 호제법 - 위키백과, 우리 모두의 백과사전

 

ko.wikipedia.org

의사코드

1. 최대공약수 알고리즘 구현
2. 최소공배수 알고리즘 구현
3. 인자를 사용하여 gcd, lcm 호출 후 결과배열 생성
4. 반환

 

개선

실무 개발할 때는 가독성이 더 중요하지만, 코딩테스트나 알고리즘 준비에서는 가독성이 조금 떨어지더라도 시간복잡도나 공간복잡도를 개선한 코드가 높은 점수를 받는다.

수학적인 테크닉들도 계속 숙달하도록 하자.

'IT > Algorithm' 카테고리의 다른 글

[programmers] 이상한 문자 만들기  (0) 2022.07.13
[programmers] 예산  (0) 2022.07.12
[programmers] 3진법 뒤집기  (0) 2022.07.10
[programmers] 크레인 인형뽑기 게임  (0) 2022.07.08
[programmers] 문자열 내 p와 y의 개수  (0) 2022.07.08
 

https://school.programmers.co.kr/learn/courses/30/lessons/68935

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

자연수 n이 매개변수로 주어집니다. n을 3진법 상에서 앞뒤로 뒤집은 후, 이를 다시 10진법으로 표현한 수를 return 하도록 solution 함수를 완성해주세요.


제한사항

  • n은 1 이상 100,000,000 이하인 자연수입니다.

발상

진법을 직접 구현하는 문제이다.

주어진 수를 3진법으로 변환하고, 역으로 만든 뒤 다시 10진법으로 변환하면 된다.

의사코드

1. 초기값 선언
2. 3진법 변환 반복{
	1. 컬랙션에 파라미터 n%3 추기
    2. n/=3
}
3. 10진법 변환 반복{
	1. 결과값 = 결과값 * 3 + 진법수
}
4. 결과값 반환

 

개선

개발 처음 배울 때 배우는 진법을 복습할 수 있는 문제였다.

https://school.programmers.co.kr/learn/courses/30/lessons/64061

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

게임개발자인 "죠르디"는 크레인 인형뽑기 기계를 모바일 게임으로 만들려고 합니다.
"죠르디"는 게임의 재미를 높이기 위해 화면 구성과 규칙을 다음과 같이 게임 로직에 반영하려고 합니다.

게임 화면은 "1 x 1" 크기의 칸들로 이루어진 "N x N" 크기의 정사각 격자이며 위쪽에는 크레인이 있고 오른쪽에는 바구니가 있습니다. (위 그림은 "5 x 5" 크기의 예시입니다). 각 격자 칸에는 다양한 인형이 들어 있으며 인형이 없는 칸은 빈칸입니다. 모든 인형은 "1 x 1" 크기의 격자 한 칸을 차지하며 격자의 가장 아래 칸부터 차곡차곡 쌓여 있습니다. 게임 사용자는 크레인을 좌우로 움직여서 멈춘 위치에서 가장 위에 있는 인형을 집어 올릴 수 있습니다. 집어 올린 인형은 바구니에 쌓이게 되는 데, 이때 바구니의 가장 아래 칸부터 인형이 순서대로 쌓이게 됩니다. 다음 그림은 [1번, 5번, 3번] 위치에서 순서대로 인형을 집어 올려 바구니에 담은 모습입니다.

만약 같은 모양의 인형 두 개가 바구니에 연속해서 쌓이게 되면 두 인형은 터뜨려지면서 바구니에서 사라지게 됩니다. 위 상태에서 이어서 [5번] 위치에서 인형을 집어 바구니에 쌓으면 같은 모양 인형 두 개가 없어집니다.

크레인 작동 시 인형이 집어지지 않는 경우는 없으나 만약 인형이 없는 곳에서 크레인을 작동시키는 경우에는 아무런 일도 일어나지 않습니다. 또한 바구니는 모든 인형이 들어갈 수 있을 만큼 충분히 크다고 가정합니다. (그림에서는 화면표시 제약으로 5칸만으로 표현하였음)

게임 화면의 격자의 상태가 담긴 2차원 배열 board와 인형을 집기 위해 크레인을 작동시킨 위치가 담긴 배열 moves가 매개변수로 주어질 때, 크레인을 모두 작동시킨 후 터트려져 사라진 인형의 개수를 return 하도록 solution 함수를 완성해주세요.

[제한사항]

  • board 배열은 2차원 배열로 크기는 "5 x 5" 이상 "30 x 30" 이하입니다.
  • board의 각 칸에는 0 이상 100 이하인 정수가 담겨있습니다.
    • 0은 빈 칸을 나타냅니다.
    • 1 ~ 100의 각 숫자는 각기 다른 인형의 모양을 의미하며 같은 숫자는 같은 모양의 인형을 나타냅니다.
  • moves 배열의 크기는 1 이상 1,000 이하입니다.
  • moves 배열 각 원소들의 값은 1 이상이며 board 배열의 가로 크기 이하인 자연수입니다.

입출력 예

boardmovesresult
[[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] 4

입출력 예에 대한 설명

입출력 예 #1

인형의 처음 상태는 문제에 주어진 예시와 같습니다. 크레인이 [1, 5, 3, 5, 1, 2, 1, 4] 번 위치에서 차례대로 인형을 집어서 바구니에 옮겨 담은 후, 상태는 아래 그림과 같으며 바구니에 담는 과정에서 터트려져 사라진 인형은 4개 입니다.

발상

테트리스와 비슷한 크레인게임을 구현하는 문제이다.

크레인이 움직이고 내려가는 과정을 알고리즘으로 구현하여 테스트하였는데, 코드가 약간 복잡해져서 디버깅하느라 시간을 많이 잡아먹었다.

의사코드

1. 초기값 선언(스택, 답, 임시변수 등)
2. 반복문(moves 길이만큼){
	1. 반복문(크레인 깊이 탐색){
    	1. 위에서부터 비어있으면 continue
        2. 인형이 존재하면 스택체크 및 비교
        3. 같으면 터트리고 답 +2, 아니면 스택에 넣기
    }
}
3. 답 반환

 

개선

로직에 오류가 났을때 디버깅을 빠르게 할 수 있는 방법을 고민해야 한다.

각 케이스별 필요한 정보를 로그를 찍는 방법과, 코드를 더 알아보기 쉽게 작성하는 방법, 그리고 쉽게 사용할 수 있는 기본제공 클래스등을 숙달시켜야 한다.

이슈가 있었던 부분은 뽑은 인형이 스택과 일치하여 터트리는 부분에서, 뽑힌 곳을 초기화를 시키는 부분이었다.

각 움직임마다 인형뽑기 기계의 상태를 로그로 이쁘게 출력하니 안뽑힌 부분을 찾을 수 있어서 문제점을 발견할 수 있었다.

실패한 테스트케이스를 디버깅할 수 있다면 편하게 하겠지만, 프로그래머스 시스템이 디버깅을 할 수 없는 상황이고, 실무에서도 테스트서버를 디버깅잡고 하나하나 파볼 수 없으니 로그를 찍어 찾는 연습도 해야한다.

https://school.programmers.co.kr/learn/courses/30/lessons/12916

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

대문자와 소문자가 섞여있는 문자열 s가 주어집니다. s에 'p'의 개수와 'y'의 개수를 비교해 같으면 True, 다르면 False를 return 하는 solution를 완성하세요. 'p', 'y' 모두 하나도 없는 경우는 항상 True를 리턴합니다. 단, 개수를 비교할 때 대문자와 소문자는 구별하지 않습니다.

예를 들어 s가 "pPoooyY"면 true를 return하고 "Pyy"라면 false를 return합니다.

제한사항

  • 문자열 s의 길이 : 50 이하의 자연수
  • 문자열 s는 알파벳으로만 이루어져 있습니다.

발상

문자열에서 원하는 문자를 추출하고 숫자를 세서 비교하는 문제이다.

문자를 가공하는 방법은 여러가지가 있는데 char배열로 변환하여 가공, 정규식, 스트림, String 함수 등 여러 방법을 쓸 수 있다.

스트림을 사용해서 한번 풀고, 최적화를 위하여 정규식을 사용해서 한번 더 풀어보았다.

의사코드

스트림
1. 소문자변환-> char스트림 생성 -> 필터링 -> 숫자세기
2. 숫자 비교

정규식
1. 제외 패턴작성
2. 문자열 가공
3. 가공된 문자열 검사{
	1. 문자가 p이면 count ++
    2. p가 아니면 count --
}
4. count가 0이면 true, 아니면 false

 

개선

스트림을 사용하면 가독성이 좋지만 일반적인 반복문이나 정규식등을 사용하였을 때랑 성능이 체감상 10배정도 나는 것 같다.

복잡한 데이터소스가 아닌 이상 간단한 가공은 for 반복문으로 처리하는 것이 속도의 관점에선 더 나은 선택인 것 같다. 

https://school.programmers.co.kr/learn/courses/30/lessons/12918

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

문자열 s의 길이가 4 혹은 6이고, 숫자로만 구성돼있는지 확인해주는 함수, solution을 완성하세요. 예를 들어 s가 "a234"이면 False를 리턴하고 "1234"라면 True를 리턴하면 됩니다.

제한 사항

  • s는 길이 1 이상, 길이 8 이하인 문자열입니다.

발상

문자열의 상태를 검사하는 문제이다.

정규식을 사용하면 간단하게 처리할 수 있다.

의사코드

1. 일치하는 정규표현식 작성
2. 정규식 패턴매치 함수 호출 및 확인

 

개선

정규식은 리눅스 서버에서 파일을 검색하거나, 실무에서 입력값 검사, 데이터 처리 등에서도 자주 사용한다.

배워두고 사용하지 않으면 잊어버리기 마련인데, 쓸려고 하면 쓸 수 있는 곳이 많이 있으니 계속 공부하고 하나씩 적용하자

 

+ Recent posts