20231114_기록_크기가 작은 부분 문자열(프로그래머스)

2023. 11. 14. 21:11IT/TIL

오늘 한 것들

 

Chapter 2 프로그래밍기초 개인과제 개선

알고리즘 코드타카

 

오늘의 TIL은 두개로 우선은 알고리즘 코드타카에서 배운 내용이다.

더보기

문제는 크기가 작은 부분 문자열로 아래의 링크이다.

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

 

프로그래머스

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

programmers.co.kr

 

문제를 설명하면 숫자로 이루어진 문자열 t와 p가 주어지는 경우에

문자열 t에서 문자열 p의 길이와 같은 부분 문자열들을 추려낸 경우,

그 부분 문자열들이 문자열 p보다 작거나 같은 수의 갯수를 구하는 문제이다.

 

예를들어 t = "3141592" 이고 p = "271"인 경우,

t의 길이가 3인 부분 문자열은 314, 141, 415, 159, 592 인데

이 중에서 271보다 작거나 같은 수는 141, 159로 답은 2이다.

 

이 문제를 풀기위한 로직은

1. 주어진 문자열 p의 길이를 구한다.

2. p의 길이로 문자열 t를 자른다.

3. 자른 문자열들과 p를 비교하여 작거나 같을 때마다 answer++을 한다.

의 세 단계로 나눌 수 있다.

이를 코드로 나타내면

 

using System;

public class Solution {
    public int solution(string t, string p) {
        int answer = 0;
        int num = p.Length;
        long[] def = new long[t.Length - num + 1];
        
        for (int i = 0; i < t.Length - num + 1; i++)
        {
            def[i] = Int64.Parse(t.Substring(i, num));
            if (def[i] <= Int64.Parse(p))
            {
                answer++;
            }
        }
        
        return answer;
    }
}

 

로 나타낼 수 있다.

int num은 문자열 p의 길이를,

long 배열 def는 문자열 t를 num의 길이로 잘라낸 부분 문자열들의 배열이다.

 

for 문에서 문자열 t를 i번째 위치부터 num의 길이로 잘라내서 숫자로 변환하여 배열 def의 def[i]위치에 넣어줬다.

if 문 안에서는 문자열 p를 숫자로 변환하여 def[i]와 비교하여 def[i]가 작거나 같은 경우 answer++을 하도록 했다.

 

 

이 과정에서 문제가 됬던 점은 2개이다.

첫 번째는 배열 def의 index의 수로

배열 def에는 문자열 t를 문자열 p의 길이(num)로 잘라주므로,

문자열 t의 길이 - num + 1개 만큼 배열 def에 넣어줄 수 있다.

이를 기호들을 이용하여 이해하려면 어려움이 있었는데,

 

예시로 나왔던 숫자를 이용하면

7자리의 수를 3자리의 수로 나타내면 몇개를 나타낼 수 있는가? 라는 문제로

7자리의 수를 순서대로 3자리 수로 표현하는 경우

7번째의 경우 1자리 수로 표현되고

6번째의 경우 2자리 수로 표현되고

5번째의 경우 3자리 수로 표현된다.

따라서 m자리의 수를 n자리의 수로 나누는 경우 m - n + 1개의 수를 구할 수 있다.

(배열 def의 index를 같이 생각하다보니 헷갈리는 부분이 많았다)

 

즉 배열 def에 넣어야되는 숫자의 개수는 t의 길이 - p의 길이 + 1개 이므로

for 문에서 i의 범위는 0 <= i <= t의 길이 - p의 길이가 된다.

(배열의 경우 index는 0부터 길이 - 1이므로)

 

이 부분에서 범위를 실수하여 결과값이 잘못 나오는 에러가 발생했었다.

배열이 나오는 경우에는 범위가 달라지는 점을 조심해야되는 것을 다시금 깨달았다.

 

 

두 번째는 int와 long의 차이로

주어진 문제에서 p와 t의 길이가 아래와 같이 주어졌다.

1 ≤ p의 길이 ≤ 18

p의 길이 ≤ t의 길이 ≤ 10,000

즉 p는 최대 18자리의 수라는 뜻으로 이는 int로는 담을 수 없는 범위이다.

C# 사전 문법 기초에서

int는 –2,147,483,648 ~ 2,147,483,647 의 범위로 10자리 수까지 담을 수 있는데,

p의 길이가 18자리 수까지 나타날 수 있으므로, int로는 범위가 초과해 런타임 오류가 나올 수 있다.

따라서 int가 아닌 long을 사용해야된다.

 

알고리즘 코드카타를 풀 때 많이 있는 경우로 문제에서 주어진 값이

int로 표현할 수 있는지, long으로 표현해야되는지 미리 판단해야되는 경우이다.

 

이러한 연습으로 문제를 풀고 제출 시에도 피드백을 받는 환경에서는 해도 괜찮은 실수이지만,

제출 시에 코드를 수정할 수 없는 코딩 테스트나 입사 시험의 경우에는

이러한 int와 long의 실수가 감점 요인이 되므로 문제를 다시금 잘 읽어야되는 점을 상기시켜줬다.

 

 

두 번째는 개인과제의 개선으로 오늘 추가한 것은 장착 개선 부분이다.

아이템을 장착하는 과정에서 타입별로 1개의 아이템을 장착할 수 있게 하는 것으로

아래의 로직으로 코드를 구현해 나갔다.

더보기

장착 개선 - 추가할 로직
무기를 기준으로 작성

bool 값으로 무기를 장착하고 있는지 확인

public static bool IsWeaponEquip = true;

(초기에 "무쇠 갑옷"과 "낡은 검"을 장착하고 있으므로,
 초기 값을 true로 시작)

아이템을 장착하려고 하는 순간
1. 그 아이템이 무기인지 방어구인지 확인
2. 무기인 경우에 무기를 장착하고 있는지 확인
3. 무기를 장착하고 있다면, 그 무기를 해제하고
4. 장착하려는 무기를 장착


무기를 장착하고 있으면 IsWeaponEquip = true
만약 무기를 해제하면 IsWeaponEquip = false로 변


-------------------------------------------------------

진행 상황
1. 아이템을 어떻게 무기인지 방어구인지 확인할 것인가
해결 방안
1. 공격력을 올리면 무기, 방어력을 올리면 방어구
-> 예상되는 문제는 방어력을 올리는 무기, 공격력을 올리는 방어구는 어떻게 할 것인가
-> 기각
2. 아이템에 새로운 특성을 추가하여 무기와 방어구 등 구분
-> public string Type -> Type에 무기, 방어구
items[i].Type == weapon -> 이런 식으로 사용할 수 있을 것.

 

아이템 별로 Type을 도입하여 중복된 Type의 아이템을 장착하고 있는지 파악할 수 있게 구현했다.

무기를 예로 들면 UnEquipWeapon(); 함수를 아래와 같이 작성했는데,

public static void UnEquipWeapon()
{
    if (IsWeaponEquip)
    {
        for (int i = 0; i < items.Length; i++)
        {
            if (items[i].Type == "Weapon")
            {
                if (items[i].IsEquip)
                {
                    items[i].IsEquip = false;
                    items[i].Name = items[i].Name.Substring(3);
                }
                IsWeaponEquip = false;
            }                 
        }
    }
}

 

 

만약 IsWeaponEquip 상태라면 (무기를 장착하고 있다면)

전체 아이템 중에서 Weapon Type의 아이템들을 찾은 후에

그 무기가 IsEquip 라면 (장착하고 있는 상태라면) IsEquip을 false로 바꾸고 (장착을 해제하고)

이름에 추가했던 [E]를 없애준 후에 IsWeaponEquip을 false로 변경하는 방식으로 구현했다.

이 함수를 통해서 무기를 장착하고 있는 경우에는 그 무기를 찾아서 해제할 수 있게 되었으며,

이는 IsWeaponEquip 이라는 bool 값을 통해서 조절할 수 있다. 

 

 

위의 사진처럼 낡은 검을 장착하고 있는 상태에서 숏소드를 장착하면

그 순간 낡은 검이 해제되고 숏소드가 장착하게 기능을 구현했다.