[프로그래머스] 푸드 파이터 대회

neoneoneo·2024년 3월 5일
0

kotlin

목록 보기
19/49

문제

수웅이는 매달 주어진 음식을 빨리 먹는 푸드 파이트 대회를 개최합니다. 이 대회에서 선수들은 1대 1로 대결하며, 매 대결마다 음식의 종류와 양이 바뀝니다. 대결은 준비된 음식들을 일렬로 배치한 뒤, 한 선수는 제일 왼쪽에 있는 음식부터 오른쪽으로, 다른 선수는 제일 오른쪽에 있는 음식부터 왼쪽으로 순서대로 먹는 방식으로 진행됩니다. 중앙에는 물을 배치하고, 물을 먼저 먹는 선수가 승리하게 됩니다.
이때, 대회의 공정성을 위해 두 선수가 먹는 음식의 종류와 양이 같아야 하며, 음식을 먹는 순서도 같아야 합니다. 또한, 이번 대회부터는 칼로리가 낮은 음식을 먼저 먹을 수 있게 배치하여 선수들이 음식을 더 잘 먹을 수 있게 하려고 합니다. 이번 대회를 위해 수웅이는 음식을 주문했는데, 대회의 조건을 고려하지 않고 음식을 주문하여 몇 개의 음식은 대회에 사용하지 못하게 되었습니다.
예를 들어, 3가지의 음식이 준비되어 있으며, 칼로리가 적은 순서대로 1번 음식을 3개, 2번 음식을 4개, 3번 음식을 6개 준비했으며, 물을 편의상 0번 음식이라고 칭한다면, 두 선수는 1번 음식 1개, 2번 음식 2개, 3번 음식 3개씩을 먹게 되므로 음식의 배치는 "1223330333221"이 됩니다. 따라서 1번 음식 1개는 대회에 사용하지 못합니다.
수웅이가 준비한 음식의 양을 칼로리가 적은 순서대로 나타내는 정수 배열 food가 주어졌을 때, 대회를 위한 음식의 배치를 나타내는 문자열을 return 하는 solution 함수를 완성해주세요.

나의 코드

class Solution {
    fun solution(food: IntArray): String {
        var answer: String = "" 
        var temp: String = ""    
        for (i in 1..food.size - 1) {        
            if(food[i] % 2 == 0) { //이미 짝수이면, 절반만 반복
                for (j in 0..(food[i]) / 2 - 1) {
                    temp += i.toString()
                }
            }
            else { //홀수이면, 1을 빼서 짝수로 만든다음에, 절반만 반복
                for (j in 0..(food[i]-1) / 2 - 1) {
                    temp += i.toString()
                }
            }
        }        
        answer = temp + "0" + temp.reversed()
        return answer
    }
}
  • 숫자가 짝수/홀수인지를 판별해서, 짝수일 경우에는 받아오는 숫자의 절반만, 홀수일 경우에는 받아오는 숫자에서 1을 빼고 절반만, 반복한다.
  • 반복해서 만들어진 String에 "0"을 먼저 추가하고, 반대로 정렬된 String을 이어 붙인다.

고수의 코드_1

class Solution {
    fun solution(food: IntArray): String {
        val answerList = food.mapIndexed { index, count ->
            if (count % 2 == 0) {
                index.toString().repeat(count / 2)
            } else {
                index.toString().repeat( (count - 1) / 2)
            }
        }        
        val answer = answerList.joinToString("") + "0" + answerList.reversed().joinToString("")
        return answer
    }
}
  • 최근 map 사용하고싶어서 chatGPT에게 map을 쓰면 어떻게 구현이 되냐고 물어봤다.
  • mapIndexed : food의 각 요소에 대한 변환을 적용한다.
    • 짝/홀수에 따른 처리가 상이하다.
    • i를 String으로 변환한 뒤, 필요한 숫자만큼 repeat으로 반복하여 찍어낸다.
    • 그럼 데이터는 [1, 222, 33] 이런식으로 변환이 된다.
  • map으로 변환된 데이터를 joinToString으로 묶어준다.

고수의 코드_2

class Solution {
    fun solution(food: IntArray): String {
        val sb = StringBuilder()
        for (i in 1..food.lastIndex) {
            repeat(food[i] / 2) { sb.append(i) }
        }
        val reversed = sb.reversed()
        sb.append(0)
        sb.append(reversed)
        return sb.toString()
    }
}
  • 이 고수는 사람인데, 역시나 repeat으로 숫자를 반복했다.
  • StringBuilder() : 가변적인 문자열을 효율적으로 처리하기 위한 클래스로, 객체 sb를 생성한다.
  • .lastIndex : 배열의 마지막 인덱스 값이다.
  • repeat(food[i] / 2) : 현재 인덱스에 해당하는 수를 절반만큼 반복한다.
    • 단순히 몫을 가져오는 계산식을 사용하므로써 짝/홀수 판별을 하지 않아도 괜찮게 된다.
    • { sb.append(i) } : 이 코드를 통해 sb 객체 안에 반복되는 숫자 데이터를 String으로 추가한다.
      • repeat(n)은 n번 반복하는 함수인데, {} 내부의 코드를 해당 횟수만큼 반복 실행하게 한다.

배운점

  • StringBuilder(), repeat() {} 의 동작을 쉽게 이해할 수 있게 해주는 코드였다.
  • 계산식을 잘 짜면 if문이 필요없는 거였구나 싶었다..! 사실 처음에 나눗셈으로 몫을 가져오면 되지 않나? 하는 생각이 0.1초 들었지만 그저 스쳐지나가버렸고, 결국 내 코드에는 쉬운 방식으로 if문을 작성하였다. 새로운 생각을 하는 것은 에너지가 드는 일이기에 나의 자동항해모드(?)는 효율적으로 일하기 위해 if문으로 푸는 방향으로 간 것 같다. 조금 번거로워도 다른 시각에서 생각해보는 연습을 꾸준히 해보자.

[TIL-240305]

0개의 댓글