ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TIL] Unity 3 + 알고리즘 문제
    TIL 2024. 5. 10. 21:23

    C# 프로그래머스 알고리즘 문제

    팀장님이 아침에 1시간 알고리즘 문제를 푸는게 어떠냐하셔서 좋다고 해서 풀어 보고 있다.

    물론 어려운거 말고 쉬운거...ㅎㅎ

    아침에 졸려서 멍 때릴때가 많았는데 하나 풀고나면 집중이 잘되긴 한다.(이게 왜 안 돼!!!하면서 화내가지고..)

    1. 기사단원의 무기 Lv.1

    더보기

    간단하게 정리하면 이렇다.

    1. 기사는 자신이 가진 숫자의 약수들(공격력이라 칭한다)을 기반으로 무기를 만든다.

    2. 그러나 나라간 협정으로 특정 공격력보다 높은 무기는 만들 수 없고, 만약 공격력을 넘는다면 정해진 공격력의 무기를 사용해야한다.

    3. 무기의 공격력 1당 1Kg의 철이 들어간다고 할 때, 한 기사의 무기를 만들 때 들어갈 철의 양을 구하여라.

     

    내가 생각했을 때의 문제 푸는 법은 다음과 같다.

    1. 약수를 먼저 구해서 배열에 넣는다. (이중 for문)

    2. 다시 for문을 돌리면서 특정 숫자(협정으로 정해진 공격력) 보다 크다면, 정해진 숫자로 바꾼다. 

    3. 그렇게 총 합을 구한다 (answer += i)

     

    위에서 적어둔 풀이법으로 코드를 짜봤다.

    using System;
    
    public class Solution {
        public int solution(int number, int limit, int power) {
            
            int[] arr = new int[number];
            int count = 0;
            int answer = 0;
            
            for(int i=1; i<=number; i++)
            {
                count = 0;
            
                for(int j=1; j<=i; j++)
                {
                    if(i%j==0)
                    {
                        count++;
                    }
                }
                
                arr[i-1]=count;
            }
            
            for(int k=0; k<number; k++)
            {
                if(arr[k]>limit)
                {
                    arr[k]=power;
                }
                answer += arr[k];
            }
            
            return answer;
        }
    }

    그러나 이 코드로 테스트 코드는 문제 없이 풀려서 제출했더니...

    시간초과!!!!!!!!

    시간 초과는 말 그대로.. 내 코드로 문제를 풀었을 때 별로 빠르지 못하다는 것이다. 

    시간 초과가 났을 때는 다음과 같은 방법을 시도할 수 있다.

     

    모든 언어에서 공통된 조건인지는 잘 모르겠지만

    1. 최대한 함수 사용 피하기

    예를 들어 list.Count() 같은 값을 계속 호출해야 한다면   int  count = list.count() 같이 값을 할당해주고 불러오는게 빠르다.

    2. 리스트 대신 큐나 스택이 더 빠르다 (가능하다면)

    3. while문 보다 for문이 더 빠르다. (반복문 자체는 많이 쓰면 값이 많을 수록 느리다)

    4. C++ 기준 입출력인 Cout 과 Cin 보다 printf 가 더 빠르다. (지금은 의미 없다)

    등등..

    누르면 여러 사람들이 질문한 글을 볼 수 있다.

    감을 잘 못잡고 있었는데 프로그래머스의 질문하기의 글 중에서  Math.Sqrt()를 이용해보라는 정보를 들었다.

    Math.Squrt()

    제곱근을 반환하는 함수다.

     

    글을 더 읽어보자면 약수는 나누는 수와 몫이 서로 대칭인 관계에 놓여있다. ex) 12/4=3 12/3=4

    그래서 약수를 구할때 구하려는 수의 제곱근까지만 범위를 지정하고 *2 해줘야 한다...라고 적으셨지만 완벽하게 이해한 것은 아니다.

     

    아무튼 참고하여 코드를 고쳐봤고 시간 초과에 걸리지 않았다.

     

    약수를 모두 구하기 위해 모든 수를 순차적으로 돌필요 없이 제곱근을 사용해 for문 계산이 훨씬 빨라졌기 때문이라고 추측한다.

    using System;
    
    public class Solution {
        public int solution(int number, int limit, int power) {
            
            int[] arr = new int[number];
            int count = 0;
            int answer = 0;
            
            for(int i=1; i<=number; i++)
            {
                count = 0;
            
                for(int j=1; j<=Math.Sqrt(i); j++)
                {
                    if(i%j==0)
                    {
                        count++;
                        if(j*j != i)
                        {
                            count++;
                        }
                    }
                }
                
                arr[i-1]=count;
            }
            
            for(int k=0; k<number; k++)
            {
                if(arr[k]>limit)
                {
                    arr[k]=power;
                }
                answer += arr[k];
            }
            
            return answer;
        }
    }

    https://learn.microsoft.com/ko-kr/dotnet/api/system.math.sqrt?view=net-8.0

     

    Math.Sqrt(Double) 메서드 (System)

    지정된 숫자의 제곱근을 반환합니다.

    learn.microsoft.com

     

    2. 과일장수 Lv. 1

    더보기

    간단하게 정리하면 이렇다.

    1. 사과를 박스안에다 포장을 해야할 때  사과의 등급은 포장된 사과들 중에 가장 품질이 낮은 사과로 결정된다.
    2. 박스안에 포장할 수 있는 사과는 정해져있고. 가지고 있는 사과를 잘 조합해 가장 높은 수익을 얻어야한다.
    3. 이익 구하는 계산 (최저 사과 점수) x (한 상자에 들어간 사과의 수 )x (상자의 수)

    내가 생각 한 방법은 이렇다.

    1. 사과들을 큰 수(등급이 높은순)로 정렬한다.

    2. 박스에 포장할 수 있는 크기만큼 건너뛰어서 가격을 계산한다

     

    작성한 코드

    using System;
    
    public class Solution {
        public int solution(int k, int m, int[] score) {
            int count = score.Length / m;
            int answer = 0;
            Array.Sort(score);
            Array.Reverse(score);
            
            for(int i = 1; i<= count;i++)
            {
                answer += score[i*m -1 ]* m; // arr[2] arr[5] arr[9] arr[12] 
            }
            return answer;
        }
    }

    sort.Reverse()

    내림차순으로 정렬해주는 함수이다.

    중요한 점은 내림차순을 하기전에 무조건 오름차순으로 한번 정렬해 준 후 실행해야한다.

     

    참고로 프로그래머스도 출력결과를 미리 볼 수 있다.

    C#이라 Console.WriteLine() 썼습니다.

    VisualStudio 쓰다가 프로그래머스로 작성하면 내가 문법에 맞게 작성했나? 또는 디버깅을 확인 하고 싶을 때가 많았는데

    출력이 가능하니 미리 중간값을 출력해보는 것도 나쁘지 않다.

    (나는 몰라서 복사해서 임의로 값넣고 VisualStudio 에 넣고 돌려본 경험이 있다...이러지 말자)

     

    Unity

    Animation & Animator

    Animation

    오브젝트에 애니메이션을 추가할 때 사용한다.

    간단한 애니메이션에 적합하며 스크립트를 통해 직접 제어할 수 있다.

    컴포넌트를 사용하여 오브젝트의 크기를 변경하거나 색상을 변환하는 등의 간단한 애니메이션을 생성할 수 있다.

    Animator

    애니메이션의 상태를 제어하고 전환을 관리하는 데 사용한다.

    Animation Controller를 사용하여 복잡한 상태를 구현할 수 있다.

    여러 애니메이션 클립을 조절하고, 전환을 제어하고 , 시퀀스를 구현하는데 적합

    Animation보다 Animator을 사용할 때가 더 많다.

     

    StringToHash

    유니티 애니메이션에서 자주 사용되는 기능.

    문자열을 해시 값으로 변환하여 성능을 개선하고 코드의 가독성을 유지한다.

    문자열은 상대적으로 연산 비용이 큰 작업이지만 StringToHash는 문자열을 고유한 정수 값인 해시로 변환하여 비용을 크게 줄일 수 있다.

    애니메이션 파라미터를 지정할 때 문자열 대신 해시 값을 사용하면 CPU시간을 절약할 수 있다.

    주의할 점은 동일한 문자열은 동일한 해시 값을 반환하지만, 반대로 동일한 해시값이 항상 동일한 문자열을 반환하지 안는다. - 해시 충돌 발생할 수 있다

    또한 해시 값을 문자열로 변환하는 것은 불가능

     

    AnimatorOverrideController

    같은 애니메이션 구성을 가진 다른 오브젝트가 있는경우, 애니메이션 파일만 갈아끼워서  같은 애니메이터를 활용하게 하는 컴포넌트.

     

    싱글턴 패턴

    소프트웨어 디자인 패턴 중 하나로, 특정 클래스의 인스턴스가 하나만 존재하도록 보장하고 이를 전역적으로 접근할 수 있게 제공하는 패턴

    싱글턴 객체는 프로그램의 수명주기 동안 계속 존재하므로 메모리 관리에 신경써야한다.

    싱글턴 패턴을 잘못 사용하면 코드의 결합도를 높이고 테스트와 유지보스를 어렵게할 수 있다,

     

    FindGameObjectWithTag

    지정된 태그와 일치하는 첫번째 활성 GameObject를 반환한다. 특저 태그를 가진 오브젝트를 빠르게 찾을 수 있도록 도움

    그러나 "FindGameObjectWithTag"는 매우 비싼연산. 즉, CPU를 많이 사용하게 된다.

    Start나 Awake에서 한번만 호출하는 것을 추천

     

    Physics.Raycast 또는 Physics2D.Raycast

    콜라이더와 교차하는지를 감지하는 데 사용되는 기술, 레이저 포인터와 비슷하다

    메서드는 시작점, 방향, 최대거리, 선택적으로 레이어 마스크를 매개변수로 받는다.

    hit 정보를 반환하여 충돌한 객체, 지점, 벡터 등을 알아낼 수 있다.

    Debug.DrawRay를 사용하여 시각적으로 RayCast를 볼 수 있다.

    'TIL' 카테고리의 다른 글

    [TIL] 유니티 개인과제 2  (0) 2024.05.14
    [TIL] 유니티로 개인과제 1  (0) 2024.05.13
    [TIL] Unity 강의 2  (0) 2024.05.09
    [TIL] Unity 강의 1  (0) 2024.05.08
    [TIL] 게임 특강  (0) 2024.05.07
Designed by Tistory.