TIL

17일차 TIL

h_luz 2024. 3. 20. 21:08

 

Swift 알고리즘 및 언어공부

 

최대공약수와 최소공배수..

어떻게든 구하려고 for문 돌려보다가 뭔가 최대공약수랑 최소공배수를 쉽게 구할 수 있는 공식 같은 게 있을 것 같아서 

최대공약수 최소공배수를 구하는 수학 공식?을 찾아봤다.

 

유클리드 호제법이라고  두 개의 정수(자연수) 사이에서의 최대공약수를 구하는 알고리즘 이 있다.

이 방식을 이용해서 문제를 풀면 간단하다.

2개의 자연수(또는 정식) a, b에 대해서 a를 b로 나눈 나머지를 r이라 하면 (단, a>b), a와 b의 최대공약수는 b와 r의 최대공약수와 같다. 이 성질에 따라, b를 r로 나눈 나머지 r'를 구하고, 다시 r을 r'로 나눈 나머지를 구하는 과정을 반복하여 나머지가 0이 되었을 때 나누는 수가 a와 b의 최대공약수이다.

 

이 과정을 코드로 풀어 쓰면 밑에 코드를 완성할 수 있다.

 

정수 a, b값을 받아서 b의 값이 0인지 확인하고, 0이면 a값 리턴. 아닌 경우 다시 재귀함수를 실행하여

a에 b의 값을 , b에는 a를 b로 나눈 값에 나머지가 0이 될 때까지 반복하는 방법

func gcd(_ a: Int, _ b: Int) -> Int {
    if b == 0 {
        return a
    } else {
        return gcd(b, a % b)
    }
}

 

그리고 최소공배수는 (정수1 x 정수2 / 두 정수의 최대공약수) 공식으로 구할 수 있다.

//두 정수 20과 16의 최대공배수 구하기

result = 20 * 16 / gcd(20, 16)

// result 는 80

 

//39. 최대공약수와 최소공배수

// 최대 공약수
func gcd(_ a: Int, _ b: Int) -> Int {
    if b == 0 {
        return a
    } else {
        return gcd(b, a % b)
    }
}

/// 최소공배수
func lcm(_ a: Int, _ b: Int) -> Int {
    return a * b / gcd(a, b)
}

func solution(_ n:Int, _ m:Int) -> [Int] {
    return [gcd(n, m), lcm(n, m)]
}

역시 코딩에는 수학적 사고가 많이 필요하다고 느꼈다.

그리고 최대공약수와 최소공배수의 값을 구하는 과정을 함수로 나눠서 사용한 것을 다른 사람의 풀이에서 봤는데

인상적이었다. 이렇게 또 하나 배워감.. 굳굳 👍

 

//40. 3진법 뒤집기
import Foundation

func solution(_ n:Int) -> Int {
    var num:Int = n
    var changeNum:String = ""
    
    // 3진수 변환
    while num != 0 {
        changeNum = String(num % 3) + changeNum
        num /= 3
    }
    // 뒤집기
    var reverseNum = Int(String(changeNum.reversed()))!
    
    var result = 0
    var count = 0
    
    // 3진수를 10진수로 변환
    while reverseNum != 0 {
        result += (reverseNum % 10) * Int(pow(Double(3), Double(count)))
        reverseNum /= 10
        count += 1
    }
    return result
}

 

이번엔 진법.. 여기 링크에서 진법에 대해서 자세히 알려준다 !

 

10진법에서 3진법으로 바꾸려면 나눗셈을 이용하면 된다.

3을 계속 나누고, 나머지들을 모아서 합치면 3진법이 된다.

10진법인 45가 있다고 생각했을 때, 3진법으로 바꾸면 1200이 된다.

10진법에서 3진법으로 변환하는 법

 

그리고 3진법에서 10진법으로 변환하려면 오른쪽부터 3의 0승씩 곱해서 더하면 된다.

1*27(3^3) + 2*9(3^2)+ 0*3(3^1) + 0*1(3^0) = 45

 

이 방식을 바탕으로 코드를 짰다.

 

그리고 새로 알게 된 제곱 함수인 pow 함수

 

pow()

: 두 정수를 입력하면 a의 b제곱을 해준다. 제곱을 구할 수 있는 함수

let value1 = 2
let value2 = 5
pow(Double(value1), Double(value2))

주의할 점은 Double 형식만 입력할 수 있음. Double 타입(소수점형)으로 변환해주지 않으면 에러가 발생한다.

 

 

그런데 !

radix를 사용하면 간단하게 진법을 변환할 수 있다... ㅠㅠㅠ

//radix 사용

import Foundation
func solution(_ n:Int) -> Int {
    var chgNum = String(n, radix: 3)
    var reverseNum = ""
    
    for i in chgNum.reversed() {
        reverseNum += String(i)
    }
    return Int(reverseNum, radix: 3)!
}

String(n, radix: 3) -> 변환하고자 하는 정수와 radix: 어떤 진수로 변환할 것인지 (3진수로 변환하고 싶으면 '3' )

그리고 String 값을 Int로 변환할 때는 옵셔널 제거해 주는 작업이 필요하다 !

 


 

iOS 앱 개발 입문

 

AutoLayout

: AutoLayout을 안 해주면 화면에 객체들이 x, y 좌표에 따라 표시되어서 다른 크기의 화면에서는 생각하는 것과 다르게 보일 수 있음.

 

제약조건

 

Alignment : 정렬을 통해 제약조건 설정

 

- Code를 통한 제약조건 지정 (현업에서는 코드를 통한 제약조건 더 많이 사용)

NSLayoutConstraint.activate([
		// 가로 가운데 정렬 (X축)
		self.textLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
		// 세로 가운데 정렬	(Y축)
		self.textLabel.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
])

 

Constraints : 상하좌우 영역 지정

 

- Code를 통한 제약조건 지정 (현업에서는 코드를 통한 제약조건 더 많이 사용)

NSLayoutConstraint.activate([
		// 위쪽 Constraints (Top)
		textLabel.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0),
		// 아래쪽 Constraints (Bottom)
		textLabel.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0),
		// 왼쪽 Constraints (Leading)
		textLabel.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0),
		// 오른쪽 Constraints (Trailing)
		textLabel.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0),
])

 


 

생명주기(LifeCycle)

: 실제 실행되고 종료되는 동안 어떤 순환을 가지고 있는 지를 나타낸다.

 

앱이 갖는 생명주기

Not running: 실행되지 않거나 종료된 상태

Foreground

   - Inactive : 실행은 되었지만, 어떤 이벤트를 받을 수 없는 상태

   - Active : 활성화되어서 이벤트를 받을 수 있는 상태

Background : 유예 상태, 진입하기 전 거치는 상태

(음악, 통화가 앱을 닫아도 사용가능한 것은 background 상태에 있는 것)

 Suspended : background 상태지만 아무 이벤트도 받지 않는 상태 (Not running과 일반적으로 동일)

 

UIView 생명주기 : 나타남과 사라짐 두 상태를 가지면서, 상태를 전환 (8가지 메소드)

1. init 메소드 : 객체가 생성될 때 호출. (필요한 의존성이나 구성요소)

2. loadView : 컨트롤러의 view 계층 구조가 생성될 때 호출

3. viewDidLoad : 보통 이 메소드가 호출되는 시점에서 다양한 뷰 컴포넌트들을 올려주고 레이아웃을 잡는 것을 실행.

4. viewWillApear : 뷰가 화면에 나타나기 전 호출 (뷰를 업데이트하거나 애니메이션 시작)

5. viewDidApear : 뷰가 화면에 나타나면 호출 (애니메이션 종료하거나 뷰의 상태를 업데이트)

6. viewWillDisapear : 뷰가 화면에서 사라지기 직전에 호출 (데이터 저장, 애니메이션 시작)

7. viewDidDisapear : 뷰가 화면에서 사라지면 호출 (애니메이션 종료, 뷰의 상태 업데이트)

8. deinit : UIViewController 객체가 메모리에서 해제될 때 호출

 


 

로직 다루기

 

버튼이나 라벨과 같은 것들을 control 키로 잡아서 코드에 드래그하면

IBOutlet을 사용해서 연결하고, IBAction으로 동작을 설정해 줄 수 있음

 

@IBOutlet weak var textLabel: UILabel!

@IBAction func buttonTapped(_ sender: UIButton) {
    self.textLabel.text = "버튼을 클릭했습니다."
    let button = sender as? UIButton
    button?.isEnabled = false
}

버튼 클릭 시, 텍스트 라벨에 텍스트는 "버튼을 클릭했습니다."로 바뀌고, 버튼은 비활성화되는 코드

 

Sender

: Sender는 이 메소드의 caller

아래와 같은 코드에서 두 개의 UIButton이 있다면 sender를 통해서 

어떤 버튼이 불러왔는지(func의 caller)를 확인하는지 알 수 있다.

@IBAction func buttonPressed(sender: AnyObject) {

    let button = sender as UIButton
    println("Button \(button.tag) was pressed!")
}

참조 사이트

 

? 근데 위에 강의 예시자료 코드에 as에는 왜 '?'가 붙었을까.. 옵셔널? 

직접 실행해 보니 에러가 있어서 ?를 지워줬더니 (button 뒤에 물음표까지) 정상으로 작동했다.

 

isEnabled

: 활성화할 것인지, 비활성화할 것인지 true와 false(Bool 값)를 통해서 동작

 

강의에서 디버깅 파트는 필요할 때

한 번 더 보면서 해보면 좋을 것 같음 !

(브레이크 포인트, LLDB ,,,)

 


 

Counter 예제

 

드디어 카운터 예제 !

 

레이아웃 요구사항

1. UILabel이 가운데 위치

2. UILabel을 기준으로 상단에는 감소버튼, 아래에는 증가버튼 위치

3. UILabel과 UIButton 사이의 간격은 16px로 설정

4. AutoLayout 사용

 

로직 요구사항

1. count의 시작은 0

2. 감소버튼을 눌렀을 때, -1씩 감소시켜 UILabel에 표시

3. 증가버튼을 눌렀을 때, +1씩 증가시켜 UILabel에 표시

 

는 내일.. 해야겠다..

 


 

내일은 counter 예제 끝내고, 과제 시작해야겠다 !

아자잣

'TIL' 카테고리의 다른 글

20일차 TIL  (3) 2024.03.25
19일차 TIL  (3) 2024.03.22
18일차 TIL  (2) 2024.03.21
16일차 TIL  (2) 2024.03.19
15일차 TIL  (4) 2024.03.18