티스토리 뷰
코드카타
k진수에서 소수 개수 구하기
문제
저 조건들을 요약하자면 n을 k진수로 변환한 숫자에서
추출한 숫자가 0을 포함하지만 않으면 된다는 뜻이다.
풀이
class Solution {
fun solution(n: Int, k: Int): Int {
// 소수 판별 함수
fun isPrime(num: Long): Boolean {
if (num <= 1) return false
return (2..Math.sqrt(num.toDouble()).toLong()).none { num % it == 0L }
}
val kn = n.toString(k) // k진수 변환
// 문자열을 0을 기준으로 나눈 뒤 공백요소는 제거
val arr = kn.split("0").filter { it.isNotEmpty() }
// arr의 요소 중 소수가 몇 개인지 출력
return arr.count { isPrime(it.toLong()) }
}
}
주어진 정수 n을 k진수로 변환한 후, 변환된 각 숫자 그룹에서
소수인 숫자들의 개수를 반환하는 로직이다.
조건에 따른 문자열 나누기
val arr = kn.split("0").filter { it.isNotEmpty() }
1100100 -> [11, , 1, , ] -> [11, 1]
여기서 kn은 n을 k진수로 변환한 결과인 문자열에 해당한다.
split 함수는 구분자(여기선 "0"에 해당)가 연속해서 나타나거나,
문자열의 시작 또는 끝에 위치할 경우 빈 문자열을 생성하여 배열에 포함시킨다.
따라서 kn을 "0"을 기준으로 나눈 결과에서 공백요소를 제거하면
arr에는 "0"을 포함하지 않는 연속된 숫자 그룹들이 포함된다.
int형 범위를 초과할 때를 고려
fun isPrime(num: Long): Boolean {
if (num <= 1) return false
return (2..Math.sqrt(num.toDouble()).toLong()).none { num % it == 0L }
}
해당 로직에서 소수 판별함수의 제수와 피제수는 Long타입이어야 한다.
n = 797161, k = 3 -> arr = [1111111111111]
arr의 요소는 int의 범위를 초과하는 수 일수도 있기 때문이다.
int의 범위는 -2147483647 ~ 2147483647(2^31)에 해당한다.
반례 찾기
fun main() {
val n = 1+3+9+27+81+243+729+2187+6561+19683+59049+177147+531441
val kn = n.toString(3)
print("$n, $kn") // 797161, 1111111111111
}
n진수의 각 m번째 자리수는 n^(m-1)의 배수에 해당한다. (n^0 = 1)
arr의 요소는 n을 k진수로 바꾼 문자열을 0을 기준으로 나눈 값들에 해당하기에
0이 존재하지 않는 3진수를 10진수로 변환했을 때 반례를 찾을 수 있었다.
회고
1번, 11번 테스트케이스에서 런타임 오류가 나서 그 이유를 찾아보니까
소수 판별함수의 제수와 피제수를 Long으로 설정해야한다고 나와있었다.
n = 1000000, k = 2 뭐 이렇게 값이 들어오면 겁나 큰 수를 반환해서
런타임 에러가 난다고 설명이 되어있는데 내가 짠 로직에서는
문제없이 돌아가서 왜 그래야 하는지 이해가 안갔었다.
그래서 그거에 대한 반례를 찾아보는데 프로그래머스 질문 탭을 다 뒤져봐도
반례가 안 나와있어서 직접 찾아본다고 거기서 시간을 좀 잡아먹었다.
arr의 요소가 int형 범위를 초과하는 수에 해당하는
반례를 찾고자 했는데 생각해보니까 반대로 접근하면 됬었다.
진수 변환에 대한 이해도가 있어야 문제 로직을 이해할 수 있었다.
1점 2점씩 오르다가 오늘은 7점 올라서 상당히 달달했다.
근데 이게 7점 줄 정도로 어려운 문제는 아닌 것 같은디...
앱 개발 입문 과제 선택 구현 사항
선택 구현 사항 1
구현 사항
- 회원 가입 페이지에서 입력한 아이디/비밀번호가 회원 가입 버튼을 눌러
로그인 화면으로 이동할 때 자동으로 입력되도록 구현합니다.
- `registerForActivityResult` 이용
전달할 데이터 등록
signUpButton.setOnClickListener {
if(editTextName.text.isBlank() || editTextId.text.isBlank() || editTextPw.text.isBlank()){
Toast.makeText(this, "입력되지 않은 정보가 있습니다.", Toast.LENGTH_SHORT).show()
}else{
intent.putExtra("id", editTextId.text.toString())
intent.putExtra("pw", editTextPw.text.toString())
setResult(RESULT_OK, intent)
finish()
}
}
회원가입 페이지에서 회원가입 버튼을 눌렀을 때
사용자가 입력한 아이디와 비밀번호를 인텐트에 추가하고
setResult()를 호출해 이전 액티비티에 데이터를 전달한다.
registerForActivityResult로 데이터 받아오기
private lateinit var signUpResult: ActivityResultLauncher<Intent>
로그인 페이지에 ActivityResultLauncher 자료형의 변수를 선언한다.
signUpButton.setOnClickListener {
val intent = Intent(this, SignUpActivity::class.java)
signUpResult.launch(intent)
}
데이터를 받아올 액티비티를 설정한다.
signUpResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { it ->
if (it.resultCode == RESULT_OK) {
val id = it.data?.getStringExtra("id")?:""
val pw = it.data?.getStringExtra("pw")?:""
editTextId.setText(id)
editTextPw.setText(pw)
}
}
회원가입 액티비티에서 아이디와 비밀번호 데이터를 받아오고
텍스트필드의 텍스트를 해당 데이터로 설정한다.
선택 구현 사항 2
구현 사항
- drawable폴더에 5장의 사진을 등록합니다.
- 자기소개 페이지가 시작될 때 5장 중 랜덤으로 1장의 사진이 표시되도록 구현합니다.
랜덤함수 활용
val profileImage = findViewById<ImageView>(R.id.profileImage)
when(Random.nextInt(5)){
0 -> profileImage.setImageResource(R.drawable.profile1)
1 -> profileImage.setImageResource(R.drawable.profile2)
2 -> profileImage.setImageResource(R.drawable.profile3)
3 -> profileImage.setImageResource(R.drawable.profile4)
4 -> profileImage.setImageResource(R.drawable.profile5)
}
Random.nextInt(n)은 0 ~ n 범위의 난수를 반환한다.
'내일배움캠프 > Android 국비지원' 카테고리의 다른 글
TIL 34일차 (모음사전 - Kotlin | 피그마 기초 강의 정리) (0) | 2024.07.01 |
---|---|
TIL 33일차 (주차 요금 계산 - Kotlin | 챌린지반 1주차 세션 정리) (0) | 2024.06.28 |
TIL 31일차 (타겟 넘버 - Kotlin | 앱개발 입문 과제 필수 구현 사항) (0) | 2024.06.26 |
TIL 30일차 (피로도 - Kotlin | 액티비티 생명주기 개념 정리) (0) | 2024.06.25 |
TIL 29일차 (프로세스 - Kotlin | Queue 알아보기 | 액티비티와 인텐트 알아보기) (0) | 2024.06.24 |