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

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

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

 

출처: unsplash.com

 

코드카타 문제풀이

APC2shake!(Silver 5, 31925번, 마라톤)

문제 내용

 

문제 풀이 방법

참가자 명단에서(N) 위 글의 조건을 만족하는 참가자들의 이름을 사전순으로 정렬해서 출력.

 

 

해결 코드(스포 주의)

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

fun main() = with(BufferedReader(InputStreamReader(System.`in`))) {
    val students = readLine().toInt()
    var studentList = mutableListOf<List<String>>()

    for (i in 0 until students) {
        // 입력값
        // 이름, 재학 여부, 역대 ICPC 수상 여부, 역대 shake! 최고 성적, 2024 APC 성적
        val studentInfo = readLine().split(" ")
        studentList.add(studentInfo)
    }

    studentList = studentList
        .filter { it[1] == "jaehak" && it[2] == "notyet" }
        .filter { it[3].toInt() > 3 || it[3].toInt() == -1 }
        .toMutableList()

    if (studentList.size >= 10) {
        studentList.sortBy { it.last().toInt() }
        studentList = studentList.subList(0, 10)
    }
    println(studentList.size)

    studentList.sortBy { it[0] }
    println(studentList.joinToString("\n") { it[0] })
}

 

풀이 과정

참가자 정보를 담을 2중 리스트 studentList를 생성한다.

입력받은 studentInfo를 studentList에 넣어 준다.

 

studentList에서 3가지의 조건을 만족하도록 리스트를 filtering 한다.

첫 번째 filter에서는 재학 여부가 재학생인 경우와 ICPC 수상 여부가 없는 데이터만 뽑도록 하고

두 번째 filter에서는 역대 shake! 최고 성적이 3보다 큰 값들과 -1인 값들만 걸러 준다. 순위이므로 3위보다 큰 값이어야 한다.

 

값을 거른 후 값의 길이가 10이 넘어가면 4번째 조건을 고려해야 한다.

마지막 값인 2024 APC 성적을 기준으로 오름차순 정렬을 해준다(순위 순으로 정렬이 된다).

정렬된 리스트에서 상위 10개를 제외한 모든 리스트 데이터를 버린다.

 

결과 리스트의 size와 리스트의 0번째 값인 이름을 기준으로 정렬해 준 결과를 출력한다.

 

 

문제 해결 과정

문제 자체는 어렵지 않았음.

조건을 만족하도록 리스트를 필터링하는 것이 다다.

순위 관련해서 필터링을 할 때는 조금 신경을 써줘야 한다. 실수하기 쉽다.

 

 

행운의 티켓(Silver 4, 1639번, 마라톤)

문제 내용

 

문제 풀이 방법

숫자로 이루어진 문자열 s가 있을 때, s에서 행운의 티켓 규칙을 만족하는 부분 문자열의 최대 길이를 출력.

행운의 티켓 규칙은 2 x N(2의 배수 자리)의 숫자로 이루어지는 티켓이다. 왼쪽 N자리와 오른쪽 N자리의 합이 일치하면 행운의 티켓이 된다.

 

 

해결 코드(스포 주의)

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

fun main() = with(BufferedReader(InputStreamReader(System.`in`))) {
    val ticket = readLine()
    var result = 0

    for (size in 1 until ticket.length / 2 + 1) {

        for (i in 0 until ticket.length - size) {
            if (i + size + size <= ticket.length) {
                val first = ticket.substring(i, size + i)
                val last = ticket.substring(i + size, i + size + size)
                val firstSum = first.sumOf { it.digitToInt() }
                val lastSum = last.sumOf { it.digitToInt() }

                if (firstSum == lastSum) result = max(result, first.length + last.length)
            }
        }
    }

    println(result)
}

 

풀이 과정

먼저 티켓 문자열(ticket)을 입력받는다.

다음으로 행운의 티켓 문자열의 길이를 저장할 result 변수를 만들어 준다.

 

나는 다음과 같은 방법으로 행운의 티켓 번호를 판단해 주었다.

ticket = 123231일 때,
비교 순서
1, 2
2, 3
3, 2
2, 3
3, 1
12, 32
23, 23
32, 31
123, 231

위와 같이 비교를 할 것이기 때문에 굳이 ticket의 length만큼 돌 필요가 없다고 생각해서

반복 횟수는 티켓 문자열의 length의 절반만 한다.

 

내부 반복문의 반복 횟수는 ticket - size 만큼 진행해 준다.

내부 반복문의 범위 안에서 티켓 번호를 만들 수 있는 경우의 수를 모두 체크해서 firstSum과 lastSum이 같은 경우는 result에 result와 first의 길이와 last의 길이의 합 중 더 큰 값을 대입해 준다.

 

반복 종료 후 최종 result를 출력한다.

 

 

문제 해결 과정

바깥의 반복에서는 행운의 티켓 자릿수를 설정하고 내부 for문에서는 문자열을 돌면서 자릿수에 맞게 왼쪽 문자열 와 오른쪽 문자열을 구해서 행운의 티켓 자릿수를 구하는 문제이다.

생각을 좀 해봐야 하는 문제였다. 문자열을 다루는 문제라 실수하기 쉬운 점도 고려해야 한다.

 

 

수준별 학습반 강의

수준별 학습반(standard class)

RecyclerView에 클릭 이벤트 추가하기.

RecyclerView에 클릭 이벤트를 추가하는 방법은 2가지가 있다

람다 사용
인터페이스 사용

 

인터페이스를 사용한 클릭 이벤트 사용

인터페이스는 클래스가 구현해야 하는 메서드들의 집합을 정의하는 틀이다.
인터페이스는 구현을 포함하지 않고, 어떤 동작을 취해야 하는지 명시만 해야 함.
여려 클래스에 공통된 동작을 강제하기 위해 사용.
구현할 메서드를 명시해서 클래스가 특정 기능을 반드시 구현하게 함.
재사용성이 좋아요!

 

adapter 안 또는 외부에 interface를 생성해 onclick 이벤트를 적용할 함수를 넣어 주고, setonClickListener 안에 인터페이스 함수를 사용함.

 

 

람다를 사용한 클릭 이벤트 사용

익명 함수(Anonymous Function)로 일종의 함수 표현식
코드 블록을 변수처럼 전달
간단한 일회성 동작이나 이벤트 처리를 위해 사용.
코드가 간결해지고, 함수나 메서드로 전달 가능.

 

adapter의 파라미터에 클릭 이벤트를 넣어 주고(고차 함수 사용) setonClickListener에 파라미터를 넣어 주고 adapter를 사용할 때, 이벤트 파라미터에 쓸 동작을 넣어 준다.

 

ListAdapter

기존의 adapter는 데이터를 수정할 때 오류가 발생하기 쉬웠다. 그래서 구글에서 ListAdapter를 구현하게 되었다.

또한 데이터를 업데이트하면 모든 데이터를 갱신하기 때문에 성능에 크게 좋지 않았다.

 

ListAdapter는 데이터를 업데이트할 때마다 변경된 부분만 갱신을 할 수 있도록 수정해 준다.
리스트 변경을 감지해 준다.
내장된 DiffUtil을 통한 자동 데이터 변경 감지 및 UI 갱신, 보다 효율적인 데이터 관리.
하지만 커스터마이징이 상대적으로 제한적임. 초보자에게는 복잡할 수 있다.

 

ListAdapter에서는 기존의 Adapter에 추가적으로 areItemsTheSame(), areContentsTheSame() 함수를 직접 구현해 주어야 함.

그리고 onBindViewHolder에 getItem(position) 전용 함수를 이용해 특정 position 번째의 데이터를 불러올 수 있다.

 

작동 순서

areItemsTheSame()이 먼저 수행된다. 이 함수는 item의 id(item의 고유 값)가 같은지 확인한다. 이 함수는 수십만 개의 아이템이 있을 때 빛을 발한다(성능 향상에 도움을 줌).
areContentTheSame()은 areItemsTheSame에서 걸러진 아이템들 중 값이 같은지 확인한다. 다른 값이 존재한다면 그 값만 교체해 준다.

 

 

개인 공부

앱 개발 숙련 개인 과제

개인 과제 필수 구현 사항 모두 완료

오늘 개발한 내용은 상품 정보 페이지 구현이다.

여태까지 했던 평범한 화면 구성이었으므로 자세한 설명은 생략한다 ㅋ.

상품 정보 페이지에는 뒤로 가기 버튼, 하단의 가격 정보를 제외한 데이터들이 스크롤이 가능하도록 구현해야 한다.

화면 구성 결과부터 봐보자. xml 코드는 생략한다.

다음과 같이 구현해 주었다.

상품 정보를 이전의 MainActivity에서 불러온 데이터 클래스를 이용해 구현했다.

 

개인 과제 선택 구현 Lv.1 구현

선택 과제 Lv.1 구현 사항은 메인 화면에서 스크롤이 되면 floating button이 활성화(visible)되고 스크롤이 최상단이면 비활성화되도록 구현하는 것과

floating button 클릭 시 스크롤을 최상단으로 이동하고, 버튼 클릭 시 버튼의 색을 변하게 하는 게 Lv.1 구현 사항이다.

 

애니메이션은 fade in/out을 사용해 주었다.

코드는 스크롤 여부 확인 및 스크롤 위로 올리는 코드만 보여주겠다.

스크롤 감지는 따로 콜백을 만들어 주었다.

binding.mainRecyclerViewGoods.addOnScrollListener(object : RecyclerView.OnScrollListener() {
    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        if (!recyclerView.canScrollVertically(-1)) {
            binding.mainFloatingActionUpscrollButton.animation = AnimationUtils.loadAnimation(this@MainActivity, R.anim.fade_out)
            binding.mainFloatingActionUpscrollButton.visibility = View.GONE
        } else {
            binding.mainFloatingActionUpscrollButton.animation = AnimationUtils.loadAnimation(this@MainActivity, R.anim.fade_in)
            binding.mainFloatingActionUpscrollButton.visibility = View.VISIBLE
        }
    }
})

onScrolled의 내부의 조건에서 canScrollVertically() 함수에서 스크롤이 조금이라도 되면 false state로 변하게 되어서 floating button이 visible 되면서 fade in 애니메이션을 적용했다.

그렇지 않고 스크롤 상태가 최상단이면 floating button을 gone 시키고 fade out 애니메이션을 적용했다.

 

binding.mainFloatingActionUpscrollButton.setOnClickListener {
    binding.mainRecyclerViewGoods.smoothScrollToPosition(0)
}

floating button 클릭 이벤트 쪽이다.

smoothScrollToPosition()을 통해 자신이 원하는 index의 데이터가 있는 쪽으로 자연스럽게 스크롤을 할 수 있다.

 


 

오늘 공부 내용 정리 및 회고

오늘은 알고리즘도 큰 문제없이 해결했고, 필수 구현도 완료했다.

선택 과제 나머지 부분은 주말에 할 수 있으면 해 보자.

728x90