[TIL][내일배움캠프]

[내일배움캠프][TIL] 23.12.05 (화) - 푸드 파이트 대회, 객체지향 프로그래밍 심화

kimlaurant 2023. 12. 5. 19:48
1. 코드카타

 

오늘 푼 알고리즘 문제는 '푸드 파이트 대회' 이다.

 

 푸드 파이트 대회

 

흠. 어째 시간이 갈수록 문제 길이가 점점 늘어나는 것 같냐.

이러다 나중에는 문제 읽는 데만 한세월 걸리는 거 아닌가 싶네.

 

일단 문제부터 파악해보자.

 

food 배열의 0번은 물이고, 이건 가운데에 하나 놓아야 하기 때문에 무조건 1이다.

그 다음 양 끝쪽에 칼로리가 적은 음식 순서대로 균등하게 나눠서 배치해야 한다. (당연히 2로 나눈 다음 생기는 나머지는 버린다.)

 

답을 구하는 방법은 여러가지겠지만, 나는 다음과 같은 방법을 사용하였다.

 

class Solution {
    fun solution(food: IntArray): String {
        var answer: String = ""
        var foodLine = intArrayOf()
        
        for (i in 1 until food.size){
            for (j in 0 until food[i]/2) {
                foodLine += i
            }
        }
        
        answer = foodLine.joinToString("") + "0" + foodLine.reversed().joinToString("")
        
        return answer
    }
}

 

우선, 0번은 사용하지 않으니 1번부터 시작한다.

그리고 1번 음식부터 각각 2로 나눈 수만큼 foodLine Array에 일렬로 나열한다.

 

그렇게 나온 값을 joinToString(" ")을 통해서 붙이고, 중간에 0을 추가한 뒤 foodLine Array를 반대로 뒤집어서 이어붙이면 완성.

 

 

2. 객체지향 프로그래밍 심화

 

이제 이 Kotlin 문법도 어느정도 익숙해질 무렵이지만, 아직까지 객체지향 프로그래밍 쪽은 더 배워야할 것이 많다.

 

그리하여 이번에는 심화 부분을 정리해보기로 했다.

 

접근제한자
  1. public : 언제 어디서든지 접근 가능한 상태. 특별히 명시하지 않으면 보통은 public이다.
  2. private : 동일한 클래스 내부에서만 접근 가능
  3. internal : 같은 모듈 내부에서만 접근 가능
  4. protected : 기본적으로는 private와 동일한 특징을 지니지만, 상속을 받은 경우에 한해서 타 모듈에서 접근 가능

이 때, 프로젝트(project) > 모듈 (module) > 패키지(package) > 클래스(class) 이다.

(즉, private를 붙이면 다른 모듈에서는 접근할 수 없음)

 

ex)

class AccessTestClass {
    public var a:Int = 1
    var b = 2
    private var c = 3
    internal var d = 4
    protected var e = 5
    
    public fun publicTest() {
        println("public 입니다")
    }

    fun publicTest2() {
        println("public 입니다")
    }

    private fun privateTest() {
        println("private 입니다")
    }

    internal fun internalTest() {
        println("internal 입니다")
    }

    protected fun protectedTest() {
        println("protected 입니다")
    }
}

 

 

예외 처리

 

프로그램을 실행시키다보면 여러 종류의 예외가 발생하며, 이 경우 프로그램이 비정상적으로 종료될 수 있다.

이를 사전에 방지하고자 미리 코드로 처리하는 것을 바로 예외 처리라고 한다.

 

○ 예외 처리 방법

 1) try-catch : 예외가 발생할 가능성이 존재하는 코드를 try에 넣고, catch를 통해서 그 예외가 발생했을 때 사용할 코드를 대신 실행시킨다. 기록을 남기는 데에도 사용.

fun method1() {
	try {
		예외가 발생할 가능성이 존재하는 코드
	} catch(예외종류) {
		예외가 발생했을때 처리할 코드
	}
}

 

2) throw : 예외를 특별히 코드로 처리하지는 않고 단지 오류가 나지 않게만 한다.

fun method1(num1:Int) {
	if(num1 > 10) {
		throw 예외종류
	}
}

 

ex)

while(true) {
	try {
		var num1 = readLine()!!.toInt()
		println("내가 입력한 숫자는 ${num1}입니다")
		break
	}
    catch(e:java.lang.NumberFormatException) {
	println("숫자를 입력하세요")
	}
}

 

 

지연 초기화

 

Kotlin에서는 클래스를 설계할 때, 안정성을 위해서 변수를 초기화하는 것을 권장하는데 이런 초기화를 지연시키는 행위를 지연 초기화라 한다.

 

초기의 값을 정의하기 어려울 때 나중에 대입하기 위해서 이 문법을 사용하는 경우가 많다.

 

○ 지연 초기화의 종류

  • lateinit : 변수
  • lazy : 상수

ex)

변수의 지연 초기화

fun main(){
    var s1 = Student()
    s1.name = "참새"
    s1.displayInfo()

    s1.age = 10
    s1.displayInfo()
}

class Student {
    lateinit var name:String
    var age:Int = 0

    fun displayInfo() {
        println("이름은: ${name} 입니다.")
        println("나이는: ${age} 입니다.")
    }
}

 

상수의 지연 초기화

fun main(){
    var s1 = Student()
    s1.name = "참새"
    s1.displayInfo()

    s1.age = 10
    s1.displayInfo()
}

class Student {
    lateinit var name:String
    var age:Int = 0
    val address: String by lazy {
        println("address 초기화")
        "seoul"
    }

    fun displayInfo() {
        println("이름은: ${name} 입니다.")
        println("나이는: ${age} 입니다.")
        println("주소는: ${address} 입니다.")
    }
}

 

 

널 세이프티 (Null safety)

 

프로그램 실행 도중 Null값이 뜨게 되면 치명적인 오류가 발생할 수 있으므로, 이를 처리하는 것이 중요하다. 이러한 과정을 널 세이프티(Null safety)라고 한다.

 

? : Null값이 발생할 수 있는 경우 사용. Null값을 저장할 수 있음.

!! : Null값이 절대 발생하지 않는다고 보장. 확실하지 않으면 사용 자제.
?. : Null값인지 아닌지 판단하고 Null값이 아닐 경우 실행.

?: : Null이 출력되는것을 막고싶을 때, Null 대신에 다른 문자열을 출력하게 만들어줌.

 

 

배열 (Array)

 

변수들에 순서를 매겨서 연속적으로 활용할 수 있는 문법.

 

본래는 여러 개의 변수를 선언하려면 따로따로 선언해야 하는데(num1, num2, num3, ...) 배열을 사용하면 이러한 번거로움을 줄일 수 있다.

 

// arrayOf메소드를 호출하면 배열을 리턴
// 1,2,3,4,5 각각을 저장한 변수 5개를 배열형태로 arr에 저장
var arr = arrayOf(1, 2, 3, 4, 5)

// arr[0]은 하나의 변수로 취급 가능
// arr은 0~4번방(인덱스)까지 접근 가능
arr[0] = 1

 

 

컬렉션 (Collection)

 

배열과는 다르게 공간의 크기를 처음 크기로 고정하지 않고 임의의 개수를 담을 수 있기 때문에 동적 배열이라고도 한다.

 

○ 컬렉션의 종류

 1) 리스트(list) : 인덱스가 존재하고, 중복 가능한 값을 가지고 있는 컬렉션.

  • 읽기 전용 : listOf(값1, 값2, 값3)
  • 수정 가능 : mutableListOf(값1, 값2, 값3)
  • 자료형 선언 : mutableListOf<자료형>(값1, 값2, 값3)
  • list에 값 추가 : list명.add(추가할 값)
  • list 값 수정 : list명.get(인덱스, 수정할 값)
  • list 값 제거 : list명.removeAt(인덱스)

 

 2) 맵(map) : 키와 값을 가지고 있는 컬렉션

  • 읽기 전용 : mapOf(키1 to 값1, 키2 to 값2, 키3 to 값3)
  • 수정 가능 : mutableMapOf(키1 to 값1, 키2 to 값2, 키3 to 값3)

 

 3) 셋(set) : 인덱스가 없고, 중복 불가능한 값을 가지고 있는 컬렉션.

  • 읽기 전용 : setOf(값1, 값2, 값3)
  • 수정 가능 : mutableSetOf(값1, 값2, 값3)

 

 4) 집합

  • 합집합 : union()
  • 교집합 : intersect()
  • 차집합 : subtract()