본문 바로가기

TIL

[TIL]2024-4-01 / 61일차 - 최종 프로젝트 5주차 1일차

1. 오늘의 코드카타 - 문자열 나누기

답안 : 

//오랜만에 봐도 문제 설명이 쉽지않다. 예시가 없다면 이해하기 어려웠을 것
//어떤 형식으로 분해를 시켜야 할까 고민하다 너무 지저분한 코드가 되어가서
//다른 답안을 참고하게 되었다. 여기서는 인덱스를 세분화한 것과
//bool체크를 통한 것이 다른 점이다.
//코드가 복잡해지던 원인이 새로운 문자의 시작지점을 판단하는 것이었는데
//이러한 체크가 더 깔끔해진 것이다.

public class Solution {
    public int solution(string s) {
        int answer = 0; // 분해한 문자열의 개수
        int sameIdx = 0; // 같은 문자열 개수
        int diffIdx = 0; // 다른 문자열 개수
        char word = ' '; // 현재 단어
        bool start = true; // 시작지점 판단
        
        for(int i = 0; i < s.Length; i++)
        {
            if(start == true) // 시작지점으로 판단될 때
            {
                word = s[i]; // 현재 단어 저장
                sameIdx++; // 같은 문자열 개수를 +
                start = false; // 시작지점 false로
            }
            else
            {
                if(s[i] == word)
                {
                    sameIdx++; // 같은 문자일 때 sameIdx에 +
                }
                else
                {
                    diffIdx++; // 다른 문자일 때 diffIdx에 +
                }
            }
            
            if(sameIdx == diffIdx) 
            // 다른 글자들이 나온 횟수가 같아지는 순간
            {
                // 답에 + 를 해주며 나머지 인덱스 초기화
                answer++;
                sameIdx = 0;
                diffIdx = 0;
                start = true; //다시 시작지점을 돌려준다
            }
            if(i == s.Length - 1) { if(start == false) { answer++; } } //마지막 지점에 도달했음에도 횟수가 같지 않다면 끊고 답에 + 해주는 조건문
        }
        return answer;
    }
}

2. 오늘의 기술 면접 질문

   2-1 'delegate', 'event', 'action', 'func' 간의 차이를 설명해주세요.
                (꼬리질문) 프로젝트에 적용해 본 경험이 있다면 설명해주세요.

=

   델리게이트는 이전에도 대답한 바 있듯 대리자라는 뜻으로 메소드를 '참조'해서 간접적으로 호출하고 '동일한 파라미터와 리턴 타입'을 가진 함수들을 호환해서 불러 옵니다.

   액션과 펑션은  델리게이트의 연장선에 있는 대리자들로 

액션은 매개변수가 없는 메서드를 참조할 수 있는 델리게이트로 반환 값이 없는 메서드를 참조할 때 사용합니다.

펑션은 매개변수와 반환 값이 있는 메서드를 참조할 수 있는 델리게이트로 메서드 결과 계산에 유용하며 메서드 반환 값을 처리할 때 사용됩니다.

   이벤트는 이들과 조금 다르며 델리게이트와 달리 인터페이스 내부에서도 선언이 되며 접근 제한자와 상관 없이 클래스 외부에서 호출 할 수 없습니다. 이벤트는 발생하였을 때 미리 정해진 이벤트 핸들러-메서드가 호출되는데 이때 델리게이트를 이용하여 핸들러를 등록하게 됩니다.

 

   즉 델리게이트 형태의 것들은 콜백의 용도로 자주 쓰이게 되고 이벤트의 경우 프로그램의 상태 변화를 나타내는 데에 쓰이게 됩니다.

 

요약하면, Delegate는 다른 메서드를 참조할 수 있는 변수, 
Event는 프로그램의 상태 변화를 나타내는 신호, 
Action은 매개변수가 없는 메서드를 참조하는 델리게이트, 
Func는 매개변수와 반환 값이 있는 메서드를 참조하는 델리게이트입니다.

 

      (꼬리질문)
아직 다양하게 적용해본 경험은 많이 없지만,
자주 써본 것으로 기억에 남는 것은 캐릭터 스테이터스를 관리할 때
이벤트와 액션을 통해


ex = public event Action OnDie;
        if (IsDead)
            OnDie?.Invoke();

등을 통해 사망처리 등을 하던 경험이 생각납니다.
장착된 무기 관리를 할 때
OnWeaponChange 등의 액션을 이용한 경험도 생각납니다.

 

 

2-2 람다식(Lambda Expression)이 무엇인지 설명해주세요.

 

람다식은 익명 함수를 간결하게 표현하는 방법으로 함수를 직접 만들지 않고도 코드 블록을 넘겨줄 수 있습니다.

델리게이트를 사용하여 익명함수를 만들 때 보통 람다식을 사용합니다.

람다식은 식 형식이 있고 문 형식이 있는데 람다식 연산자(=>)를 사용하여 오른쪽에 식을 쓰는 것이 식 형식이고 문 형식은 식이 아닌 코드 블록으로 작성하는 형식입니다.

간결한 코드로 가독성이 높고 필요 없는 계산을 하지 않는 장점이 있지만 남용하게 되면 순회할 때 효율성이 떨어진다는 단점이 있습니다.

 

 

2-3 콜백이란 무엇인가요? 사용해봤는지?

 

콜백은 다른 함수의 매개변수로 전달되어 특정 조건이 충족되거나 이벤트가 발생했을 때 실행되는 함수를 말합니다.

비동기적으로 작업을 하는 데 사용되고 동적으로 동작을 변경하거나 확장할 수 있습니다.

콜백 함수를 중첩해서 사용할 경우 에러 처리가 어렵고 디버깅이 어려울 수 있습니다.

 

위에 써본 경험처럼 장비 매니저에서 작동하는 OnChangeWeapon 액션을 통해

플레이어 스테이터스 코드에서 해당 액션이 발생 시에 장비의 스탯을 플레이어 스테이터스에 적용하는

메서드를 Invoke 해주는 방식으로 장비 변경을 구현했었습니다.

 

 

2-4 정렬 알고리즘이란 무엇이며, 사용 이유에 대해 설명해주세요.

 

원소들을 일정한 규칙에 따르거나 번호순에 맞춰 정렬하는 알고리즘

데이터 정렬을 수행하는 이유 중 가장 큰 이유로는 이진 탐색이 가능한 데이터를 만들기 위해서로

탐색할 데이터가 정렬되어 있지 않다면 모든 데이터를 탐색하는 순차 탐색만 사용할 수 있지만

데이터가 정렬되어 있다면 이진 탐색이라는 알고리즘을 사용할 수 있습니다.

 

이진 탐색이란 데이터가 정렬돼 있는 배열에서 특정한 값을 찾아내는 알고리즘으로

이진 탐색 알고리즘은 O(log n)의 시간복잡도를 보이기에 효율적입니다.

 

2-5 선택 정렬과 버블 정렬에 대해 설명해주시고, 코드를 작성해보세요.

 

 

선택 정렬은 배열에서 최소값을 앞으로 보내어 정렬하는 알고리즘으로

배열을 처음부터 끝까지 순회하면서 최소값을 찾아 앞으로 보내고 이 과정을 반복하기에

처리할 데이터가 많아질 수록 비효율적인 수단이 됩니다.

그렇기에 해당 정렬방법의 시간 복잡도는 O(n^2) 

장점 - 

단순한 알고리즘, 비교횟수는 버블 정렬보다 많으나 교환 횟수가 더 적어 많은 교환이 일어나는 경우에는 더 효율적일 수 있음. 또한 정해진 배열 안에서 교환하는 방식이라 제자리 정렬이기에 다른 메모리 공간을 차지하지 않음.

 

단점 -

시간 복잡도 면에서 비효율적, 불안정 정렬(중복된 값이 입력 순서와 동일하지 않게 정렬)

 

 

 

버블 정렬은 인접한 두개의 수를 비교하여 더 큰 것을 뒤로 보내는 것을 반복하여 순서대로 정렬하는 알고리즘으로

위가 작은 것부터 앞으로 정렬하는 느낌이라면 버블 정렬은 큰 것부터 뒤로 보내며 정렬하는 반대 방식입니다.

정해진 크기의 배열을 순회하면서 비교하고 정렬하는 과정을 반복하기에 어떠한 상황에도 시간 복잡도는 O(n^2)   공간 복잡도 또한 O(n) 으로 고정되어 있습니다.

 

장점 -

단순한 알고리즘, 정렬하고자 하는 배열 안에서 교환하는 제자리 정렬이기에 다른 메모리 공간 불필요, 안정 정렬(중복된 값이 입력 순서와 동일하게 정렬)

 

단점 - 

시간 복잡도가 고정되어 있으나 이 자체가 비효율적인 수준, 정렬 과정에서 교환 연산이 많이 일어나게 됩니다.

 

 

using System;

class SortingAlgorithms
{
    // 선택 정렬(Selection Sort) 구현
    static void SelectionSort(int[] arr)
    {
        int n = arr.Length;
        for (int i = 0; i < n - 1; i++)
        {
            int min_idx = i;
            for (int j = i + 1; j < n; j++)
            {
                if (arr[j] < arr[min_idx])
                {
                    min_idx = j;
                }
            }
            // 최소값과 현재 위치의 값을 교환
            int temp = arr[min_idx];
            arr[min_idx] = arr[i];
            arr[i] = temp;
        }
    }

    // 버블 정렬(Bubble Sort) 구현
    static void BubbleSort(int[] arr)
    {
        int n = arr.Length;
        for (int i = 0; i < n - 1; i++)
        {
            for (int j = 0; j < n - i - 1; j++)
            {
                if (arr[j] > arr[j + 1])
                {
                    // 인접한 두 원소 교환
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

 

 

gif 출처들 = https://github.com/GimunLee

 


3. 오늘의 작업

오늘은 사정이 있어 일주일만에 복귀했기 때문에 프로젝트 진행 정도 파악을 해야 했다.

후크 캐릭터가 완성되어 감에 따라 애니메이션이 필요해져 이 부분을 작업했다.

 

 

기존에 서브 스테이트 머신을 안쓰다보니 뒤늦게 바꾸려니 기존 파라미터들의 사용 방법이 지금의 형태에 맞춰져 있어 원하는 대로 바꾸기가 시간적으로 오래 걸릴 것으로 예상 되어서 불편하지만 이대로 추가하며 사용하였다.

 

네트워크 연동에 있어 레이어가 많이 갈리다 보면 동기화에 버그가 날 때가 많아 한 레이어에 몰아 넣으려고 한 점도 작용하였다.

 

 

꽤나 자연스러운 그래플링 모션이 나왔다.

날라가는 모션에 경우 기존 점프 모션과 연계되게 되어 있으나 이 부분을 위한 모션과 착지 모션을 만들까도 생각 중이다.