본문 바로가기
♞ | 공부일지/♝ | TIL

[Android, 내일배움캠프] 공부일지(2024-07-18)

by immgga 2024. 7. 18.
오늘 공부한 내용 정리(2024년 7월 18일)

 

출처: unsplash.com

 

코드카타 문제풀이

조옮김(Bronze 1, 4732번, 마라톤)

문제 내용

 

문제 풀이 방법

음계가 주어질 때, 다음 줄에는 조옮김을 해야 하는 값(M)이 주어진다.

입력받은 음계를 M만큼 조옮김한 음계를 출력.

문제 설명에는 12 음계가 적혀 있고 저 음계로만 출력을 해야 한다.

입력받은 음계가 12 음계가 아닐 수 있다. 플랫(b)과 샵(#)의 관계를 이용하는 게 중요함.

 

 

해결 코드(스포 주의)

더보기
import java.io.BufferedReader
import java.io.InputStreamReader

private val musicalScales = listOf("A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#")

fun main() = with(BufferedReader(InputStreamReader(System.`in`))) {
    while (true) {
        var result = ""
        val input = readLine().split(" ")
        if (input[0] == "***") break
        val move = readLine().toInt()

        for (i in input.indices) {
            val scale = input[i]
            val scaleIndex = changeSameMusicalScalesIndex(scale)

            val resIndex = scaleIndex + move % 12
            if (move > 0) {
                if (resIndex >= musicalScales.size) {
                    val overFlowIndex = resIndex - musicalScales.lastIndex - 1
                    result += "${musicalScales[overFlowIndex]} "
                } else result += "${musicalScales[resIndex]} "
            } else {
                if (resIndex < 0) {
                    val overFlowIndex = resIndex + musicalScales.lastIndex + 1
                    result += "${musicalScales[overFlowIndex]} "
                } else result += "${musicalScales[resIndex]} "
            }
        }

        println(result)
    }
}

private fun changeSameMusicalScalesIndex(scale: String): Int {
    // Db == C#
    // B# == C
    val search = musicalScales.indexOf(scale)
    return if (search != -1) {
        search
    } else {
        val scaleFirst = scale.first().toString()
        val scaleFirstIndex = musicalScales.indexOf(scaleFirst)

        val sameScale = if (scale.last() == 'b') {
            if (scaleFirstIndex == 0) musicalScales.lastIndex
            else scaleFirstIndex - 1
        } else scaleFirstIndex + 1

        sameScale
    }
}

 

풀이 과정

무한히 입력받아야 해서 무한 반복문을 써주고, 음계 대신에 "***"가 들어 있으면 반복을 종료한다.

음계를 입력(input) 받고 나서 조옮김을 해야 하는 값(move)을 입력받는다.

 

그다음 음계의 개수만큼 반복해 주고 입력받은 음계를 12 음계 리스트(musicalScales)의 몇 번째 index에 들어 있는지 체크하기 위한 changeSameMusicalScalesIndex()를 호출한다.

 

함수 안에서는 파라미터 음계의 index 값을 musicalScales에서 찾아 주고,

입력받은 음계가 12 음계 리스트 안에 들어있는 경우는 그대로 return 하고, 그렇지 않은 경우는 플랫(b)이나 샵(#)이 들어있다는 뜻이므로 입력받은 음계의 첫 번째 문자의 index를 불러온다(scaleFirstIndex).

만약 마지막 문자가 b(플랫)이면 원본 음에 반음 낮다는 뜻이므로 scaleFirstIndex의 -1 또는 11(음계 리스트의 마지막 값)을 해준다.

위 조건에 해당하지 않으면, 원본에 비해 반음 높다는 뜻의 샵(#)이므로 scaleFirstIndex의 +1을 return 한다.

scaleFirstIndex + 1만 return 하는 이유는 12 음계에서 scaleFirstINdex가 0 또는 11이 되는 경우는 없기 때문.

 

음계를 변환한 값을 scaleIndex로 생성하고 최종 index는 scaleIndex + move % 12로 생성한다

12로 나누는 이유는 12의 배수 이상의 수가 들어왔을 때 몇 번째의 순환인지 체크하기 위함이다.

 

move가 음수냐 양수냐에 따라 출력 로직도 다르다.

resIndex가 musicalScales.size보다 크거나 같으면 resIndex - musicalScales.lastIndex에서 1을 빼거나 더한다.

빼는 경우는 move가 양수인 경우에는 1을 빼고 아닌 경우는 1을 더한다.

최종 index가 musicalScales에서 몇 번째의 값인지 불러와서 출력한다.

 

 

문제 해결 과정

12 음계만 고려하는 게 아닌, 플랫(b)과 샵(#)을 고려해 12 음계에서 동일한 음계로 바꿔 주고  이동된 음계의 index가 12 음계의 범위를 넘는지도 체크해야 하는 구현 문제이다.

 

 

삼각형 만들기(Silver 5, 2622번, 마라톤)

문제 내용

 

문제 풀이 방법

성냥개비의 개수가 주어질 때, 성냥개비를 모두 사용해 만들 수 있는 삼각형의 개수를 출력.

삼각형이 성립하기 위해서는 가장 큰 변이 나머지 2개의 변의 합보다 작아야 한다.

 

 

해결 코드(스포 주의)

더보기
import java.io.BufferedReader
import java.io.InputStreamReader
import kotlin.math.max

fun main() = with(BufferedReader(InputStreamReader(System.`in`))) {
    val size = readLine().toInt()
    var cnt = 0

    for (i in 1 .. size / 3 + 1) {
        for (j in i .. max(size - i, i)) {
            val left = size - i - j

            if (left < j) break
            if (left < i + j) cnt++
        }
    }

    println(cnt)
}

 

풀이 과정

성냥개비의 개수 size를 입력받고 삼각형의 개수인 cnt를 입력받는다.

 

바깥 반복 조건을 성냥의 개수의 3을 나눠서 +1 한 값까지 반복시킨다.

내부 반복은 i부터 size - i와 i 중 더 큰 값을 조건으로 지정한다.

최대한 중복을 줄이기 위해 for의 범위를 설정해 주었다.

 

만약 left(i와 j를 뺀 나머지 값)가 j 보다 작으면 break 한다.

그러면 가장 긴 변이 left가 된다.

left가 i + j보다 작은 경우에만 cnt를 늘려 준다.

 

반복 종료 후 cnt를 출력한다.

 

 

문제 해결 과정

반복문의 범위 설정을 생각해봐야 하는 문제이다.

mutableSet을 이용해서 모든 경우를 체크하는 방법은 불가능하다(메모리 초과 발생)

for문과 if로 최대한 중복을 제거해 가면서 서치를 해주어야 한다.

 

 

주특기 숙련 강화 강의

주특기 숙련 강화 강의

Fragment 통신, Repository 패턴

Repository 패턴

앱의 규모가 점점 커짐에 따라 개발자는 이제 코드를 효율적으로 짜야하는 방법을 생각해보아야 한다.

역할별로 파일을 분류하고 패키지화해 효율적으로 관리해야 한다.

그중의 하나가 Repository를 사용하는 Repository 패턴이다.

 

 

Data의 출처(network, local cache) data(room, shared preference, dataStore)에 관계없이 동일한 인터페이스로 데이터에 접근할 수 있도록 하는 패턴.

Data Layer를 캡슐화를 시키는 것이 Repository 패턴의 주된 목적이다.
Data Layer와 Presentation(view) Layer의 의존성이 줄어든다.

Repository -> DataSource 의존성 회피
의존성을 없애게 되면 dataSource 변경 시(network 코드를 변경함) repository에는 영향이 없다.

Presentation Layer에는 Data Layer에 직접 접근하지 않아서 새로운 데이터 추가가 쉽다.

Presentation Layer에는 Repository에 데이터를 요청하기만 하면 돼서 일관된 Interface로 데이터를 요청할 수 있다.

 

관심사를 분리해서 서로의 의존성을 분리해서 유지 보수성을 높여 주었다.

나중에 clean architecture를 사용하기 위한 기초 과정임.

 

domain을 구현하는 경우

꼭 구현해야 하는 건 아님. 현재까지도 갑론을박이 있음.

자신의 상황에 맞게 구현하는 게 맞는 듯.

 

 

Singleton 패턴

객체에 대한 하나의 인스턴스만 필요할 때, 하나의 인스턴스를 재사용하기 위해 사용.

kotlin의 Object class를 주로 이용한다.

클래스를 정의함과 동시에 객체를 생성함.

 

singleton 객체를 만들 때는 INSTANCE에서 클래스 자체를 return 하도록 만들어야 한다. 초기값은 null로 설정한다.

INSTANCE를 불러오기 위한 함수를 만들어 주어야 한다.

fun getInstance(): DataType {
    return INSTANCE
}

 

 

수준별 학습반 개인 과제 v3(standard class)

검색 화면 구현

공부 내용 간단 정리

검색을 통해 v3의 필수 구현 항목인 Fragment끼리 데이터 전달을 만드려고 한다.

그전에 검색 화면을 만들어 주었다.

RecyclerView로 제작했는데, 다중 viewType RecyclerView Adapter로 구성했다.

이전에 추천 페이지에서 사용했던 방법과 동일하기 때문에 자세한 설명은 생략한다.

 

최종 구현 사진

 


 

오늘 공부 내용 정리 및 회고

Fragment끼리 데이터를 전달하기 위한 UI를 구성했다.

내일은 Fragment 데이터 전달을 적용해 볼 예정이다.

그리고 Repository 패턴과 MVVM 패턴을 적용을 해볼까?

안 쓴 지 너무 오래돼서 공부를 다시 해야 할 것 같다.

728x90