2023. 11. 14. 21:11ㆍIT/TIL
오늘 한 것들
Chapter 2 프로그래밍기초 개인과제 개선
알고리즘 코드타카
오늘의 TIL은 두개로 우선은 알고리즘 코드타카에서 배운 내용이다.
문제는 크기가 작은 부분 문자열로 아래의 링크이다.
https://school.programmers.co.kr/learn/courses/30/lessons/147355
문제를 설명하면 숫자로 이루어진 문자열 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 값을 통해서 조절할 수 있다.
위의 사진처럼 낡은 검을 장착하고 있는 상태에서 숏소드를 장착하면
그 순간 낡은 검이 해제되고 숏소드가 장착하게 기능을 구현했다.
'IT > TIL' 카테고리의 다른 글
20231116_기록_숫자 문자열과 영단어(프로그래머스) (0) | 2023.11.16 |
---|---|
20231115_기록_최소직사각형(프로그래머스) (0) | 2023.11.15 |
20231113_기록_개인과제 (0) | 2023.11.13 |
20231110_기록_3진법 뒤집기(프로그래머스) (0) | 2023.11.10 |
20231109_기록_Flood Fill(LeetCode 773) (1) | 2023.11.09 |