티스토리 뷰
코드카타
카펫
문제
카펫은 갈색 타일이 노란색 타일을 둘러싼 형태여야 한다.
갈색 타일 수와 노란색 타일 수가 매개변수로 주어질 때
해당 카펫의 가로, 세로 크기를 리스트 담아 반환하는 문제이다.
제한 사항
카펫의 가로 길이는 세로길이보다 같거나 길다고 언급되어있다.
입출력 예시
카펫의 크기가 n * m 일 때, brown은 2(n + m) - 4의 값을 가진다.
이는 올바른 카펫 형태를 검사하는 조건에 해당한다.
풀이 과정
해당 문제를 해결하려면 (가로, 세로)형태의 경우의 수를 찾아야한다.
가로와 세로를 곱한 값은 총 타일 개수에 해당한다.
만약에 brown = 10, yellow = 2 라고 했을 때 12의 약수를 구해 짝을 지으면
(1, 12) , (2, 6) , (3, 4) , (4, 3) , (6, 2) , (12, 1) 와 같은 경우의 수가 나온다.
가로의 길이가 세로보다 길거나 같기에 (1, 12) , (2, 6) , (3, 4)의 경우의 수는 제외힌다.
또한, 가운데에 노란색 격자가 위치하기 위해선 가로, 세로 길이가
모두 3 이상이여야하기에 (6, 2) , (12, 1)의 경우의 수는 제외하여
최종적으로 (4, 3)이 카펫의 가로 세로 길이가 된다.
풀이
class Solution {
fun solution(brown: Int, yellow: Int): List<Int> {
var res = mutableListOf<Int>() // 결과 리스트 초기화
val tiles = brown + yellow // 전체 타일 개수
// (카펫 최소 높이 ~ 타일 개수) 범위 순회
for (h in 3..tiles) {
// 전체 타일 수가 높이로 나누어 떨어지면
if (tiles % h == 0) {
// 너비 계산 후
val w = tiles / h
// 갈색 타일 수가 조건에 맞다면
if (2 * (w + h) - 4 == brown) {
// 가로 세로 크기를 리스트에 추가 후 반복문 종료
res.add(w)
res.add(h)
break
}
}
}
return res
}
}
카펫의 크기는 (너비 x 높이)에 해당하므로 카펫의 높이가 타일개수와 나누어 떨어진다면
카펫의 너비는 타일개수에서 카펫의 높이를 나눈 값이 된다.
Kotlin 문법 강의 4주차 정리
접근 제한자
접근 제한자란?
객체 지향 프로그래밍에서 클래스의 변수 및 메서드에 대한
접근 권한을 제어하는 데 사용되는 키워드들이다.
위치 용어 정리
프로젝트: 최상단 개념으로, <모듈, 패키지, 클래스>를 포함한다.
모듈: 프로젝트 아래의 개념으로 <패키지, 클래스>를 포함한다.
패키지: 모듈 아래의 개념으로, <클래스>를 포함한다.
Kotlin 접근 제한자의 종류
public: 어디서나 접근할 수 있다. (접근 제한자를 명시하지 않으면 public으로 선언됨)
private: 동일한 클래스 내부에서만 접근할 수 있다.
internal: 같은 모듈 내부에서만 접근할 수 있다.
protected: 기본적으로 private이지만 상속을 받은경우에 타 모듈에서 접근할 수 있다.
접근제한자 쓰는 이유
접근 제한자를 쓰는 이유는 데이터의 무분별한 접근을 막기 위해서이다.
클래스들 간의 접근제어를 정의하면 추후에 유지보수가 용이해진다.
예제 코드
open class AccessModifier {
val a = 1
private val b = 2
internal val c = 3
protected val d = 4
}
class UseProtected : AccessModifier(){
val protectedVal = d
}
fun main() {
val accessModifier = AccessModifier()
val useProtected = UseProtected()
println(accessModifier.a)
println(accessModifier.c)
println(useProtected.protectedVal)
}
b는 private로 선언되어 있기에 main에서 출력할 수 없다.
protected로 선언된 d를 출력하려면 해당 프로퍼티가 위치한 클래스를
상속하는 클래스를 만들어 그 클래스의 public으로 선언된 멤버를 호출해야한다.
간단 정리
간단한 프로젝트 할 땐 public과 private개념정도만 알고 있으면 된다.
public은 클래스에서 갖다 쓸 멤버를 선언할 떄 쓰고,
private는 클래스 내에서만 쓸 멤버를 선언할 떄 쓴다.
예외처리의 활용
"예외"의 정의
에러에는 프로그램을 실행하기 전 알 수 있는 컴파일 에러와,
프로그램 실행 도중에 발생하는 런타임 에러, 즉 예외가 존재한다.
예외 처리란?
실행 도중 예외가 발생하는 것을 막기 위해 진행하는 것이 예외 처리이다.
코틀린에서는 try-catch와 throw로 예외처리를 진행한다.
try-catch
fun method1() {
try {
예외가 발생할 가능성이 존재하는 코드
} catch(예외종류) {
예외가 발생했을때 처리할 코드
}
}
try에는 예외 발생 가능성이 있는 코드를
catch에는 예외 처리를 진행할 코드를 작성한다.
throw
fun method2(num1:Int) {
if(num1 > 10) {
throw 예외종류
}
}
throw는 예외를 던질 때 사용하는 키워드이다.
예외가 발생했을 때의 처리는 따로 하지 않는다.
예외 처리가 필요한 이유
프로그램이 도중에 종료되는 것을 방지하기 위해서이다.
예외처리를 진행하면 프로그램의 안정성을 높일 수 있다.
예외 확인
fun main() {
print(1/0)
}
나눗셈 연산을 할 때 제수가 0이라면 예외가 발생한다.
콘솔창에서 해당 예외가 무슨 예외에 해당하는지 확인해준다.
예외처리 개념
fun divide(a: Int, b: Int): Int {
if (b == 0) {
throw ArithmeticException("0으로 나눌 수 없습니다.")
}
return a / b
}
fun main() {
val a = 10
val b = 0
try {
val result = divide(a, b)
println("나눗셈 결과: $result")
} catch (e: ArithmeticException) {
println("나눗셈 오류 발생: ${e.message}")
} finally {
println("나눗셈 연산 완료")
}
}
divdie 함수에서 ArithmeticException라는 예외가 발생했을 때
그 예외의 메시지를 throw로 정의해준다.
try 블럭은 예외가 발생하지 않았을 때 실행이 된다.
catch 블럭은 지정한 예외가 발생하였을 때 실행이 된다.
finally 블럭은 예외 발생 여부와 상관없이 실행이 된다.
b(제수)는 0이므로 main()에서는 catch와 finally 블럭만을 실행시킨다.
예외처리 예시
// 숫자를 입력해야하는데 실수로 문자를 입력했을때의 예외를 처리
while(true) {
try {
var num1 = readLine()!!.toInt()
println("내가 입력한 숫자는 ${num1}입니다")
break
} catch(e:java.lang.NumberFormatException) {
println("숫자를 입력하세요")
}
}
try 블럭이 실행될 때 숫자를 입력할 때까지,
즉 예외가 발생하지 않을 때까지 계속해서 입력을 받는다.
지연초기화
지연초기화란?
코틀린에서는 클래스를 설계할 때 안정성을 위해 반드시 변수의 값을 초기화하도록 한다.
이 떄 초기값을 정의하기 난처하다면 나중에 대입하기 위해 지연초기화 키워드를 사용한다.
저사양으로 제한되어있는 환경에서 메모리를 더욱 효율적으로 사용하기 위해 쓰는 키워드이다.
지연초기화 문법
fun main() {
val student = Student()
student.name = "주영"
println("${student.name}의 성별은 ${student.gender}이다.")
}
class Student {
lateinit var name: String
val gender by lazy { "남성" }
}
변수를 초기화할 때는 lateinit을, 상수를 초기화할 때는 lazy 키워드를 사용한다.
변수를 지원초기화하려면 클래스 내에서 변수의 타입을 지정해줘야하고
변수를 사용하기 전에 해당 변수를 타입에 맞는 값으로 초기화 해줘야 한다.
지원초기화 된 상수는 해당 상수가 호출되는 시점에서 지정한 값으로 초기화 된다.
초기화 확인
fun main() {
val student = Student()
student.studentInfo()
}
class Student {
lateinit var name: String
val gender by lazy { "남성" }
fun studentInfo() {
if(this::name.isInitialized) {
println("${name}의 성별은 ${gender}이다.")
} else {
println("name 변수를 초기화해주세요.")
}
}
}
isInitialized를 활용해서 변수가 초기화 되었는지 확인할 수 있다.
해당 문법을 사용할 땐 값이 아니라 참조형태로 사용해야하므로 this:: 를 앞에 붙인다.
널 세이프티
널 세이프티란?
Null 예외를 방지하기 위해 쓰는 문법이다.
코틀린은 안전한 설계를 위해 자료형에 Null 여부를 명시할 수 있다.
널 세이프티 키워드
!! => Null 아님을 보장한다.
?. => Null이 아닐때만 참조하는 메소드를 실행한다.
?: => 값이 Null이면 설정해둔 다른 값으로 초기화한다.
배열
배열이란?
동일한 자료형의 요소들이 메모리 상에서 연속적으로 나열된 자료구조이다.
반복적으로 변수에 접근할 필요가 있는 로직을 구현할 때 사용한다.
배열 개념
// arrayOf메소드를 호출하면 배열을 리턴한다
var arr = arrayOf(1,2,3,4,5)
// 배열요소를 모두 출력한다
println(Arrays.toString(arr))
// 배열의 첫번째 요소에 저장된 값을 출력한다
// 배열의 인덱스는 0부터 시작하고 선언한 배열 크기는 5이므로 0 ~ 4 번지에 접근 가능하다
// 배열의 n번지값, 즉 배열의 요소는 하나의 변수로 취급이 된다
println(arr[0])
컬렉션
컬렉션이란?
개발에 유용한 자료구조를 지원하는 것으로,
코틀린에서는 리스트, 맵, 집합 자료구조를 지원한다.
배열과 달리 크기가 정해져있지 않아 동적으로 값을 추가할 수 있다.
List
// 불변형 리스트
val scores1 = listOf(1, 2, 3)
// 가변형 리스트
val scores2 = mutableListOf(1, 2, 3)
불변형 리스트는 한 번 생성된 이후에는 요소를 추가, 삭제, 변경할 수 없지만,
가변형 리스트는 생성된 후에도 요소를 추가, 삭제, 변경할 수 있다.
Map
fun main() {
// 불변형 맵으로 변수명[키]로 데이터에 접근할 수 있다
var scoreInfo1 = mapOf("kor" to 94, "math" to 90, "eng" to 92)
println(scoreInfo1["kor"])
// 가변형 맵으로 데이터 접근 뿐 아니라 키값의 변경 또한 가능하다
var scoreInfo2 = mutableMapOf("kor" to 94, "math" to 90)
scoreInfo2["eng"] = 92
println(scoreInfo2["eng"])
// 맵의 키와 값을 동시에 추출해서 사용할 수 있다
for((k,v) in scoreInfo2) {
println("${k}의 값은 ${v}입니다")
}
}
코틀린에서 Map 자료형은 키(key)와 값(value)의 쌍으로 데이터를 저장하고 관리할 때 사용한다.
이 자료형은 특정 키를 통해 해당 키에 연결된 값을 빠르게 찾아낼 수 있다.
Set
fun main() {
// 귀여운 새의 집합
val birdSet = setOf("닭", "참새", "비둘기", "물오리")
// 날 수 있는 새의 집합
val flyBirdSet = setOf("참새", "비둘기", "까치")
// 모든 새의 집합 (합집합)
val unionBirdSet = birdSet.union(flyBirdSet)
// 귀엽고 날 수 있는 새의 집합 (교집합)
val intersectBirdSet = birdSet.intersect(flyBirdSet)
// 귀여운 새들 중에서 날 수 없는 새의 조합 (차집합)
val subtractBirdSet = birdSet.subtract(flyBirdSet)
}
Set은 순서가 존재하지 않고 중복되는 요소가 없는 집합 자료형이다
다른 컬렉션들은 요소를 찾는데에 집중하지만, Set은 요소가 존재하는지에 집중한다
Set을 이용해 집합 간의 교집합, 차집합, 합집합을 구할 수 있다.
'내일배움캠프 > Android 국비지원' 카테고리의 다른 글
TIL 18일차 (N개의 최소공배수 - Kotlin | 키오스크 Lv1 ~ Lv3 구현) (0) | 2024.06.13 |
---|---|
TIL 17일차 (예상 대진표 - Kotlin | 코틀린 심화문법 정리 2) (0) | 2024.06.12 |
TIL 15일차 (피보나치 수 - Kotlin | 계산기 구현 과제 피드백 반영) (0) | 2024.06.10 |
TIL 14일차 (이진 변환 반복하기 - Kotlin | 안드로이드 스튜디오 계산기 만들기) (1) | 2024.06.09 |
TIL 13일차 (JadenCase 문자열 만들기 - Kotlin | 연산자 간의 우선순위를 고려한 연산 로직짜기) (0) | 2024.06.08 |