10월 30일

Yullgiii·2023년 10월 30일
0
post-thumbnail

내일 배움 캠프

오늘부터는 불안정한 게더타운에서 젭으로 이동을 하였다...
팀원들과 오늘은 KPT작성을 해볼 예정이다.
그리고 알고리즘 문제와 자바강의를 들을 예정에 있다.

Java

조금 헷갈리는 Wrapper 클래스 (아이언맨이라 생각하자)

사람이 원시값 슈트가 래퍼클래스!

  • 각 원시 자료형에는 그에 해당하는 래퍼 클래스가 있음
    • 해당 자료형에 관련된 클래스/인스턴스 기능들을 제공
    • 클래스 인스턴스를 받는 곳에 활용
  • 각 자료형의 원시값은 해당 래퍼 클래스의 인스턴스와 서로 변환 가능
  • 원시값의 존재 이유 : 더 높은 성능(가장 중요한 이유이지...)
    • 대신 순수한 객체지향 언어는 아니게 됨…

이렇게 알고 있더라도 헷갈리긴한다..
Wrapper 클래스 종류

원시 자료형래퍼 자료
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

이 클래스를 알려면 기본적으로 알아야하는 정보인 박싱언박싱이 있다.
원시값 -> 래퍼클래스 : boxing
래퍼클래스 -> 원시값 : unboxing

제네릭....어렵...

자료형을 필요에 따라 동적으로 정할 수 있도록 해 주는 역할을 한다...

		//  제네릭 메소드
		//  T : 타입변수. 원하는 어떤 이름으로든 명명 가능
		public static <T> T pickRandom (T a, T b) {
        return Math.random() > 0.5 ? a : b;
    }

가장 기본되는 형식!!!!!
타입이 일관되지 않고 묵시적 변환 불가하면 오류가 발생한다.
예를 들어 문자를 더블로 받거나 하나는 하나는 스트링하나는 더블일경우!
클래스로 제네릭 활용하기!!!(보통은 변수명으로 T많이 사용)
제네릭을 클래스로 사용할때는 각각의 자료명을 적어줘야한다...

위와 같은 식으로!!!
그리고 주의 사항으로 제네릭 클래스는 배열 생성시 new로 초기화 필수!!!!!!

다시금 복습하고 곱씹어봐도 제네릭은 어렵긴한데 좀 쉽게 생각하면 편하게 살아보자!!느낌이다
객체지향을 최대치로 활용하며 사용해보자 느낌?

와일드 카드 제네릭에 대한것!!!!
여러가지 법칙이 여전히 존재하는데 유의사항을 늘 생각하자
부모는 자식에게 속할수없다!!!!
제네릭의 다형성이라는게 아니라 이 문제 자체의 다형성을 인식해야한다!!!
참고는 https://github.com/jinyr1128/Java-Practice/tree/master/src/Sec07/chap03
이 깃을 참고해보자!

이제 다음강부터 쓰이게 될 클래스들을 만들어서 예제를 만들어 둘것이다.

Side, Unit, Attacker, Swordman, Knight, MagicKnight, Horse ,Main 으로 구성된 클래스들을 만들어 두었다.
Side : 각 진영을 표기하는 것이라서 열거형을 사용하였다.
Unit : 추상클래스로 작성이 되어있다. 진영이 지정되어있다!외부에서 가져갈수있도록 getter/setter 를 설정해줬다.
Attacker : 공격을 하는 무언가 이기 때문에 인터페이스로 해두고 그냥 기본 행동으로만 지정해놨다.
Swordman : 유닛을 상속(진영과 체력 존재) 어태커 적용
Knight : 소드맨을 상속(업그레이드 버젼) 추가 사항도 몇 작성 오버라이드를 하여 칼과 창을 놔둔다.
MagicKnight : 나이트를 상속 그리고 마나를 가지고 광역 공격을 가진다
Horse : 유닛을 제네릭으로 받아온다 말을 타면 체력이 늘어나는 기믹을 활용
Main : 각 클래스를 활용할수 있도록 만들어둔 클래스이다.
아래의 링크를 참고해보자!
https://github.com/jinyr1128/Java-Practice/tree/master/src/Sec07/chap04

Algorithm

추억 점수

문제 설명
사진들을 보며 추억에 젖어 있던 루는 사진별로 추억 점수를 매길려고 합니다. 사진 속에 나오는 인물의 그리움 점수를 모두 합산한 값이 해당 사진의 추억 점수가 됩니다. 예를 들어 사진 속 인물의 이름이 ["may", "kein", "kain"]이고 각 인물의 그리움 점수가 [5점, 10점, 1점]일 때 해당 사진의 추억 점수는 16(5 + 10 + 1)점이 됩니다. 다른 사진 속 인물의 이름이 ["kali", "mari", "don", "tony"]이고 ["kali", "mari", "don"]의 그리움 점수가 각각 [11점, 1점, 55점]]이고, "tony"는 그리움 점수가 없을 때, 이 사진의 추억 점수는 3명의 그리움 점수를 합한 67(11 + 1 + 55)점입니다.

그리워하는 사람의 이름을 담은 문자열 배열 name, 각 사람별 그리움 점수를 담은 정수 배열 yearning, 각 사진에 찍힌 인물의 이름을 담은 이차원 문자열 배열 photo가 매개변수로 주어질 때, 사진들의 추억 점수를 photo에 주어진 순서대로 배열에 담아 return하는 solution 함수를 완성해주세요.

제한사항
3 ≤ name의 길이 = yearning의 길이≤ 100
3 ≤ name의 원소의 길이 ≤ 7
name의 원소들은 알파벳 소문자로만 이루어져 있습니다.
name에는 중복된 값이 들어가지 않습니다.
1 ≤ yearning[i] ≤ 100
yearning[i]는 i번째 사람의 그리움 점수입니다.
3 ≤ photo의 길이 ≤ 100
1 ≤ photo[i]의 길이 ≤ 100
3 ≤ photo[i]의 원소(문자열)의 길이 ≤ 7
photo[i]의 원소들은 알파벳 소문자로만 이루어져 있습니다.
photo[i]의 원소들은 중복된 값이 들어가지 않습니다.

문제 이해를 위한 정리

이 문제는 사진들의 추억 점수를 계산하는 것인데 조건이 각 사진에는 여러 인물들이 있고, 각 인물은 그리움 점수를 가지고 있음. 한 사진의 추억 점수는 그 사진에 등장하는 모든 인물들의 그리움 점수를 합한 값
예를 들어, 'may'라는인물의 그리움 점수가 5점, 'kein'이라는 인물의 그리움 점수가 10점, 'kain'이라는 인물의 그리움 점수가 1점일 때, 이 세 명이 모두 등장하는 사진의 추억 점수는 16점(5 + 10 + 1)
그러나 만약 어떤 사진에 등장하는 특정 인물('tony')에 대한 그리움 점수가 주어지지 않았다면, 이 사람은 계산에서 제외즉 'tony'가 없던 것처럼 계산을 하는것이지
그럼 이 문제를 풀기 위해서는 해줘야하는게 뭘까
1. 각사진 등장민물 확인!
2.그리움 점수를 찾아 더하기
3.없으면 무시하고 다음으로 넘어가요~
4.다 끝내면 순서대로 배열~!!!!!!

내가 제출한 코드

import java.util.*;

class Solution {
    public int[] solution(String[] name, int[] yearning, String[][] photo) {
        // 그리움 점수를 저장할 맵을 생성
        Map<String, Integer> yearningMap = new HashMap<>();
        for (int i = 0; i < name.length; i++) {
            // 각 사람의 이름과 그리움 점수를 매핑하여 저장
            yearningMap.put(name[i], yearning[i]);
        }
        
        // 각 사진의 추억 점수를 저장할 배열을 생성
        int[] scores = new int[photo.length];
        
        for (int i = 0; i < photo.length; i++) {
            for (String person : photo[i]) {
                // 만약 사진 속 인물의 이름이 그리움 점수 맵에 있다면,
                if (yearningMap.containsKey(person)) {
                    // 해당 인물의 그리움 점수를 추억 점수에 더하기
                    scores[i] += yearningMap.get(person);
                }
            }
        }
        
        // 계산된 추억 점수가 담긴 배열을 반환
        return scores;
    }
}

이제는 광기의 주석이 몸에 베이게 하려고 주석을 다는중이다...위 코드의 작동은 이런식으로 이루어진다.
1.yearning 배열을 name 배열과 매칭하여 그리움 점수를 저장하는 yearningMap을 생성한다. 이 과정에서 각 사람의 이름이 키값이고, 해당 사람의 그리움 점수가 값으로 들어간다.

2.각 사진마다 인물들이 누구인지 확인하며 해당 인물들의 그리움점수를 합산하여 scores라는 배열에 저장한다. 이 과정에서 만약 특정 인물이 yearningMap에 없다면(즉, 해당 인물의 그리움점수가 없다면), 이는 무시되고 다음 인물로 넘어간다.

3.모든 계산이 끝나면, 각각의 사진에 대한 최종적인 추억점수가 담긴 scores배열을 반환한다

한문제 더 풀어보도록하자...

덧칠하기

문제 설명
어느 학교에 페인트가 칠해진 길이가 n미터인 벽이 있습니다. 벽에 동아리 · 학회 홍보나 회사 채용 공고 포스터 등을 게시하기 위해 테이프로 붙였다가 철거할 때 떼는 일이 많고 그 과정에서 페인트가 벗겨지곤 합니다. 페인트가 벗겨진 벽이 보기 흉해져 학교는 벽에 페인트를 덧칠하기로 했습니다.

넓은 벽 전체에 페인트를 새로 칠하는 대신, 구역을 나누어 일부만 페인트를 새로 칠 함으로써 예산을 아끼려 합니다. 이를 위해 벽을 1미터 길이의 구역 n개로 나누고, 각 구역에 왼쪽부터 순서대로 1번부터 n번까지 번호를 붙였습니다. 그리고 페인트를 다시 칠해야 할 구역들을 정했습니다.

벽에 페인트를 칠하는 롤러의 길이는 m미터이고, 롤러로 벽에 페인트를 한 번 칠하는 규칙은 다음과 같습니다.

롤러가 벽에서 벗어나면 안 됩니다.
구역의 일부분만 포함되도록 칠하면 안 됩니다.
즉, 롤러의 좌우측 끝을 구역의 경계선 혹은 벽의 좌우측 끝부분에 맞춘 후 롤러를 위아래로 움직이면서 벽을 칠합니다. 현재 페인트를 칠하는 구역들을 완전히 칠한 후 벽에서 롤러를 떼며, 이를 벽을 한 번 칠했다고 정의합니다.

한 구역에 페인트를 여러 번 칠해도 되고 다시 칠해야 할 구역이 아닌 곳에 페인트를 칠해도 되지만 다시 칠하기로 정한 구역은 적어도 한 번 페인트칠을 해야 합니다. 예산을 아끼기 위해 다시 칠할 구역을 정했듯 마찬가지로 롤러로 페인트칠을 하는 횟수를 최소화하려고 합니다.

정수 n, m과 다시 페인트를 칠하기로 정한 구역들의 번호가 담긴 정수 배열 section이 매개변수로 주어질 때 롤러로 페인트칠해야 하는 최소 횟수를 return 하는 solution 함수를 작성해 주세요.

제한사항
1 ≤ m ≤ n ≤ 100,000
1 ≤ section의 길이 ≤ n
1 ≤ section의 원소 ≤ n
section의 원소는 페인트를 다시 칠해야 하는 구역의 번호입니다.
section에서 같은 원소가 두 번 이상 나타나지 않습니다.
section의 원소는 오름차순으로 정렬되어 있습니다.

문제 이해를 위한 정리

이 문제는 페인트를 칠하는 최소횟수를 찾는거잖아?그치???? 대답!
그러면 벽은 N미터이고 1미터간격으로 나눠져있고 왼쪽부터 오른쪽으로 번호가 있어
페인트칠을 할 때 사용하는 롤러의 길이는 m미터이고 롤러로 한 번에 칠할 수 있는 범위는 연속된 m개의 구역이지...(어지럽지만 집중해서 따라와봐)
다시 페인트칠해야 하는 구역들의 목록(section 배열)이 주어진 상태이고 구역들을 모두 칠하면서 롤러를 사용한 최소 횟수를 찾아야 하는게 문제인거잖아! 후 요약이지?
예를 들어, 벽의 길이 n=8, 롤러의 길이 m=3, 다시 칠해야 하는 구역 section=[1,2,4]라고 가정해 보자고!

첫 번째로 롤러를 사용하여 1~3번 구역까지 칠하면 된다.(롤러 사용 횟수: 1) 그런 다음 4번 구역을 칠하기 위해 롤러를 다시 사용(롤러 사용 횟수: 2)
이 경우에는 총 두 번의 롤러 사용으로 모든 필요한 부분을 칠했잖아? Holy Moly~
주어진 조건에서 중요한 점은 "다시 칠하기로 정한 모든 구역은 적어도 한 번 이상 페인트칠 되어야 하며", "롤러로 한 번에 연속된 m개의 구역만을 칠했다고 인정한다" 라는 것이지 그렇게 코드를 짜보자고!

내가 제출한 코드

import java.util.*;

class Solution {
    public int solution(int n, int m, int[] section) {
        // 처음 칠해야하는 구역을 롤러로 칠하기 시작한다.
        int left = section[0]; // 롤러의 왼쪽 끝
        int right = Math.min(left + m - 1, n); // 롤러의 오른쪽 끝 (벽을 넘어가지 않도록 처리)
        
        // 페인트칠 횟수를 저장할 변수
        int answer = 1;
        
        for (int i = 1; i < section.length; i++) {
            if (section[i] > right) { 
                // 현재 구역이 롤러의 범위를 벗어나면 새롭게 페인트칠을 시작한다.
                left = section[i];
                right = Math.min(left + m - 1, n);
                
                // 페인트칠 횟수 증가
                answer++;
            }
            // 그렇지 않으면 이미 칠해진 구역에 포함되므로 아무 작업도 하지 않는다.
        }
        
        return answer;
    }
}

1.각 구역마다 확인하면서 현재 롤러의 범위 내에 속하지 않는다면 새롭게 페인트칠을 시작하는데 "새롭게 페인트칠"이란 해당 구역부터 m미터 만큼 오른쪽으로 이동하며 벽에 페인트를 촵촵!

2.만약 현재 확인하는 구역이 이미 롤러로 칠했던 부분에 속한다면 아무런 작업도 하지마! 왜냐하면 이미 해당 부분은 한 번 이상 페인트칠했기 때문이지...

3.모든 구역을 확인한 후 최종적으로 answer 변수에 저장된 값을 반환! 이 값은 전체 벽에서 몇 번의 동작으로 모든 필요한 부분들을 칠했는지 나타내는 값이 되는거지!!!!

회고

아 뭔가 월요일이라 집중도 잘 안되는 느낌이기도 하고 어수선한 기분도 드는데 그래도 알고리즘도 두개나 풀었고,,,고작...
그리고 제네릭과 래퍼 클래스에 대해서는 어느정도 확실한 자기만의 생각을 가지게 되었기떄문에 만족스러운 결과인것같다!!!!!!!

profile
개발이란 무엇인가..를 공부하는 거북이의 성장일기 🐢

0개의 댓글