본문 바로가기
알고리즘/Codewars

Codewars - [6 kyu] Sum consecutives

by 개발자J의일상 2022. 1. 17.
반응형

 

 

You are given a list/array which contains only integers (positive and negative). Your job is to sum only the numbers that are the same and consecutive. The result should be one list.

 

Extra credit if you solve it in one line. You can assume there is never an empty list/array and there will always be an integer. 

 

Same meaning: 1 == 1

 

1 != -1

 

#Examples:

[1,4,4,4,0,4,3,3,1] # should return [1,12,0,4,6,1]

"""So as you can see sum of consecutives 1 is 1 
sum of 3 consecutives 4 is 12 
sum of 0... and sum of 2 
consecutives 3 is 6 ..."""

[1,1,7,7,3] # should return [2,14,3]
[-5,-5,7,7,12,0] # should return [-10,14,12,0]

My Solution

fun sumConsecutives(s: List<Int>): List<Int> {
    var curInt = s[0]
    val newList = mutableListOf<Int>()
    var consecutiveSum = curInt
    for (i in 1..s.size-1)
    {
        if (curInt == s[i])
        {
            consecutiveSum += curInt
        } else
        {
            newList += consecutiveSum
            consecutiveSum = s[i]
            curInt = s[i]
        }
    }
    newList += consecutiveSum
    return newList
}

연속되는 값이 있을 때 그 값을 더해서 새로운 배열에 추가하고 연속되는 것이 없으면 그냥 새로운 배열에 추가하는 문제!

 

연속되는 값이 뭔지 파악하기 위해 일단 curInt로 첫 번째 배열을 가르킨다.

 

newList는 수정이 가능해야 되니 mutableListOf<Int>로 생성한다. 

 

연속되는 값이 있을 때까지 합을 더해야 하니 consecutiveSum을 선언하고 첫 번째 값으로 초기화 한다.

 

1부터 list의 끝까지 for문을 도는데 curInt와 list의 값이 같으면 consecutiveSum을 합쳐주고 아니면 consecutiveSum을 그냥 newList에 저장한다. 

 

만약에 [1, 4, 4, 0] 이면 consecutiveSum은 이미 1이었기 때문에 newList에 그냥 consecutiveSum을 넣으면 되고 consecutiveSum을 새로운 4로 update한다. curInt도 4로 update해준다. 

 

이렇게 하는 이유는 다음으로 넘어가보자.

 

s[i]는 이제 다시 4가 되고 consecutiveSum은 8이된다. 하지만 현재 curInt는 그대로 4일 것이다. 그 전의 curInt와 같기 때문이다. 그래서 curInt와 다른 변수가 필요했던 것이다.

 

for문이 다돌고나면 마지막 consecutiveSum을 newList에 추가한다.

 

[1, 4, 4, 0]의 경우에 마지막에 s[i]가 0이되면 else로 빠지게 되고 newList에 consecutiveSum = 8이 저장되고 consecutiveSum과 curInt에 0이 저장된다. 

 

하지만 이미 for문이 끝났기 때문에 0을 저장할 방법이 없다. 이는 그냥 다 끝나고나서 consecutiveSum을 newList에 더해주면된다.

 

curInt가 있는데 왜 consecutiveSum을 더하냐고 묻는다면...

[1, 4, 4, 4]의 경우를 생각해보면 된다. consectiveSum이 이때는 12가 될텐데 만약에 for문을 나오고 newList에 curInt를 저장하면 4가 저장될 것이다.

 

Best Solution

fun sumConsecutives(s: List<Int>) = mutableListOf(s[0]).apply {
    (1..s.lastIndex).forEach { if (s[it] == s[it - 1]) this[lastIndex] += s[it] else add(s[it]) }
}

뭔가 더 많이 간단하다. apply라는 function을 사용하였는데, 아직은 이해를 못하고 있다.

추후 apply를 정리하면 추가 정리를 하려고한다.

 

forEach를 통해 1..s.lastIndex까지 돌리는데 현재 list의 원소와 이전 list의 원소가 같으면 mutableListOf의 lastIndex에 s[it]을 계속 더하고 아니면 s[it]에 add한다.

 

결국 연속되는 list면 맨끝에 계속해서 연속된 값을 더해주고 아니면 현재 위치에 그대로 원소를 저장하는 것이다.

 

functional programming 방법인데 아직은 미숙한 것 같다. 점점 보면서 익숙해져야 겠다.

300x250

'알고리즘 > Codewars' 카테고리의 다른 글

Codewars - [7 kyu] Reverse words  (0) 2022.05.03
Codewars - [5 kyu] Simple assembler interpreter  (0) 2022.04.29

댓글