소피it블로그

[Swift] 코딩테스트로 스위프트 공부하기 - 입출력과 사칙연산 (2), 조건문 본문

개발_iOS/코딩테스트로 스위프트 공부하기

[Swift] 코딩테스트로 스위프트 공부하기 - 입출력과 사칙연산 (2), 조건문

sophie_l 2022. 4. 6. 00:47

1. 곱셈

https://www.acmicpc.net/problem/2588

 

2588번: 곱셈

첫째 줄부터 넷째 줄까지 차례대로 (3), (4), (5), (6)에 들어갈 값을 출력한다.

www.acmicpc.net

정말 열받게 하는 문제... 이것 때문에 머리 싸매고 끙끙거렸다.

문제 자체는 어려운 부분이 없다. 날 힘들게 한 부분은 역시나 스위프트 문법. 파이썬으로는 힘도 안들이고 풀 수 있는 문제인데😡

 

날 가장 힘들게 했던 부분은 Character를 Integer로 변환하기. 파이썬에서는 문자열 또한 리스트처럼 바로 인덱스로 접근이 가능하기 때문에 생각해볼 필요도 없던 문제였지만 스위프트에서는 문자열에 stringName[i] 이런 식으로 접근하는 게 불가능했다.

다른 방법을 찾아 구글을 떠돈 결과 아래와 같은 해법을 찾았다.

let myString = "example"

let getA = myString[myString.index(myString.startIndex, offsetBy: 2)]

주의할 점 몇가지를 적어보자면, myString[] 대괄호 안에 적어줘야 한다는 것, startIndex는 첫 인덱스지만 endIndex는 마지막 인덱스가 아니라 문자열의 길이라는 것, offsetBy는 음수도 가능하다는 점(endIndex와 함께 씀).

 

보고 배운 자료: https://zeunny.tistory.com/37

 

[Swift] 인덱스로 문자열의 글자 가져오기

인덱스로 문자열의 글자 가져오기 처음에 나는 python 에 익숙해져 있어 문자열을 글자를 가져오기 위해 처음에는 아래와 같은 코드를 생각했다. let name = "seonho" let str = name[2] 하지만 swift 에서는

zeunny.tistory.com

그런데 난관은 이게 끝이 아니었다.

뭔소린지 1도 모르겠는 오류

듣도 보도 못한 오류가 나버린 것. 오래 끙끙거리고 이것저것 출력해보고 인터넷을 뒤적여본 결과, 문제점이 뭔지 알아냈다.

바로 Character를 Integer로 변환할 때 one = Int("1")! 처럼 강제 언래핑하는 듯한 방식을 사용할 수 없다는 것.

나는 문제가 되는 지점이 String인줄 알았는데 type(of: char)로 확인해보니 Character였다. 그래서 영어로 Character를 Integer로 바꾸는 방법을 구글링해보았고, 아래와 같은 해답을 얻었다.

 

Character에는 wholeNumberValue가 있는데 이를 활용하면 된다.

let char: Character = "1"

if let intVal = char.wholeNumberValue {
	print(intVal * 2)
}

이런 방법이 있었다니. 정말 화가 난다. 파이썬처럼 쉬우면 좀 좋을까. 하여튼 좋은 해답을 얻어서 이를 코드에 반영하였고, 결과적으로 통과할 수 있었다. 두 번 작성하였는데 차이점은 for문 구현 뿐이다.

간신히 성공한...

이 경우 for문 자체에는 어려움이 없지만 내부에서 endIndex가 들어가고 offsetBy가 음수가 되므로 주의할 것.

여기까지 쉽지 않았다.

for 문을 쓸 때 역순으로 루프를 돌고 싶으면 reversed()를 써주면 된다.


2. 주사위 세개

https://www.acmicpc.net/problem/2480

 

2480번: 주사위 세개

1에서부터 6까지의 눈을 가진 3개의 주사위를 던져서 다음과 같은 규칙에 따라 상금을 받는 게임이 있다.  같은 눈이 3개가 나오면 10,000원+(같은 눈)×1,000원의 상금을 받게 된다.  같은 눈이 2개

www.acmicpc.net

어려운 문제는 아니었는데, 풀이 과정에서 array의 최댓값을 찾는 함수와 개수를 세는 함수, 그리고 풀이에 있어 필수적인 과정은 아니지만 배열을 집합으로 만들어주는 과정이 있었기 때문에 관련 내용들을 한번 정리하고 가고자 한다.

 

우선 나의 풀이 두 가지를 먼저 보자. 뭔가 더 깔끔하고 기똥찬 풀이가 있을 것도 같은데 지저분하고 구구절절한 코드밖에 생각이 나지 않아 속상하다.

집합을 이용한 풀이. 조금 더 지저분하다

먼저 푼 풀이이다. 이 경우 중복을 허용하지 않는 집합의 성질을 이용해서 중복이 없는 경우, 즉 주사위 세 개에서 다 다른 숫자가 나온 경우를 먼저 걸러주었고 그 후에는 전부 중복인 숫자가 나온 경우를 다시 걸러주었다. 그러다보니 마지막 else구문에서 다시 한번 if 문을 중첩해서 쓰는 일이 발생했는데, 이 부분이 지저분해서 마음에 들지 않는다. 수정할 수는 있지만 일단 크게 중요한 부분은 아니니 스킵. 중첩문을 안은 else문을 보면 a와 b가 중복인 경우, b와 c가 중복인 경우, 그리고 a와 c가 중복인 경우를 나눠주었다.

조금 더 깔끔하게 정돈된 풀이

조금은 더 깔끔하게 풀었다. 우선 셋 다 중복이라면 배열의 최댓값과 최솟값이 같을 것이라는 전제 하에 세 개 다 같은 경우를 먼저 걸러주었고, 그 후에는 두 개가 같은 경우를 하나씩 else if 구문으로 걸러줬다. 마지막으로 모든 if 조건문에 걸리지 않은 경우라면 셋이 다 다른 숫자일 경우일테고, 그 경우 최댓값을 사용해서 계산을 마무리한다.


여기서 새로 써본 문법이 몇 가지 있었는데,

1) Array의 최댓값과 최솟값 찾기 함수: max(arrayName) 처럼 쓰지 않는다. arrayName.max()라고 써줘야 한다. 그리고 무엇보다 중요한 것은, max()와 min()의 리턴값은 옵셔널이라는 점. 따라서 강제 언래핑(강제 언래핑 좋은 방법은 아니지만 코딩테스트에 한해 써주기로 했다. 오류 없는 입력이 들어올 것임을 전제하고)을 해준다.

 

2) Array를 Set으로 변환해주는 함수: 아주 간단하다.

let setName = Set(arrayName)

3) Set의 요소 개수를 세주는 함수: 역시 간단하게 count를 써주면 되는데, 주의할 점은 min(), max()와 다르게 ()를 붙이지 않는다.

if setName.count == 1 { }