-
짝수와 홀수, 배열의 평균값, 자리수 합치기iOS 앱 개발 부트캠프/TIL 2024. 11. 3. 14:19
짝수와 홀수
문제 설명
- 정수 num이 짝수일 경우 "Even"을 반환하고 홀수인 경우 "Odd"를 반환하는 함수, solution을 완성해주세요.
제한 조건
- num은 int 범위의 정수입니다.
- 0은 짝수입니다.
문제풀이
다음과 같이 num % 2 == 0 을 조건으로 짝수 홀수를 나누려고 했는데, 15번의 테스트 중 한 번 에러가 났다.
음수나 0 때문인가 생각도 해봤지만 0은 짝수로 처리되니 문제가 없고, 2로 나눠서 나머지가 0인지 보는 것이니 음수인 것도 문제가 없다.
혹시나해서 음수나 0, 여러 짝수와 홀수, 큰 수도 입력하며 테스트 해봤는데 문제를 발견하질 못했다.
어떤 테스트 값이 입력 되었길래 런타임 에러가 난 건지 모르겠다. 매개변수 타입이 Int이니 실수나 문자열이나 Int 범위를 넘는 숫자가 들어온 것도 아닐텐데.. 무슨 에러인지 좀 더 고민해봐야 할 것 같다.
여하튼 문제를 풀기 위해 코드를 바꿔서 시도해보았다.
func solution(_ num:Int) -> String { if num % 2 == 1 || num % 2 == -1 { return "Odd" } else { return "Even" } }
나머지가 1인지를 판별하는 경우인데 이 경우 입력 값이 음수 일땐 나머지도 음수가 되므로 -1의 경우도 생각해서 조건문을 설정하였다.
첫번째 방식과 다를 바 없다고 생각하지만 에러가 발생하지 않고 잘 해결되었다.
그런데 처음의 코드보다 조건문이 길어진 부분이 있어 더 나은 방법이 없을까 하다가, 짝수 or 홀수의 단순한 조건이기 떄문에 삼항 연산자를 쓰면 더 간단해지겠다는 생각이 들었다.
func solution(_ num:Int) -> String { num % 2 == 0 ? "Even" : "Odd" }
삼항연산자를 쓰니 코드가 훨씬 간결해졌다.
이것도 처음의 방식에서 if-else 대신 삼항연산자를 쓴 것뿐인데 잘 작동하는게 이상하다고 생각된다. if-else문과 삼항연산자의 다른 점이 뭔가 있는지 찾아봐야할 것 같다.
그리고 짝수와 홀수, 음수와 양수 같은 참/거짓 정도의 단순한 조건문이 필요한 경우 삼항연산자가 더 나을 수 있을 것 같다.
배열의 평균값
문제 설명
- 정수를 담고 있는 배열 arr의 평균값을 return하는 함수, solution을 완성해보세요.
문제 풀이
반복문을 썼다면 다음과 같은 방식으로 구현해야 했겠지만,
func solution(_ arr:[Int]) -> Double { var total = 0 for number in arr { total += number } return Double(total) / Double(arr.count) }
어제 공부한 고차함수의 reduce를 한 번 사용해보았다.
func solution(_ arr:[Int]) -> Double { return Double(arr.reduce(0, +)) / Double(arr.count) }
배열의 모든 수를 더하는 구문을 훨씬 간결하게 작성할 수 있다. 그리고 어제의 경험으로 형변환도 주의해서 작성하였다. for문을 사용하는 것보다 간단한 코드로 배열의 평균 값을 구할 수 있었다.
자리수 더하기
문제 설명
- 자연수 N이 주어지면, N의 각 자릿수의 합을 구해서 return 하는 solution 함수를 만들어 주세요.
- 예를들어 N = 123이면 1 + 2 + 3 = 6을 return 하면 됩니다.
문제 풀이
이 경우 숫자를 문자열로 변환한 뒤, character로 한 글자씩 저장해 다시 Int로 변환해 더한다면 풀 수 있을 것 같았다.
func solution(_ n:Int) -> Int { var charNumber: [Character] = [] // 문자열로 변환한 숫자를 한 글자씩 저장하기 위한 배열 var stringNumbers = String(n) // 정수 입력 n을 문자열로 변환 var sum = 0 // 반환할 결과를 저장할 변수 // 한 글자씩 char 배열에 추가하기 for char in stringNumbers { charNumber.append(char) } // character가 저장된 배열 하나씩 가져와 더하기 for i in charNumber { if let num = Int(String(i)) { // 옵셔널 처리하기 sum += num } } return sum }
단순하게 형변환을 하려고 했더니 character는 Int로 형변환이 안되어서 String으로 먼저 형변환을 한 뒤 다시 Int로 형변환 하는 식으로 해야했다.
그리고 문자는 공백이 있거나 알파벳 같은 숫자로 변환할 수 없는 문자가 포함되어 있을 수 있기 때문에 Int(String(i))의 반환 값이 옵셔널 값이어서 옵셔널 처리를 해야했다.
입력으로 받는 매개변수가 Int 타입이고 이걸 형변환 한 것이기 때문에 이상한 값이 들어가진 않을 것이라 sum += Int(String(i))! 같이 강제 언래핑을 해도 되겠지만, 안전한 옵셔널 처리 습관을 들이기 위해 if let 구문을 사용해 옵셔널 바인딩 처리를 하는 방법을 선택했다.
더 나은 방법 생각하기
작성한 코드를 다시 읽어보면서 생각을 다시 해보았는데, charNumber 배열을 쓴 것은, 문자열에서 문자를 하나씩 배열에 저장한 뒤에 그 배열을 다시 반복문에서 사용해야 글자를 하나씩 읽어 올 수 있을 것이라고 생각해서였다.
그런데 애초에 charNumber 배열에 한 글자씩 문자를 저장할 때, 문자열로 변환 된 stringNumbers에서 한 글자씩 charNumber에 저장할 수 있었다. 이것이 가능하다면 character 타입의 문자를 저장하겠다고 배열을 만들어 한 글자씩 저장할 필요가 없다. 처음부터 문자열로 변환된 숫자를 하나의 반복문에서 한 글자씩 뽑아내면 되는 것이었다.
또한 stringNumbers 변수도, 반복문을 작성할 때 형변환을 하면 딱히 선언할 필요 없는 변수인 것이다.
func solution(_ n:Int) -> Int { var sum = 0 for char in String(n){ // 반복문 작성할 때 형변환 하기 if let num = Int(String(char)){ // 옵셔널 바인딩 하기 sum += num } } return sum }
이렇게 하면 훨씬 간결한 코드로 자릿수 더하기 코드를 완성할 수 있다.
코드가 단순해져서인지 실행 시간도 0.05ms ~ 0.1ms에서 0.03ms ~ 0.05ms로 절반으로 줄어들었다.
'iOS 앱 개발 부트캠프 > TIL' 카테고리의 다른 글
야구게임 로직 만들기 (5) 2024.11.05 약수의 합 (0) 2024.11.04 짝수의 합, 배열의 평균 값 (2) 2024.11.02 클래스와 구조체의 인스턴스 그리고 초기화 (0) 2024.11.01 추상화 된 프로토콜 만들기 (0) 2024.10.31