01/15 본캠프 #15

guno park·2024년 1월 15일
0

본캠프

목록 보기
16/77

알고리즘 풀어보기

최대공약수와 최소공배수

풀이

최대공약수와 최소공배수를 나눠서 풀었음.

int a = n <m ? m:n;
int b = n <m? n:m;

주어진 두 수 m,n 중 큰 값을 a, 작은 값을 b로 두었음.

최대공약수 구하기

for (int i =1;i<=b;i++){
	if (n%i ==0 && m%i==0){
		answer[0]=i;                
	}
}

반복문을 돌렸을 때, i가 a보다 커지면 약수가 될 수 없기에 i의 범위는 b보다 작거나 같을 때까지, n과 m의 나머지가 0이 되는 i 중 가장 큰 값을 answer[0]에 저장한다.

최소공배수 구하기

for (int i =1;i<=a;i++){
           for (int j =1;j<=a;j++){               
               if (b*j ==a*i){
                   answer[1]=b*j;
                   break;
               }
            }
            if (answer[1] != 0)
                break;
        }        

2중 for문을 돌려서, 작은수안쪽for문 == 큰수바깥쪽for문을 했을 때 true가 되는 b*j의 값이 최소공배수라고 판단. answer[1]에 저장하고 break; 최소공배수를 구하기에 더 돌릴 필요가 없음. 같은 의미로 바깥쪽 for문도 만약 answer[1]번이 0이 아니라면 break로 빠져나오게 해준다.

3진법 뒤집기

풀이

(참고 : 동그라미)
3진법 변환만 살짝 가져옴.

변환하는 법

10진법 a라는 수가 있을 때, a가 0이 될 때까지, a%3을 저장하고 ,a/3을 해준다.

while(a!=0){
list.Add(a%3);
a/=3;
}

뒤집기

변환하면서 만들어진 리스트를 Reverse한 후, 0번부터 3의n제곱을 곱해서 더하면 뒤집은 값이 출력된다.

list.Reverse();
for (int i=0;i<list.Count;i++){
	answer += list[i]*(int)Math.Pow(3,i);
}

기억해야 할 점.

2진법이고 3진법이고 위와 같은 방식으로 변환할 수 있음을 기억하자.

이상한 문자 만들기

(참고 : toupper,tolower DevStory)

처음 생각한 풀이

  1. 문자열을 문자 단위로 분리한다.
  2. 소문자인지 대문자인지 구분한다.
  3. 짝/홀수로 구분해 바꿔준다. (대문자 -> 소문자면 아스키코드로 +32, 반대면 -32)
  4. 합쳐서 반환한다.

문제 발생

이렇게 했을 때 문제는 문자열+int로 하면 string이 아니라 int로 나와서 실패했다. 거기에 같은 배열에 넣어놨더니 공백 기준으로 짝/홀수를 체크해야되는데 그렇게 하기 힘들어졌다.

문제 해결

먼저 대문자,소문자 변환을 String 클래스에서 제공하는 ToUpper(),ToLower() 메서드로 해결했다.
그리고 공백 기준으로 체크해야하기에 주어진 string을 공백기준으로 Split해주었다.
그리고 그 나눠진 string들을 또 문자로 분리해서 짝/홀수에 따라 변환해주고 차례대로 반환값에 더해주면 된다.
※ 바깥 for문에서 공백을 더해주기 때문에, i==a.Length일 때는 공백을 더하지 않도록 처리해준다.

public class Solution {
    public string solution(string s) {
        string answer = ""; 
        string[] a = s.Split(' ');        
        for (int i =0; i < a.Length; i++){
            char[] chars = a[i].ToCharArray();
            for (int j=0;j<chars.Length;j++){
            if (chars[j] != 32 && j % 2 == 0){
                answer += $"{chars[j]}".ToUpper();
            }
            else if (chars[j] != 32 && j % 2 == 1){
                answer += $"{chars[j]}".ToLower();
            }            
            }            
            if (i!=a.Length-1)
                answer += " ";
        }

        return answer;        
    }
}

삼총사

풀이

이 문제는 number의 길이 n 중에서 조건에 해당하는 3명을 뽑는 문제로 수학의 조합 문제와 같다.
조건 없이 구한다면 수학 공식을 적용해도 되겠지만, 여기서는 3명의 합이 0이 되는 조합 갯수를 구해야 하기때문에, 그냥 간단하게 for문 3중첩으로 돌렸다.
1. 첫번째 for문으로 첫 학생을 지정
2. 두번째 for문으로 두번째 학생을 지정
3. 세번째 for문으로 두번째 학생 이후를 돌려서 0이 나오는 세 학생의 조합을 찾는다.
4. ~반복~

using System;

public class Solution {
    public int solution(int[] number) {
        int answer = 0;
        for (int i=0;i<number.Length;i++){
            for (int j=i+1; j<number.Length;j++){
                for (int k=j+1;k<number.Length;k++){
                    if (number[i]+number[j]+number[k]==0)
                        answer++;
                }
            }
        }
        return answer;
    }
}

의외로 생각과 달랐던 점

맨 위 for문은 i가 number의 끝까지 가기 때문에 밑에서 좀 걸리지 않을까 걱정했는데, for문에 두번째 문단이 조건식이기 때문에, i가 끝이라면 j=i+1; number.Length의 길이를 넘어서기때문에 돌아가지 않는다. 두번째가 돌아가지 않는다면 3번째도 돌아가지 않기 때문에 알아서 걸러진다.

최소직사각형


풀이

딱 보자마자 든 생각은, '가로로 넣는 지 세로로 넣는 지 고민할 필요가 없겠구나'였다.
가로x세로로 적혀있다고 하면, 두 수의 위치를 바꿔주면 그만이다.
그래서
1. 알고리즘 시작 부분에 만약 가로가 세로보다 작다면, 가로와 세로의 값을 바꿔주도록 했고,
2. 가장 큰 세로x 가장 큰 가로 를 구하기 위해 가로, 세로별 배열을 따로 만들어 각각 저장해주고,
3. 정렬을 통해 가장 끝의 값끼리 곱해서 산출했다.

using System;
using System.Linq;

public class Solution {
    public int solution(int[,] sizes) {
      int answer = 0;
 for (int i = 0; i < sizes.GetLength(0); i++)
 {
     if (sizes[i,0] < sizes[i, 1])
     {
         int temp = sizes[i,0];
         sizes[i,0] = sizes[i, 1];
         sizes[i,1] = temp;
     }
 }
 int[] width = new int[sizes.GetLength(0)];
 int[] Height = new int[sizes.GetLength(0)];

 for (int i =0; i < sizes.GetLength(0); i++)
 {
     width[i]= sizes[i,0];
     Height[i] = sizes[i, 1];
 }
 width = width.OrderBy(x => x).ToArray();
 Height = Height.OrderBy(x => x).ToArray();
 

 return answer=width[width.Length-1]*Height[Height.Length-1];
    }
}

끝나고 든 생각

굳이 width[width.Length-1]을 안 넣고 width[-1]을 넣어도 되지 않을까?
=> 어레이 바운드 벗어났다고 에러났다. 아닌가보다.

시저 암호

풀이

(참고 : Convert 코딩하는 돼징)
내 생각에는 조금 어렵게 풀지 않았나 싶다.

  1. 들어온 문자열을 문자로 뜯어준다. (아스키코드값을 통해 밀어주기위해서)
  2. 대문자, 소문자, 공백 구분을 해준다.
  3. 공백을 제외한 각 구분에 만약 문자+n을 했을 때 대문자,소문자 범위를 벗어나는 지 조건을 판별하고, 만약 벗어났다면 (chars[i] - 25 + n -1)만큼 해서 돌아오게 만든다.
  4. 각 문자들을 문자열 answer에 반환한다.
using System;
public class Solution {
    public string solution(string s, int n) {
    string answer = "";
	char[] chars = s.ToCharArray();
    for (int i = 0; i < chars.Length; i++)
    {
        if (chars[i] >= 65 && chars[i] <= 90)
        {
            if (chars[i] + n > 90)
                answer += Convert.ToChar(chars[i] - 25 + n -1);

            else
            {
                answer += Convert.ToChar(chars[i] + n);
            }

        }
        else if (chars[i] >= 97 && chars[i] <= 122)
        {
            if (chars[i] + n > 122)
                answer += Convert.ToChar(chars[i] - 25 + n-1);

            else
            {
                answer += Convert.ToChar(chars[i] + n);
            }

        }
        else if (chars[i] == 32)
            answer += " ";
    }
	return answer;
	}
}

여기서 Convert.ToChar라는 메서드가 쓰였는데, ()안에 있는 값은 int값이고, 그 값에 해당하는 아스키코드로 바꿔주는 기능을 수행한다.

하고 느낀 점

아~까 (이상한 문자열 만들기) 할 때 알았으면 이 방법으로 했지 싶은데, 덕분에 upper/lower를 알아서 다행이다.

숫자 문자열과 영단어

생각한 풀이

주어진 s에 zero~nine까지 Replace()를 한다. 끝

using System;

public class Solution {
    public int solution(string s) {
        int answer = 0;
        s = s.Replace("zero","0");
        s = s.Replace("one","1");
        s = s.Replace("two","2");
        s = s.Replace("three","3");
        s = s.Replace("four","4");
        s = s.Replace("five","5");
        s = s.Replace("six","6");
        s = s.Replace("seven","7");
        s = s.Replace("eight","8");
        s = s.Replace("nine","9");
        
        return answer=int.Parse(s);
    }
}

포스팅 하는 이유

원래는 안 적으려 했는데, Replace에 대해 기록하기 위해 포스팅함.
(참고 : 와이키키박사의 비밀기지)

Replace의 기능
1. 문자열 치환 : "A"라는 문자열을 "B"로 치환하는 기능
만약 문자열에 "A"라는 문자가 없으면, 아무것도 안 하고 넘어감.
2. 공백을 제거 할 수 있음

ex)

string A1 = "My Name";
string A2 = null;

A2 = A1.Replace(" ","");

Console.WriteLine("A1 : " + A1);
Console.WriteLine("A2 : " + A2);

문자열 내 마음대로 정렬하기


이 문제는 좀 오래 걸렸다. 결국 혼자서는 못 풀었다.

첫번째 풀이 (튜플)

using System;
using System.Collections.Generic;
using System.Linq;

public class Solution {
    public string[] solution(string[] strings, int n) {
       string[] answer = new string[strings.Length];
	List<Tuple<char, int>> list = new List<Tuple<char, int>>();
    for (int i = 0; i < strings.Length; i++)
    {
        string s = strings[i];
        list.Add(new Tuple<char,int>(s[n],i));                
    }
    list = list.OrderBy(x => x).ToList();
    for (int i = 0; i < answer.Length; i++)
    {
        answer[i] = strings[list[i].Item2];
    }
    return answer;
        }
}

첫번째로는 튜플로 풀어보려했다. char,int로 각각 정렬에 사용될 값과 그 인덱스를 받아온다.
이 방법은 첫번째 테스트까지만 통과하고
두번째 테스트인 사전순으로 정렬하는 기능을 통과하지 못해 폐기했다.

두번째 풀이 (Sort)

(참고 : sort)

string[] answer = new string[] { };
      
Array.Sort(strings, (a, b) =>
{
    if (a[n] < b[n])
        return -1;
    else if (a[n] > b[n])
        return 1;
    else if (a[n] == b[n])
        return String.Compare(a[n + 1].ToString(), b[n+1].ToString());
    else
        return 0;
});

return answer = strings;

두번째 풀이는 람다식으로 a와 b를 비교해 a가 더 작으면 앞으로, 크면 뒤로, 같다면 그 다음번째 문자를 비교하는 방식으로 진행했다.
이 방법으로 사전순 정렬까지 통과했으나, 큰 단점이 있다.
바로 붙어있는 두 문자열만 비교한다는 것으로, 전체적인 정렬이 먼저 이루어지지 않으면 바닥부터 쓸고 천장 먼지터는 격이 되어버린다는 것이다.

참고 한 것

(참고 : 애뎡의 잡동사니)
한 4시쯤부터 7시 반까지 하다보니, 그냥 적당한 거 없나 찾아보는데, 한 줄로 정리되는 게 있어서 노력한 의미를 찾기위해 이걸 분석해보려고 한다.

문제의 이해

 answer = strings.OrderBy(x => x).OrderBy(x => x[n]).ToArray();

진행 순서는 ->
1. strings 전체를 먼저 오름차순을 정렬한다.
2. 다시 정렬을 하는데 이번에는 n번째 문자를 기준으로 정렬한다.

와!

비교분석

이 문제 풀이가 내꺼에 비해 이렇게 간단해질 수 있던 이유는
1. 전체적인 정렬부터 시작했다. (전체를 사전순으로 정렬하면, n에서 겹치는 것들이 나와도 그것도 사전순으로 정렬된다.)
2. Linq와 람다를 적절히 사용할 줄 안다. (x=>x[n])은 나도 해봤지만, OrderBy.OrderBy는 처음 봤다.

문제를 파악하는 데 있어 무엇은 우선해서 해야할 것인지 알아야한다.
그러기 위해선 문제와 조건을 잘 읽어보자.
ex) 두개가 겹치면 사전순 > 전체 정렬부터 먼저 하기

팀 프로젝트 - TextRpg 만들기

회복하는 기능 추가하기

만약 전투에 져서 마을로 돌아 왔을 때, 떨어진 체력을 충전할 곳을 안 만들었기에 개인과제처럼 간단하게 하나 만들었다.
1. 입장하면 휴식하는 곳에 대해 간단하게 소개를 하고, 기능과 조건을 알려준다.
2. 플레이어의 선택을 통해 돌아갈 지, 회복할 지 정한다.
3. 회복을 한다면 체력과 마나를 다 채워서 보내고, 골드를 회수 한 후 메인으로 돌려보내고,
그냥 돌아간다를 선택하면 메인으로 보낸다.

통합

오늘은 전체 코드를 통합해 검수과정을 거쳤다.
혼자 할 때는 찾지 못했는데, 여러명이 같은 화면을 보고 있으니 다 다른 시야로 봐서 그런가 엄청
많이 나왔다.
다른 분들 코드랑 합치다 보니, 클래스에서 멤버 호출할 때 달라지는 게 많았는 데, 그런 것들이나 아니면 '나중에 통합하고 붙여야지~'같은 것들을 오늘 다 정리했다.
발표자료도 다 만들고 했는데, README는 뭐 적어야될지 잘 모르겠다.

내일 할 일

  1. 알고리즘 풀기
  2. 동기화/비동기화 공부
  3. 유니티 미리 좀 점검하기

0개의 댓글