콜라를 받기 위해 마트에 주어야 하는 병 수 a, 빈 병 a개를 가져다 주면 마트가 주는 콜라 병 수 b, 상빈이가 가지고 있는 빈 병의 개수 n이 매개변수로 주어집니다. 상빈이가 받을 수 있는 콜라의 병 수를 return 하도록 solution 함수를 작성해주세요.
class Solution { fun solution(a: Int, b: Int, n: Int): Int { var answer: Int = 0 var sbBottles: Int = n while ( sbBottles >= a ) { val temp = sbBottles / a * b answer += temp sbBottles = temp + (sbBottles % a) } return answer } }
- 바꿀 수 있는 콜라의 개수(sbBottles)가 마트에서 받아주는 콜라 개수(a)보다 크거나 같아야지만 계산이 가능해지므로, while문의 조건에 명세한다.
- while문 안에는 임시 변수를 두어 바꿀 수 있는 콜라 개수를 저장해두고, answer에 누적한다.
- while문 안에서 계속해서 초기화 선언되므로 불변 변수(val)로 선언한다. - 팀원의 코드를 참고함!
- 그리고나서 바꿀 수 있는 콜라 개수를 갱신하는데, 이미 교환한 콜라 개수(temp)와 개수가 모자라 바꾸지 못했던 콜라 개수(sbBottles % a)를 더하여 계산한다.
위 코드는 팀원들과 데일리 알고리즘 리뷰를 통해서 힌트를 얻어 작성한 것이고.. 아래는 나 혼자 삽질한 내용이다. 결국 내가 접근한 방식에 대해 스스로 답을 구하지는 못하였다.
class Solution { fun solution(a: Int, b: Int, n: Int): Int { var answer: Int = 0 var remainder: Int = 0 var sbBottles: Int = n // (n / a) * b = n 계산식을 반복 // 20 / 2 * 1 = 10 // 10 / 2 * 1 = 5 // 5 / 2 * 1 = 2 (나머지 1 적립) // 2 / 2 * 1 = 1 (몫이 1일 때 적립) // 2 / 2 * 1 = 1 (나머지가 0이고 몫이 1일 때 종료) while (true) { if ( sbBottles % a == 0 ) { // 나머지가 없을 때 println("나머지가 없을 때 진입") sbBottles = (sbBottles / a) * b println("다음에 바꿀 수 있는 콜라병은 $sbBottles") } else if ( sbBottles % a > 0 ) { // 나머지가 있을 때 println("나머지가 있을 때 진입") remainder = sbBottles % a // 나머지는 적립 sbBottles = (sbBottles / a) * b // 몫은 사용 println("다음에 바꿀 수 있는 콜라병은 $sbBottles , 적립된 나머지는 $remainder") } else if ( remainder > 0 && sbBottles == 1) { // 나머지가 있고 몫이 1일 때 println("나머지 있고 몫이 1일 때 진입") sbBottles += remainder sbBottles = (sbBottles / a) * b } answer += sbBottles if ( remainder == 0 && sbBottles == 0 ) break // 나머지가 0이고 몫이 1이면 종료 } return answer } }
- 결국 답을 구하지 못 한 코드이다.
- while(true)로 두어 계속해서 반복하다가 특정 조건이 되면 break로 빠져나오게 하였다.
- 이렇게 코드를 돌리면 무한반복의 굴레에 빠져 답을 구할 수가 없었다(사실 어떻게 또 수정해서 test case 2개에 대해서는 답을 구할 수는 있었지만, 막상 제출하면 전부 fail을 받았다.)
- 똑같은 계산식을 반복해야 하고, 특정 조건이 생기면 다른 계산식을 쓰자! 라는 생각에 처음에 이렇게 접근했는데, 점점 추가할 조건이 많아져 코드가 길어지고 복잡해졌다.
- 여러모로 문제가 많았던 코드이고, 아 이건 아니다 싶어서 생각해낸게 재귀함수인데...
class Solution { fun solution(a: Int, b: Int, n: Int): Int { return sbb(a, b, n, 0) } // (n / a * b) + (n % a) = n 바꿀 수 있는 콜라 개수 tailrec fun sbb(a: Int, b: Int, n: Int, acc: Int): Int { return if (a > n) { acc // 종료 조건: a > n 이면 적립된 값을 반환 } else { sbb(a, b, (n / a * b) + (n % a), acc + ((n / a * b) + (n % a)) } } }
- 예전부터 재귀함수를 응용해보고 싶었고, 마침 반복되는 계산식을 함수로 빼내어 처리하면 되겠다 싶어서 써봤다.
- 코드에 에러는 없었지만 정확한 답이 나오지 않았다. 계산식이 잘 못되었기 때문이다.
- ChatGPT에게 재귀함수를 써서 문제를 풀어달라고 하니 아래와 같이 답을 주지만 코드를 돌려보면 제대로된 답을 구하지 못한다.
- 여기도 계산식 부분이 잘 못된 것 같다. 저렇게 한줄짜리 계산식을 사용하지 않고, 나의 풀이처럼 풀어서(?) 코드를 쓴 다음 재귀함수 처리하면 정상 작동 할 것 같다. 다만, 이렇게 돌이켜보니 이 문제를 풀 때 재귀함수까지 쓰는건 좀 오바인 것 같다.
class Solution { fun solution(a: Int, b: Int, n: Int): Int { var answer: Int = 0 val result = buyCola(a, b, n) answer = result return answer } tailrec fun buyCola(a: Int, b: Int, n: Int, total: Int = 0): Int { return if (n < a) total else buyCola(a, b, (n / a) * b + n % a, total + n / a) } }
class Solution { fun solution(a: Int, b: Int, n: Int): Int { return (if (n > b) n - b else 0) / (a - b) * b } }
- 계산식은 이렇게 짜는거더라..
[TIL-240306]