<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>se_bb.log</title>
        <link>https://velog.io/</link>
        <description>-</description>
        <lastBuildDate>Tue, 15 Oct 2024 11:59:41 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. se_bb.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/se_bb" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[iOS/Swift] 얼레벌레 TableView 개념 (계속 업데이트 예정)]]></title>
            <link>https://velog.io/@se_bb/241015-iOS-TableView</link>
            <guid>https://velog.io/@se_bb/241015-iOS-TableView</guid>
            <pubDate>Tue, 15 Oct 2024 11:59:41 GMT</pubDate>
            <description><![CDATA[<h1 id="0-개요">0. 개요</h1>
<p>다른 웬만한 뷰들은 한 번 하면 글쿠나ㅇㅇ 하고 넘어가지는데 얘는 어려워서 기록용으로 남깁니다. 계속 업데이트 예정입니다</p>
<h1 id="1-tableview-간단하게-구현해보기">1. TableView 간단하게 구현해보기</h1>
<p>먼저 프로젝트 하나 생성합니다.
<strong>프로젝트 이름 절대절대절대 &quot;Swift&quot;로 하면 안됩니다. 결국 빌드 에러나서 나중에 프로젝트 이름 수정했습니다. Swift뿐만 아니라 framework 내에 있는 키워드로도 프로젝트 이름을 하면 안된다고 합니다 흑.</strong></p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/6d07bbb3-dda2-4ad1-854d-aac28d9d4168/image.png" alt=""></p>
<p>Command+Shift+L 키 누른 후, view controller 찾아서 드래그 합니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/1a4796d6-f1ea-44c7-bd06-999eb5981c6d/image.png" alt=""></p>
<p>짠
두 개의 controller를 만들었습니다. 굳이 이렇게 한 이유는 기록을 위해서 입니다. 아무튼 새로 생성한 view controller를 클릭 -&gt; 우측에서 &quot;is initial view controller&quot;를 체크합니다.</p>
<p>왜죠</p>
<p>이렇게 해야 빌드 했을 때 첫 화면이 방금 생성한 view controller가 되기 때문입니다. 노란색 네모로 표시해둔 것 처럼 initial view controller 왼쪽 옆에는 화살표가 따라옵니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/7a8fd7d4-de43-4555-b2c4-a53d7e99d22d/image.png" alt=""></p>
<p>이제 생성한 view controller에 대한 Cocoa Touch Class 파일을 만들어야 합니다.</p>
<p>왜죠</p>
<p>이 파일을 만들고 이 파일과 새로 만든 view controller를 연결해줘야, 화면 UI 상호작용 및 동작을 제어할 수 있습니다. 화면을 제어하는 코드를 이 Cocoa Touch Class 파일에 코딩하는 거죠</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/a36fdcea-fe94-4d67-bec9-f16f60a7548c/image.png" alt=""></p>
<p>Class 이름은 자유롭게 쓰고, 밑에 &quot;Subclass of:&quot;에선 UIViewController를 선택합니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/e62b9faa-2829-4e89-a700-a51fa357d128/image.png" alt=""></p>
<p>짠
생겼습니다.
저 파일에 간단한 제어 코드 하나를 썼습니다.
view의 배경화면을 갈색으로 지정했습니다. 그대로 빌드 해봅니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/c400ccda-4ead-4842-ac2f-3154d238ae91/image.png" alt=""></p>
<p>안되는데요; 갈색 어디갔죠</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/4bdc779f-f534-4f6b-aedd-4a27d2668d2a/image.png" alt=""></p>
<p>아래 작업을 하지 않았기 때문입니다. 생성한 MyTableViewController.swift 파일과 새로 만든 view Controller를 반드시 연결해줘야합니다. 아래처럼 view Controller 클릭 -&gt; 우측 &quot;Class&quot; 란에서 MyTableViewController를 선택해줘야 합니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/0c48f43f-d109-493f-a311-9f816150344b/image.png" alt=""></p>
<p>그 후 다시 빌드해보면 이번엔 정상적으로 갈색으로 보입니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/684af90b-28e8-4666-a993-4b0fa4018b7b/image.png" alt=""></p>
<p>그 다음으로 Table View를 화면에 드래그 해줍니다.
Command + Shift + L 누른 후 &quot;Table View&quot; 검색해서 화면 안에 드래그 해줍니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/233b42ee-2285-436b-a979-ab76b6d33971/image.png" alt=""></p>
<p>Table View의 크기를 화면 꽉 차게 해주고 싶습니다. 쥔공이니까요.</p>
<p>아래 캡쳐 화면처럼 초록색으로 표시한 부분을 누르고 -&gt; 왼(leading), 위(top), 오(trailing), 아래(bottom)을 0으로 채우고 -&gt; &quot;Add 4 Constraints&quot;를 클릭합니다.
0의 의미는 크기가 아닌, 부모 뷰(바탕화면이라 칩니다) 사이의 margin 값으로 보시면 됩니다. margin을 0으로 주었기 때문에 간격 없이 Table View가 화면에 꽉차게 되는 것입니다.</p>
<p>이 부분은 또 Auto Layout 관련 내용인데 조만간 열심히 공부해서 기록해야겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/0006d769-d7f9-4d5a-9bb1-90e52a82fa86/image.png" alt=""></p>
<p>꽉 한 Table View를 Ctrl+드래그 해서 MyTableViewController.swift 파일에 끌어옵니다. 이렇게 끌어오면 상수 하나가 뿅 생깁니다. 덕분에 이제 이 swift 코드에서 저 상수를 이용해서 화면 내의 Table View에 접근할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/e25be8e3-b74a-4557-81e3-1f4f862a32d8/image.png" alt=""></p>
<p>이제 Table View의 알맹이인 Table Cell를 화면 위에 있는 Table View 위에 얹습니다. 아까처럼 Command + Shift + L 입니다. 캡쳐 화면이 누락되었지만 이름은 &quot;myCell&quot;로 지정했습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/d7fe7827-c099-4451-bc1c-82045b548bf9/image.png" alt=""></p>
<p>이제 저 Table View에 리스트 형식으로 데이터를 놓아보겠습니다.
그러기 위해선 <strong>UITableViewDelegate</strong>와 <strong>UITableViewDataSource</strong> 프로토콜을 사용해야 합니다. 근본적으로 왜 그래야하는지는 지금 당장 파진 않겠습니다. 그러면 한도 끝도 없고 진도가 안 나가기 때문입니다.
MyTableViewController 클래스에 상속 시켜도 되지만, 저는 가독성을 위해 extension을 활용하여 밑에다 따로 구분해놨습니다. 이건 본인 스타일이라서 원하는대롱</p>
<p>에러나는데요</p>
<p>네</p>
<p>에러를 읽어보니, <em>&quot;너 저 프로토콜 사용하고 싶어? 그럼 필수적으로 함수 구현해라&quot;</em> 라는 의미입니다. fix 버튼을 눌러봅니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/e1b4624c-d8ab-4630-84b5-b430dea78bb1/image.png" alt=""></p>
<p>오 메서드 두 개를 만들어줬습니다. 이 두개를 필수적으로 구현해야 한다고 합니다. 이 부분 또한 깊게 파지 않겠습니다. 일단 주석을 달아 제가 이해한 메서드 역할을 기록했습니다.</p>
<pre><code class="language-swift">extension ViewController: UITableViewDelegate, UITableViewDataSource{
// 테이블뷰의 셀 개수를 정의하는 메서드
// 셀 개수를 리턴하도록 구현하면 된다.
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
        &lt;#code#&gt;
    }
    // 테이블 뷰의 각 셀을 화면에 리턴하는 메서드
    // 셀 데이터 개수만큼 호출됨
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
        &lt;#code#&gt;
    }

}</code></pre>
<p>일단 아래와 같이 코드를 아주아주 간단하게 하드코딩 하듯이 적었습니다. 한 줄씩 기록해보면,</p>
<blockquote>
<pre><code class="language-swift">return 5</code></pre>
</blockquote>
<pre><code>    - 이 테이블 뷰는 5개의 셀을 가지고 있다는 뜻입니다. 즉 화면에 5줄의 내용이 생길 것 입니다.

&gt; ```swift
let cell = tableView.dequeueReusableCell(withIdentifier: &quot;myCell&quot;, for: indexPath)</code></pre><pre><code>- 화면에 얹어져 있는 &quot;myCell&quot; 이름의 Table Cell과 연결되는 셀 타입의 상수를 생성합니다.</code></pre><pre><code class="language-swift">cell.textLabel?.text = &quot;Hello TableVIew !&quot;</code></pre>
<pre><code>- 이 상수를 이용하여 화면의 &quot;myCell&quot;의 text에 &quot;Hello TableView !&quot;를 대입합니다.</code></pre><pre><code class="language-swift">return cell</code></pre>
<pre><code>- 위의 코드로 잘 생성된 셀을 리턴합니다.</code></pre><p><img src="https://velog.velcdn.com/images/se_bb/post/adf7e583-ad4d-4722-b89b-db47396f3e80/image.png" alt=""></p>
<p>엥</p>
<p>Hello TableView ! 안보이는데요</p>
<p>네 또 코드를 추가해줘야 합니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/e136c2e1-556c-49b8-b783-582f58f84472/image.png" alt=""></p>
<p>아래 두 개 코드를 추가해줘야 각 셀들이 보입니다. 이 역시 일단은 근본적인 이해는 하지 않고, 아 필요하구나 정도로 익히고 진도를 빼겠습니다.</p>
<blockquote>
<pre><code class="language-swift"> myTableView.delegate = self
 myTableView.dataSource = self</code></pre>
</blockquote>
<pre><code>
그럼 최종적으로 아래 코드가 만들어집니다. 이걸 다시 빌드해보겠습니다.

```swift
//
//  MyTableViewController.swift
//  Swift
//
//  Created by  on 2024/10/15.
//

import UIKit

class MyTableViewController: UIViewController {

    @IBOutlet var myTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .brown
        myTableView.backgroundColor = .green
        myTableView.delegate = self
        myTableView.dataSource = self

    }

}

extension MyTableViewController: UITableViewDelegate, UITableViewDataSource {
    // 테이블뷰의 셀 개수를 정의하는 메서드
    // 언뜻보면 셀 개수만큼 호출되는 것처럼 보이지만, 셀 데이터 추가하기 전에 테이블 뷰 레이아웃을 잡기 위해, 셀 데이터 셋팅하기 전에 작업을 하면서 내부적으로 몇 번씩 호출될 수 있음
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
        return 5

    }

    // 테이블 뷰의 각 셀을 리턴하는 메서드
    // 셀 데이터 개수 만큼 호출됨
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: &quot;myCell&quot;, for: indexPath)
        cell.textLabel?.text = &quot;Hello TableVIew !&quot;
        return cell
    }


}
</code></pre><p>짠
잘 보입니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/a8fb5680-9d3b-43ae-8a54-db26b8697bc7/image.png" alt=""></p>
<pre><code class="language-swift">//
//  MyTableViewController.swift
//  Swift
//
//  Created by  on 2024/10/15.
//

import UIKit

class MyTableViewController: UIViewController {

    @IBOutlet var myTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .brown
        myTableView.backgroundColor = .green
        myTableView.delegate = self
        myTableView.dataSource = self

    }

}

extension MyTableViewController: UITableViewDelegate, UITableViewDataSource {
    // 테이블뷰의 셀 개수를 정의하는 메서드
    // 언뜻보면 셀 개수만큼 호출되는 것처럼 보이지만, 셀 데이터 추가하기 전에 테이블 뷰 레이아웃을 잡기 위해, 셀 데이터 셋팅하기 전에 작업을 하면서 내부적으로 몇 번씩 호출될 수 있음
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
        return 5

    }</code></pre>
<p><img src="https://velog.velcdn.com/images/se_bb/post/629bcc71-249b-4af3-b4ce-0c314bd20963/image.png" alt=""></p>
<h1 id="2-디버깅-해서-약간-더-살펴보기">2. 디버깅 해서 약간 더 살펴보기</h1>
<p>저 두 개의 <em>tableView()</em> 메서드가 핵심이었던 것 같습니다. 그런데 하다보니 저 두 메서드가 언제, 얼마나 호출되는지 궁금해서 살짝 코드를 변경해서 print()로 로그를 찍어봤습니다.</p>
<p>⬇️</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/ac7221f2-182a-428f-a292-596788d961f5/image.png" alt=""></p>
<p>오..
일단 cell을 리턴하는 2번째(편의상 그렇게 부르겠습니다.) tableView()는 0,1,2로 순차적으로 인덱스를 가지며 3번 호출됩니다. 코드 위쪽에 선언한 배열의 크기가 3이라 셀의 개수가 3개라서 그런 것 같습니다.</p>
<p>이해 가능. 그런데..</p>
<p>cell의 개수를 리턴하는 1번째 tableView()는 왜 3번이나 호출되는건지 모르겠습니다. 그래서 처음엔 이 메서드도 셀의 개수만큼 호출된다고 추측했습니다. 하지만..</p>
<blockquote>
<p>💡 <em>로그를 보면, numberOfRowsInSection(첫번째 tableView())이 3번 호출된 후에 cellForRowAt(두번째 tableView())이 호출되는데, 이건 셀 데이터가 추가되기 전에 항상 호출되는 것이 아닙니다. 이 동작은 테이블 뷰의 정상적인 작동 방식입니다.
테이블 뷰는 기본적으로 화면에 그려질 셀의 개수를 알아야 하고, 이를 위해 미리 numberOfRowsInSection(첫번째 tableView())을 여러 번 호출할 수 있습니다. 이 동작은 성능 최적화를 위해 이루어집니다.</em></p>
</blockquote>
<p>저의 스승님이신 챗GPT 은사님께서 알려주셨습니다.</p>
<p>결론:</p>
<p><em>&quot;셀의 개수를 리턴하는 메서드를 왜 몇 번씩 호출하냐&quot;</em>
<em>&quot;이게 다 최적화를 위한거고 정상이니까 그런 줄 알아라&quot;</em></p>
<p>가 결론이라고 볼 수 있습니다.</p>
<h1 id="최종-소스-코드">최종 소스 코드</h1>
<pre><code class="language-swift">//
//  MyTableViewController.swift
//  Swift
//
//  Created by  on 2024/10/15.
//

import UIKit

class MyTableViewController: UIViewController {

    let cellDatas = [&quot;Hello TableVIew !&quot;, &quot;This is TableView&quot;, &quot;Welcome~&quot;]

    @IBOutlet var myTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .brown
        myTableView.backgroundColor = .green

        myTableView.delegate = self
        myTableView.dataSource = self
    }


}

extension MyTableViewController: UITableViewDelegate, UITableViewDataSource {
    // 테이블뷰의 셀 개수를 정의하는 메서드
    // 언뜻보면 셀 개수만큼 호출되는 것처럼 보이지만, 셀 데이터 추가하기 전에 테이블 뷰 레이아웃을 잡기 위해, 셀 데이터 셋팅하기 전에 작업을 하면서 내부적으로 몇 번씩 호출될 수 있음
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
//        return 5
        print(&quot;tableView log!!!!!! \(section), \(cellDatas.count)&quot;)
        return cellDatas.count
    }

    // 테이블 뷰의 각 셀을 리턴하는 메서드
    // 셀 데이터 개수 만큼 호출됨
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: &quot;myCell&quot;, for: indexPath)
//        cell.textLabel?.text = &quot;Hello TableVIew !&quot;
        cell.textLabel?.text = cellDatas[indexPath.row]
        print(&quot;log !!!!!! \(cellDatas[indexPath.row]) - \(indexPath.row)&quot;)
        return cell
    }


}
</code></pre>
<h1 id="끝">끝</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[[iOS/Swift] 2. 전구껐다꼈다 앱 만들기]]></title>
            <link>https://velog.io/@se_bb/iOSSwift-2</link>
            <guid>https://velog.io/@se_bb/iOSSwift-2</guid>
            <pubDate>Wed, 31 Jan 2024 06:42:38 GMT</pubDate>
            <description><![CDATA[<h1 id="0-개요">0. 개요</h1>
<p>🙉 완성본 미리보기 🙉</p>
<blockquote>
<p>버튼으로 전구 이미지 확대&lt;-&gt;축소 시키기
switch로 전구 껐다&lt;-&gt;컸다 하기</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/se_bb/post/24b6d70f-4af1-4835-91ce-a7e255837af8/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/47854ae5-8b22-4458-8bcf-333e6a857ff6/image.png" alt=""></p>
<h2 id="1-image-view란">1) image View란</h2>
<p>말 그대로 이미지를 띄울 수 있는 객체입니다.</p>
<p>아래 리스트는 이미지 뷰에서 사용할 수 있는 확장자들입니다.</p>
<ul>
<li>.png</li>
<li>.tiff or .tif</li>
<li>.jpeg or .jpg</li>
<li>.gif</li>
<li>.bmp or .BMPf</li>
<li>.ico</li>
<li>.cur</li>
<li>.xbm</li>
</ul>
<h2 id="2-화면에-필요한-객체-얹기">2) 화면에 필요한 객체 얹기</h2>
<p>맨 위에 완성 화면을 보면 1)image View 2)button 3)switch 세 개의 객체가 보입니다.
아래 사진 속 빨간색 박스를 눌러서 3개의 객체를 화면에 추가합니다.(추가하는 자세한 방법은 이전 편 참고하면 됩니다.)</p>
<p>초록색 박스부분은 Image View의 정확한 좌표와 크기를 숫자로 지정할 수 있는 size inspector 영역입니다.
저는 이곳에서 Image View 사이즈를 150px*150px로 조정했습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/535d7696-f4eb-40cb-bfbd-034bc2ac72a4/image.png" alt=""></p>
<p>이제 저 Image View에 켜진/꺼진 전구 사진을 넣어야합니다. 그러기 위해선 이 프로젝트 폴더 내에 사진이 첨부되어 있어야 합니다. 사진도 같이 공유하겠습니다.</p>
<p>&lt;켜진전구&gt;
<img src="https://velog.velcdn.com/images/se_bb/post/43522d91-3f27-40c8-abc3-635d03d341d5/image.png" alt="">
&lt;꺼진전구&gt;(다크모드로 읽으면 잘 안보이내요..)
<img src="https://velog.velcdn.com/images/se_bb/post/51db5c7f-af8a-4f62-83a7-4e7f120373ce/image.png" alt=""></p>
<p>이 두 사진을 다운로드 받은 후, 아래 화면처럼 프로젝트 네비게이터 영역에 드래그 해서 끌고 옵니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/3e5e82c7-63b2-4d02-9cb8-fbb2b0822850/image.png" alt=""></p>
<p>그럼 아래와 같이 창이 하나 뜨는데 이 때, Destination 체크를 해줍니다.
방금 드래그해서 가져온 사진 파일 자체를 복사할거냐고 물어보는 겁니다.
체크 해제 시, 저 전구 사진의 저장 경로만 따와서 참조하는 식으로 접근하기 때문에 아예 사진을 복사해서 프로젝트 안에 넣어두는 게 좋습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/0d09ab2d-4d46-4c86-869c-e0b87bc8436e/image.png" alt=""></p>
<h2 id="3-아웃렛-변수와-액션-함수-추가하기">3) 아웃렛 변수와 액션 함수 추가하기</h2>
<blockquote>
<p>[ 필요한 아웃렛 변수 ]</p>
</blockquote>
<ul>
<li>이미지 뷰에 대한 아웃렛 변수 : 켜진전구&lt;-&gt;꺼진전구 사진 교체, 크기 확대&lt;-&gt;축소 변경을 위해 접근이 필요함</li>
<li>버튼에 대한 아웃렛 변수 : 버튼 Title &#39;확대&#39;&lt;-&gt;&#39;축소&#39;로 변경을 위해 접근이 필요함</li>
</ul>
<blockquote>
<p>[ 필요한 액션 함수 ]</p>
</blockquote>
<ul>
<li>버튼에 대한 액션 함수 : 눌렀을 때 전구 이미지를 확대 or 축소시키는 함수가 필요함</li>
<li>스위치에 대한 액션 함수 : 눌렀을 때 전구 이미지를 변경시키는 함수가 필요함</li>
</ul>
<p>아웃렛 변수 추가를 위해 아래와 같이 보조편집기를 열어줍니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/75fedf0b-5fe3-4ee7-bf9e-3be2f9b14b11/image.png" alt=""></p>
<p>그리고 아래와 같이 객체 우클릭(or Ctrl+클릭) &gt; controller.swift 소스파일에 쭉 드래그합니다. 캡쳐 성공ㅎ</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/b2a97491-47b9-41d2-b467-7dc6ae0fd25a/image.png" alt=""></p>
<p>변수명을 &#39;imgLamp&#39;로 설정하고 Connect 클릭</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/a62515e8-bf1d-4ae5-b12b-5a4952e41327/image.png" alt=""></p>
<p>버튼도 똑같은 방법으로 아웃렛 변수를 만들어줍니다.
그렇게 아래와 같이 두 개의 아웃렛 변수가 추가된 상태입니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/7557ac5c-1b0a-4da6-92be-0df59ceeba5d/image.png" alt=""></p>
<p>이제 확대&lt;-&gt;축소 버튼을 클릭했을 때 실행될 액션 함수를 추가하겠습니다.
아웃렛 변수 만들었을 때와 똑같이 Ctrl+클릭 &gt; 드래그</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/893c3d82-7d22-4eb6-82f8-4464fe6ac8ed/image.png" alt=""></p>
<p>메소드명은 &#39;onBtnClick&#39;으로 설정
Type은 &#39;Any&#39; -&gt; &#39;UIButton&#39; 으로 변경합니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/e624b9cb-4a99-4dbb-9064-082bf1c0e12e/image.png" alt=""></p>
<p>버튼과 동일하게 switch 객체에 대한 액션 함수도 생성합니다.
사용자가 switch를 껐다&lt;-&gt;켰다 할 때마다 전구 이미지를 바꿔줘야 하기 때문입니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/dbfeacb3-ef8c-4dda-9430-7ffd133e50ab/image.png" alt=""></p>
<h2 id="액션-함수-구현하기">액션 함수 구현하기</h2>
<pre><code class="language-swift">//
//  ViewController.swift
//  HelloWorld
//
//  Created by  on 2024/01/29.
//
import UIKit
class ViewController: UIViewController {
    @IBOutlet var imgLamp: UIImageView!
    @IBOutlet var btnResize: UIButton!

    var isZoom: Bool = false   //현재 이미지가 확대된 상태인지 여부
    var imgOn: UIImage?         //켜진 전구 이미지
    var imgOff: UIImage?        //꺼진 전구 이미지


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        // 전구 이미지 가져오기
        imgOn = UIImage(named:&quot;light_On.png&quot;)
        imgOff = UIImage(named: &quot;light_Off.png&quot;)

        imgLamp.image = imgOn   //켜진 전구 이미지로 시작

    }
    // 버튼 클릭 시 이미지 Resize하는 액션 함수
    @IBAction func onBtnClick(_ sender: UIButton) {
        let scale: CGFloat = 1.5
        var newWidth: CGFloat, newHeight: CGFloat   //변경된 픽셀 사이즈

        // 현재 확대된 상태면 &gt; 줄여줌
        if (isZoom){
            newWidth = imgLamp.frame.width / scale
            newHeight = imgLamp.frame.height / scale
            btnResize.setTitle(&quot;확대&quot;, for: .normal)
        }
        else{   //축소된 상태 &gt; 키워줌
            newWidth = imgLamp.frame.width * scale
            newHeight = imgLamp.frame.height * scale
            btnResize.setTitle(&quot;축소&quot;, for: .normal)
        }

        isZoom = !isZoom    //사진 크기 상태값 변경
        imgLamp.frame.size = CGSize(width: newWidth, height: newHeight) //이미지 뷰 Resize


    }

    // switch 변경 시 이미지 변경하는 액션 함수
    @IBAction func onSwitch(_ sender: UISwitch) {
        // 스위치 On으로 바꼈다면 &gt; 켜진 전구 이미지로 변경
        if (sender.isOn){
            imgLamp.image = imgOn
        }
        else{
            imgLamp.image = imgOff
        }

    }

}</code></pre>
<h2 id="실행-결과">실행 결과</h2>
<p>⬇️ 앱 실행 직후
<img src="https://velog.velcdn.com/images/se_bb/post/24b6d70f-4af1-4835-91ce-a7e255837af8/image.png" alt=""></p>
<p>⬇️ switch 버튼 껐을 때
<img src="https://velog.velcdn.com/images/se_bb/post/47854ae5-8b22-4458-8bcf-333e6a857ff6/image.png" alt=""></p>
<p>⬇️ &#39;확대&#39; 버튼 눌렀을 때
<img src="https://velog.velcdn.com/images/se_bb/post/fdb37a44-5d24-41f6-b208-416820b793a7/image.png" alt=""></p>
<p>정렬충으로서 전구가 확대되면서 중앙 벗어나는 거 못 봐주겠슴..</p>
<h2 id="뷰-위치-조정하기">뷰 위치 조정하기</h2>
<p>책에 나와있지 않는 부분이라 구글링+삽질 꽤나 했습니다..</p>
<blockquote>
<p>imgLamp.frame.origin.x = Double형의 어떤 값
imgLamp.frame.origin.y = Double형의 어떤 값</p>
</blockquote>
<p>이런식으로 원하는 좌표 값을 대입하면 됩니다.</p>
<p>제 화면 기준으로 작은 전구 사진일 때 중앙 x좌표=121,
큰 전구 사진일 때 중앙 x좌표=84로 둘의 차이는 37이더라구요
그래서 버튼 누를 때 마다 37을 더하거나 빼줌으로서 x 좌표를 이동시켰습니다.</p>
<h2 id="코드-수정-후-실행-결과">코드 수정 후 실행 결과</h2>
<p>⬇️ 앱 실행 직후</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/c23acd64-a3e7-488c-bd02-4f5aaa913881/image.png" alt=""></p>
<p>⬇️ &#39;확대&#39;버튼 눌렀을 때</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/39ed718f-ec3d-4217-863a-2f25ac31e2b5/image.png" alt=""></p>
<p>⬇️ &#39;축소&#39;버튼 눌렀을 때</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/b3d5a0b1-ea56-4b7a-b90a-14371b9a2b8b/image.png" alt=""></p>
<h2 id="최종-코드">최종 코드</h2>
<pre><code class="language-swift">//
//  ViewController.swift
//  HelloWorld
//
//  Created by  on 2024/01/29.
//

import UIKit

class ViewController: UIViewController {


    @IBOutlet var imgLamp: UIImageView!
    @IBOutlet var btnResize: UIButton!

    var isZoom: Bool = false   //현재 이미지가 확대된 상태인지 여부
    var imgOn: UIImage?         //켜진 전구 이미지
    var imgOff: UIImage?        //꺼진 전구 이미지


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        // 전구 이미지 가져오기
        imgOn = UIImage(named:&quot;light_On.png&quot;)
        imgOff = UIImage(named: &quot;light_Off.png&quot;)

        imgLamp.image = imgOn   //켜진 전구 이미지로 시작

    }

    // 버튼 클릭 시 이미지 Resize하는 액션 함수
    @IBAction func onBtnClick(_ sender: UIButton) {
        let scale: CGFloat = 1.5
        let distance: CGFloat = 37  //이미지 크기 변경에 따른 중앙 x 좌표
        var newWidth: CGFloat, newHeight: CGFloat   //변경된 픽셀 사이즈

        // 현재 확대된 상태면 &gt; 줄여줌
        if (isZoom){
            newWidth = imgLamp.frame.width / scale
            newHeight = imgLamp.frame.height / scale
            btnResize.setTitle(&quot;확대&quot;, for: .normal)
            imgLamp.frame.origin.x = imgLamp.frame.origin.x + distance  //중앙정렬
        }
        else{   //축소된 상태 &gt; 키워줌
            newWidth = imgLamp.frame.width * scale
            newHeight = imgLamp.frame.height * scale
            btnResize.setTitle(&quot;축소&quot;, for: .normal)
            imgLamp.frame.origin.x = imgLamp.frame.origin.x - distance  //중앙정렬
        }

        isZoom = !isZoom    //사진 크기 상태값 변경
        imgLamp.frame.size = CGSize(width: newWidth, height: newHeight) //이미지 뷰 Resize



    }

    // switch 변경 시 이미지 변경하는 액션 함수
    @IBAction func onSwitch(_ sender: UISwitch) {
        // 스위치 On으로 바꼈다면 &gt; 켜진 전구 이미지로 변경
        if (sender.isOn){
            imgLamp.image = imgOn
        }
        else{
            imgLamp.image = imgOff
        }

    }

}
</code></pre>
<p>편-안</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[iOS/Swift] 1. 이름 출력하기]]></title>
            <link>https://velog.io/@se_bb/iOSSwift-1.-Hello-World</link>
            <guid>https://velog.io/@se_bb/iOSSwift-1.-Hello-World</guid>
            <pubDate>Tue, 30 Jan 2024 00:19:34 GMT</pubDate>
            <description><![CDATA[<h1 id="0-개요">0. 개요</h1>
<p>💯 오늘 포스팅 목표</p>
<blockquote>
<ul>
<li>화면에 필요한 객체들 배치하기</li>
</ul>
</blockquote>
<ul>
<li>아웃렛 변수, 액션 함수 개념 이해하기</li>
<li>아웃렛 변수, 액션 함수 구현하기</li>
</ul>
<p>🙉 완성본 미리보기 🙉
    - 사용자로부터 이름을 입력받고 &quot;Hello, ㅇㅇㅇ&quot; 화면에 띄우기</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/1b4a89e2-b66f-4d87-95d9-f59b8dd3003a/image.png" alt=""></p>
<h1 id="1-화면-구현">1. 화면 구현</h1>
<h2 id="1-레이블-추가하기">1) 레이블 추가하기</h2>
<p><img src="https://velog.velcdn.com/images/se_bb/post/59bbbeba-39b4-427e-948c-ab3793babd59/image.png" alt=""></p>
<p>새 프로젝트를 만든 후, Main.storyboard 파일을 열어줍니다.
그 후, 오른쪽 상단에 &#39;+&#39;를 누릅니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/a9ab0d30-0df6-46bb-b905-ead3c15b6b57/image.png" alt=""></p>
<p>화면에 추가할 수 있는 다양한 객체들이 보입니다.
이 중에서, 텍스트를 보여주는 레이블을 꾹 눌러 드래그하여 스토리보드에 올립니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/af68ab72-9956-433d-a64b-444f1b0d3781/image.png" alt=""></p>
<p>먼저, 텍스트를 &quot;hello, &quot;로 수정합니다.
그리고 우측을 보면 label 객체에 대한 attribute inspector가 보입니다.
label 객체의 폰트, 크기, 배경색, 정렬 등등 다양한 속성을 컨트롤할 수 있는 창입니다.
이 attribute inspector로 원하는 대로 꾸미면 됩니다.
저는 간단하게 중앙 정렬 정도만 하고 넘어갔습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/c35141c4-aea2-4916-b2b1-bd2a6965ad36/image.png" alt=""></p>
<p>동일한 방식으로 &quot;Name :&quot; label 객체를 추가했습니다.</p>
<h2 id="2-텍스트-필드-추가하기">2) 텍스트 필드 추가하기</h2>
<p>이제 사용자로부터 이름을 입력 받을 수 있는 객체인 text field를 추가합니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/9f785ee8-4d7a-4b3a-a9f2-734e165cd374/image.png" alt=""></p>
<p>역시나, 우측 맨 상단에 &#39;+&#39; 버튼을 누릅니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/b068684e-8b6c-42b8-a870-06652cc4e969/image.png" alt=""></p>
<p>&#39;text field&#39; 객체를 꾸욱 클릭하여 드래그해서 화면에 놓습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/cc1e99f3-1b0b-4e39-ad2e-81532317ad5c/image.png" alt=""></p>
<p>&#39;Name : &#39; 레이블 객체 옆에 배치했습니다.</p>
<h2 id="3-버튼-추가하기">3) 버튼 추가하기</h2>
<p>마지막으로 사용자가 이름을 모두 입력한 후에 누를 버튼 기능을 하는 button 객체를 추가합니다.
위와 방법은 똑같으니, 캡쳐 화면들은 생략하겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/e25fa20c-9ac6-43b2-a540-1c96ed789e8f/image.png" alt=""></p>
<p>버튼을 추가하고 옆에 attribute inspector 영역을 활용하여 배경색을 채우고, 검정색으로 바꿨습니다.
전 무채색을 좋아하거든요..</p>
<h1 id="2-동작-구현">2. 동작 구현</h1>
<h2 id="1-아웃렛-변수와-액션-함수-구현하기">1) 아웃렛 변수와 액션 함수 구현하기</h2>
<p>우리가 스토리보리에 추가한 레이블, 텍스트 필드, 버튼과 같은 객체를 선택하고 내용, 속성을 변경하거나 동작을 구현하기 위해서는
해당 객체에 접근할 수 있는 &#39;<strong>아웃렛 변수</strong>&#39;와 동작을 정의한 함수인 &#39;<strong>액션 함수</strong>&#39;가 필요합니다.</p>
<p>제가 이해한 방식으로 설명 드리자면 앱 실행 중, 화면의 텍스트나 버튼의 색상 등등을 바꿔줘야할 때가 있잖아요? 그 때 controller.swift와 같은 소스파일에서 스토리보드 위에 올라가 있는 객체들을 &#39;<strong>아웃렛 변수</strong>&#39;를 이용해서 접근한다고 보면 됩니다.
<strong>액션 함수</strong>는 버튼을 눌렀을 때, 사용자가 키패드의 &#39;Done&#39; 버튼을 눌렀을 때 등 객체의 다양한 이벤트가 발생했을 시 동작하는 함수이구요.</p>
<p>그래서 위에 만들어놓은 알맹이 없는 화면에 아웃렛 변수와 액션함수를 구현해서
사용자로부터 이름을 입력받고 -&gt; 버튼을 눌렀을 때 -&gt; 사용자의 이름이 &#39;Hello, ㅇㅇㅇ&#39;로 출력되도록 구현할 겁니다.
<br>
ㄱㄱ
<br></p>
<h2 id="2-아웃렛-변수-추가">2) 아웃렛 변수 추가</h2>
<p>아웃렛 변수를 추가하기 위해서는 xcode 화면을 둘로 쪼개야합니다. 드래깅을 통해 아웃렛 변수를 선언하기 때문입니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/705ab5f7-e02a-4b65-b9c7-226c57515ab8/image.png" alt=""></p>
<p>우측 상단에 가로줄 여러개가 그려져 있는 모양 클릭 &gt; &#39;Assistant&#39; 클릭</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/abe3fc9b-cfcf-4140-b022-652209f8f154/image.png" alt=""></p>
<p>이제 우측에 소스파일도 같이 보여줍니다.
이 상태에서 화면 위에 있는 객체들의 아웃렛 변수를 우측 소스파일에 선언할겁니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/16a3f090-940a-41d7-a727-c10d3702e1e8/image.png" alt=""></p>
<p>노력 많이 해봤는데.. 드래깅 하는 찰나는 캡쳐를 못하겠네요
Hello 레이블 우클릭한 상태에서(or ctrl+클릭) &gt; viewDidLoad() 위까지 쭉 끌어다 놓으면
위와 같은 작은 꼬마창이 뜹니다.
Hello 레이블에 대한 아웃렛 변수 이름이나 Type을 정의하면 됩니다.
저는 Name - lblHello 으로 설정했습니다.
나머지 속성들은 그대로 뒀구요.
그리고 아래 &#39;Connect&#39; 버튼 클릭하면</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/a727daea-fdb7-456e-8417-e2551780f283/image.png" alt=""></p>
<p>위와 같이 Hello 레이블에 접근할 수 있는 아웃렛 변수가 선언되었습니다.
swift 문법에 대해서는 따로 다루진 않겠습니다.
&#39;아, 이제 lblHello 라는 이름으로 저 레이블에 접근할 수 있겠구나&#39; 정도로만 쓸게요</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/0a7cc18a-0562-42d1-9f38-85b35f62798e/image.png" alt=""></p>
<p>이렇게 2개의 레이블, 1개의 텍스트 필드 객체에 대한 아웃렛 변수를 선언했습니다. 버튼에 대한 아웃렛 변수는 이번 포스팅에서 하지 않습니다.
버튼 속성이나 버튼 값을 조작할 일이 없기 때문입니다.
하고 싶으면 해두 돼요 근데</p>
<h2 id="3-액션-함수-추가">3) 액션 함수 추가</h2>
<p>이제 버튼을 눌렀을 때 &#39;Hello, ㅇㅇㅇ&#39;라고 출력 할 수 있도록 액션 함수를 구현하겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/1fceaa0e-340d-4e45-91aa-8cf124b3e0a6/image.png" alt=""></p>
<p>아웃렛 변수 선언 방법과 똑같이 버튼 우클릭(or Ctrl+클릭) 상태 &gt; ViewDidLoad() 함수 밑에 드래그 합니다.
일반적으로 액션 함수는 ViewDidLoad() 밑에 구현합니다.
Name : onClick
Type : UIButton 으로 설정</p>
<p>나머지 속성은 건들지 않습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/29f65b01-d007-4c83-a8e2-f87b1239361f/image.png" alt=""></p>
<p>위와 같이 onClick 함수가 생겼습니다.
이제 여기에 사용자가 이름을 입력하고 버튼을 누르면
lblHello에 사용자의 이름을 추가하는 기능을 구현합니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/c1414d39-97c3-419a-86ff-73566e323c4e/image.png" alt=""></p>
<p>정말 간단한 한 줄 입니다.
레이블 객체 내의 text 속성을 통해 레이블에 써있는 텍스트에 접근할 수 있습니다.
&#39;!&#39; 기호는 swift에서 옵셔널 변수를 옵셔널 강제 해제하는 문법인데 설명 생략하겠습니다.
하지만 중요한 개념이므로 꼭 구글링해서 읽어보세요 ~</p>
<h1 id="4-결과-확인">4. 결과 확인</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/5b28ae90-42d2-42fd-a13f-3b108f864a6c/image.png" alt=""></p>
<p>⬆️ 빌드 직 후</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/04a38e77-df1c-4c73-abc9-e80762fd24db/image.png" alt=""></p>
<p>⬆️ 이름 입력 후, 버튼 눌렀을 때</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[iOS/Swift] 0. iOS 앱 개발 가보자고..🔥]]></title>
            <link>https://velog.io/@se_bb/iOSSwift-iOS-App-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@se_bb/iOSSwift-iOS-App-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Sun, 17 Dec 2023 10:08:40 GMT</pubDate>
            <description><![CDATA[<h1 id="미리요약">미리요약</h1>
<blockquote>
<ul>
<li>xcode 설치</li>
</ul>
</blockquote>
<ul>
<li>App 프로젝트 구조 간단 설명</li>
<li>처음부터 힘 빼지 않고 꾸준히 하기로 했습니다(제발..😇)</li>
</ul>
<h1 id="xcode-설치">xcode 설치</h1>
<p>이거 설치하려고 맥북 긁었습니다. 이제 나한테 없는 건 에어팟 맥스뿐..</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/57c90961-fce3-40d5-a05a-86bc305b394b/image.png" alt="">
AppStore &gt; &#39;xcode&#39; 검색 &gt; 설치하면 됩니다.
회사에선 버전 13으로 개발중인데 어차피 개인공부용이니까 버전 안 맞춤</p>
<p>설치 생각보다 오래 걸립니다. xcode 설치+시뮬레이터 설치시간까지 걸립니더ㅜ</p>
<h1 id="프로젝트-생성">프로젝트 생성</h1>
<p>설치가 완료되면 App 프로젝트를 생성해봅니다.
<img src="https://velog.velcdn.com/images/se_bb/post/9eda6285-90b6-4179-bde0-5c2851c255af/image.png" alt=""></p>
<p>&#39;Create New Project...&#39; 클릭</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/7dcd1a44-24b1-4f1c-b45c-b1d9babe19c4/image.png" alt=""></p>
<p>&#39;iOS &gt; App &gt; Next&#39; 클릭</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/71d01d21-bd85-4964-91ac-1901d4de5f7c/image.png" alt=""></p>
<p>Product Name: 개발하고자 하는 앱 이름를 입력합니다.
Team: default 옵션인 &#39;none&#39;으로 해도 되지만 어차피 빌드 돌릴 때 에러납니다. xcode에 이메일 계정 하나 추가하면 &#39;Personal Team&#39;으로 하나 생기는데 그걸로 설정하면 됩니다.
Organization Identifier: 개인 혹은 회사의 식별을 위한 고유한 URL입니다. 일반적으로 도메인 역순으로 기입합니다. xcode가 자동으로 생성해줍니다.
Bundle Identifier: 앱 식별자입니다. 다른 앱들과 구별하기 위한 용도이므로 유일한 값이 됩니다.
Interface: Storyboard로 선택합니다.
Language: Swift 선택합니다.
☑️ include Tests 해제 합니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/11101aaf-c78b-43a0-9090-89b2ba4cc9fa/image.png" alt=""></p>
<p>프로젝트를 저장할 경로를 결정합니다. 저는 보통 앱 이름과 똑같은 폴더를 생성해서 그 안에 저장합니다. 캡처는 HelloWorld2로 되어있는데 나중에 정정했습니다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/c223de9a-a38f-475d-a87b-def6b421bdc3/image.png" alt=""></p>
<p>프로젝트가 생성됐습니다.
생성 직후에 뜨는 창은 프로젝트 환경설정하는 창이라고 보면 됩니다. 여기서
Minimum deployments: <del>12.0으로 최대한 낮춥니다.</del> -&gt; 13.0으로 수정했습니다.(Appdeleagate에서 에러남)
deployment Info: iPhone &amp; iPad <strong><em>Portrait</em></strong> 만 체크✅</p>
<blockquote>
<p>deployment Info</p>
</blockquote>
<ul>
<li>앱이 지원하는 화면 방향을 설정합니다.</li>
<li>Portrait: 세로 정방향</li>
<li>Upside Down: 세로 거꾸로</li>
<li>Landscape Left: 왼쪽으로 눕혔을 때</li>
<li>Landscape right: 오른쪽으로 눕혔을 때</li>
</ul>
<h1 id="프로젝트-파일-구조">프로젝트 파일 구조</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/b299863c-56c4-4c35-b992-0066d9999e18/image.png" alt=""></p>
<p>프로젝트 생성 직후에 생기는 파일들입니다.</p>
<ol>
<li><p>AppDelegate.swift</p>
<ul>
<li>앱의 전반적인 생명주기에 대해 관리하는 파일 입니다.</li>
<li>앱 구동 시, 앱이 실행중일 때, 백그라운드로 진입했을 때, 앱 종료 시 등등 일 때 수행하고 싶은 동작이 있으면 이 파일에 와서 코딩하면 됩니다.</li>
</ul>
</li>
<li><p>SceneDelegate.swift</p>
<ul>
<li>사용자 인터페이스(UI)의 실행주기를 관리하는 파일입니다.</li>
<li>⚠️여긴 잘 모르겠어서 나중에 보충⚠️</li>
</ul>
</li>
<li><p>ViewController.swift</p>
<ul>
<li>화면에 보이는 뷰에서 해야할 동작이나 상호작용을 코딩하는 파일입니다.</li>
<li>우리가 일반적으로 가장 많이 코딩하게 될 파일입니다.</li>
<li>하나의 뷰 당 하나의 뷰컨트롤러 파일이 필요합니다.</li>
</ul>
</li>
</ol>
<ol start="4">
<li>Main.storyboard<ul>
<li>화면에 있는 뷰의 모습, 뷰들 간의 관계를 그림으로 표현한 파일입니다.</li>
</ul>
</li>
</ol>
<ol start="5">
<li>Assets.xcassets<ul>
<li>앱의 아이콘을 보관하는 장소입니다.</li>
<li>이 안에 단순히 아이콘 이미지만 때려 넣으면 되는 줄 알았는데..</li>
<li>json파일도 필요합니다;;</li>
<li>다행히 아이폰 아이콘 생성 사이트가 있어서 편하게 생성 가능합니다.</li>
</ul>
</li>
</ol>
<ol start="6">
<li><p>LaunchScreen.storyboard</p>
<ul>
<li>앱 실행 시 잠시 나타나는 스플래시 화면을 만드는 스토리보드입니다.</li>
<li>&#39;로딩중~&#39; 화면 이라고 보면 될 것 같습니다.</li>
</ul>
</li>
<li><p>Info.plist</p>
<ul>
<li>앱이 실행되는 데 필요한 정보를 기입하는 곳입니다.</li>
<li>외부 library 경로 저장하고 그렇더라구요</li>
</ul>
</li>
</ol>
<p>끝.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] - 둘만의 암호]]></title>
            <link>https://velog.io/@se_bb/%EB%91%98%EB%A7%8C%EC%9D%98%EC%95%94%ED%98%B8</link>
            <guid>https://velog.io/@se_bb/%EB%91%98%EB%A7%8C%EC%9D%98%EC%95%94%ED%98%B8</guid>
            <pubDate>Tue, 29 Aug 2023 05:27:31 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/155652">문제 보기</a></p>
<h1 id="1차-접근">1차 접근</h1>
<ol>
<li>index만큼 뒤의 알파벳을 바로 구한다.(1차변경) -&gt; cOldChar + index
 (이 때 z 넘어가지 않도록 작업)</li>
<li>원래 알파벳 &lt; skip배열 &lt; 새 알파벳 사이를 학인한다.</li>
<li>2번에 해당하는 skip 배열 원소(알파벳)의 개수를 센다.</li>
<li>새 알파벳 3번에서 구한 개수만큼 뒤의 알파벳으로 변경해준다.(2차변경)</li>
</ol>
<h1 id="1차-오답">1차 오답</h1>
<pre><code class="language-java">class Solution {
    public String solution(String s, String skip, int index) {
        String answer = &quot;&quot;;
        char[] cArrAnswer = new char[s.length()];

        for(int i=0;i&lt;s.length();i++){
            char cOldChar = s.charAt(i);
            int nPlusIndex = 0;
            int cNewChar = (cOldChar+index) &gt; 122 ? (cOldChar+index) % 123 + 97 :  (cOldChar+index) % 123;
            for(int j=0;j&lt;skip.length();j++){
                if ( (int)cOldChar &lt; (int)skip.charAt(j) &amp;&amp;  (int)skip.charAt(j) &lt;  cNewChar ){

                    nPlusIndex++;

                }

            }
            cNewChar = (cNewChar+nPlusIndex) &gt; 122 ? (cNewChar+nPlusIndex) % 123 + 97 :  (cNewChar+nPlusIndex) % 123;
            cArrAnswer[i] = (char)(cNewChar);
        }

        answer = new String(cArrAnswer);
        return answer;
    }
}</code></pre>
<h1 id="원인">원인</h1>
<p>1차 접근 순서에서 1.에 오류가 있었다.
index만큼 뒤의 알파벳을 한꺼번에 계산해서 찾으면 z-&gt;a로 넘어가는 경우,
2. if문을 건너뛰어버리기 때문이다.
애초에 대소비교로 skip 배열 내를 탐색하는 거 자체가 잘못됐었다.
알파벳을 뒤로 하나씩 바꿔보면서 skip 배열에 그 알파벳이 있는지 확인하고 작업하는 게 핵심 접근이었다.</p>
<h1 id="접근-방법">접근 방법</h1>
<p>알파벳을 뒤로 하나씩 바꿔보면서 skip 배열에 그 알파벳이 있는지 확인하고 작업</p>
<h1 id="최종-코드">최종 코드</h1>
<pre><code class="language-java">class Solution {
    public String solution(String s, String skip, int index) {
        String answer = &quot;&quot;;
        char[] cArrAnswer = new char[s.length()];

        for(int i=0;i&lt;s.length();i++){
            char cOldChar = s.charAt(i);
            int cNewChar = cOldChar;
            // index 길이만큼 반복
            for(int j=0;j&lt;index;j++){
                cNewChar = cNewChar + 1;    // 알파벳 1자씩 뒤로
                if (cNewChar &gt; 122) {   //&#39;z&#39;를 벗어나는 경우
                    cNewChar = (int)&#39;a&#39;;    // &#39;a&#39;로 돌아온다
                }

                //바꾼 문자가 skip해야 할 문자인지 확인하고 건너뛴다
                for(int p =0;p&lt;skip.length();p++){
                    if ((char)cNewChar == skip.charAt(p)){
                        --j;

                        break;
                    }
                }

            }

            cArrAnswer[i] = (char)cNewChar;

        }

        answer = new String(cArrAnswer);
        return answer;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] - 명예의 전당(1)]]></title>
            <link>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EB%AA%85%EC%98%88%EC%9D%98-%EC%A0%84%EB%8B%B91</link>
            <guid>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EB%AA%85%EC%98%88%EC%9D%98-%EC%A0%84%EB%8B%B91</guid>
            <pubDate>Sat, 05 Aug 2023 08:06:23 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/138477">문제 링크로 넘어가기</a></p>
<h1 id="접근-방법">접근 방법</h1>
<p>굳~이 길이가 k인 명예의 전당 배열을 만들진 않고, 그냥 배열에 통으로 넣었다.</p>
<ol>
<li>점수를 일단 넣는다.</li>
<li>내림차순 정렬</li>
<li>배열에 저장된 점수의 개수 &gt;= k이면
 3-1. k번째 점수가 최하위</li>
<li>배열에 저장된 점수의 개수 &lt; k 이면
 4-1. 오른쪽 끝에 있는 점수가 최하위</li>
</ol>
<h1 id="소스코드">소스코드</h1>
<pre><code class="language-java">import java.util.*;

class Solution {
    public int[] solution(int k, int[] score) {
        int[] answer = new int[score.length];
        ArrayList&lt;Integer&gt; winners = new ArrayList&lt;&gt;();

        //1. score의 길이만큼 반복
        for(int i=0;i&lt;score.length;i++){
            //2. 명예의전당 배열에 i번째 점수를 넣는다
            winners.add(score[i]);
            //3. 내림차순 정렬한다.
            Collections.sort(winners, Collections.reverseOrder());
            //4. 명에의전당 배열 k-1번째 원소를 answer에 저장한다.
            if (winners.size() &lt; k) {
                answer[i] = winners.get(winners.size()-1);
            }
            else{
                answer[i] = winners.get(k-1);
            }
        }


        return answer;
    }
}</code></pre>
<h1 id="필요했던-개념">필요했던 개념</h1>
<h2 id="collectionssort">Collections.sort()</h2>
<blockquote>
</blockquote>
<p>Collections.sort(arraylist);    //오름차순
Collections.sort(arraylist, Collections.reverseOrder());// 내림차순</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] - 대충 만든 자판]]></title>
            <link>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EB%8C%80%EC%B6%A9-%EB%A7%8C%EB%93%A0-%EC%9E%90%ED%8C%90</link>
            <guid>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EB%8C%80%EC%B6%A9-%EB%A7%8C%EB%93%A0-%EC%9E%90%ED%8C%90</guid>
            <pubDate>Sun, 30 Jul 2023 12:22:37 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/160586#">문제 링크로 넘어가기</a></p>
<h1 id="접근-방법">접근 방법</h1>
<ol>
<li>주어진 키배열의 모든 알파벳의 최소 클릭 수 저장</li>
<li>targets 반복
 2-1 각 알파벳의 클릭 수 더하기
 2-2 없으면 반복문 멈추고 -1로 결론짓고 다음 target 문자열로 넘어가기</li>
</ol>
<h1 id="소스코드">소스코드</h1>
<pre><code class="language-java">import java.util.*;

class Solution {
    public int[] solution(String[] keymap, String[] targets) {
        int[] answer = new int[targets.length];
        HashMap&lt;Character, Integer&gt; map = new HashMap&lt;&gt;();

        // keymap 위 모든 알파벳의 최소 클릭 수 구하기
        for(int i=0;i&lt;keymap.length;i++){


            // 최소 클릭수로 덮어씌우기 위해 문자열 끝부터 시작
            for(int j=0;j&lt;keymap[i].length();j++){


                if (map.containsKey(keymap[i].charAt(j))) {
                    // 최소 클릭 수가 뒤에 나왔을 때 갱신
                    Integer nCurrCnt = map.get(keymap[i].charAt(j));
                    if (nCurrCnt &gt; (j+1)){
                        map.put(keymap[i].charAt(j),j+1);
                    }
                }
                else {
                    map.put(keymap[i].charAt(j),j+1);
                }

            }
        }


        // 모든 targets 단어에 대해 반복
        for(int i=0;i&lt;targets.length;i++){
            int nCnt = 0;
            for(int j=0;j&lt;targets[i].length();j++){
                char alpha = (targets[i].charAt(j));
                Integer nMinClick = map.get(alpha);
                if ( nMinClick != null ) {
                    nCnt += nMinClick;
                }
                else{
                    nCnt = -1;  // i번째 단어는 작성할 수 없음
                    break;
                }
            }
            answer[i] = nCnt;

        }



        return answer;
    }
}</code></pre>
<h1 id="필요했던-개념">필요했던 개념</h1>
<h2 id="hashmapcontainskeyk">HashMap.containsKey(k)</h2>
<blockquote>
<p>해시맵 안 데이터 중 키 값 k가 있는지 없는지 확인하는 함수
반환값 : boolean</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[iOS/Objective-C] 키보드를 감추는 iOS 앱 만들기]]></title>
            <link>https://velog.io/@se_bb/iOSObjective-C-%ED%82%A4%EB%B3%B4%EB%93%9C%EB%A5%BC-%EA%B0%90%EC%B6%94%EB%8A%94-iOS-%EC%95%B1-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@se_bb/iOSObjective-C-%ED%82%A4%EB%B3%B4%EB%93%9C%EB%A5%BC-%EA%B0%90%EC%B6%94%EB%8A%94-iOS-%EC%95%B1-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Mon, 03 Jul 2023 07:49:14 GMT</pubDate>
            <description><![CDATA[<p>지난 포스팅의 섭씨-&gt;화씨로 변환하는 앱을 실행해보면 입력할 땐 키보드가 자동으로 올라오는데, 키보드의 return키를 누르거나 디스플레이 다른 부분을 터치해도 키보드가 사라지지 않는다.
<strong>왜냐하면 아이폰 앱은 키보드를 사라지게 하는 기능을 개발자가 직접 구현해 놓아야하기 때문이다.</strong>(..ㄴㅇ0ㅇㄱ !)</p>
<p>따라서 이번 포스팅에서는 키보드를 감추는 코드를 만들 것이다.</p>
<h1 id="예제-앱-만들기">예제 앱 만들기</h1>
<h2 id="인터페이스-ui-생성">인터페이스 UI 생성</h2>
<p>⬇️ HideKeyBoard 라는 이름의 프로젝트를 새로 생성한다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/f5313e5a-e421-42b2-8b7a-ea01a0a3851d/image.png" alt=""></p>
<p>⬇️ 텍스트를 입력 받는 text field 컨트롤을 화면에 추가하고
.h파일에 저 컨트롤 접근을 위한 아웃렛을 정의한다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/14916e5f-1c71-4c66-82af-4156c33f0daf/image.png" alt=""></p>
<h2 id="return키-눌렀을-때-키보드-감추는-동작-구현">return키 눌렀을 때 키보드 감추는 동작 구현</h2>
<p>이제 사용자가 키보드의 return키를 눌렀을 때 키보드를 감추도록 구현할 것이다.</p>
<p>⬇️ .h파일에 키보드를 감추는 동작을 할 메소드를 선언한다.
이름은 내맘대루</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/4927678b-6a52-4d65-a2c4-9185f18e3688/image.png" alt=""></p>
<p>⬇️ 그리고 .m파일로 와보자
⚠️경고문이 생겨있다⚠️
방금 선언한 메소드의 구현부가 없다고 경고를 주는 것이다.</p>
<p>보기 싫으니까 얼른 메소드를 구현하자</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/9dfed0d1-813e-4f08-9107-d79d1831e968/image.png" alt=""></p>
<p>⬇️ 쨘 간결한 한 줄 코드 완성 ~
고작 한 줄이지만 많은 설명과 개념이 들어있는 구문이다 물론 내 기쥰..
sender 객체의 메소드 resignFirstResponder()를 호출한다.
영어를 해석하면 메소드의 역할을 알 수 있다.</p>
<p>resign : 사임하다
FirstResponder : 사용자가 현재 상호작용 하고 있는 객체를 의미
(이 예제에서는 가상 키보드가 될 것임)</p>
<p>자연스럽게 해석하면 FirstResponder라는 자격을 포기하게 하는 메소드이다.</p>
<p>예를 들어 사용자가 text field를 누르면 FirstResponder 자격은 text field가 갖게 된다. 이 때, return키를 눌렀을 때 이벤트로 resignFirstResponder()를 호출하도록 구현한다면 ?
강제로 text field가 갖고 있는 FirstResponder 자격을 포기하게 할 수 있고, 그렇게 가상 키보드를 감출 수 있는 것이다 !</p>
<p><del><em>그냥 애플에서 눈치껏 자격 반납하도록 구현해줬으면..</em> 큼큼</del></p>
<br>

<p>그리고 여기서 구현이 끝났다고 생각했다..쩝
메소드를 실행시킬 시점 연결을 안했다 ㅎㅎ;;</p>
<p>return키를 눌렀을 때 동작하도록 설정해보자..</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/5015432e-c96d-4100-b051-fdf9616c729a/image.png" alt=""></p>
<p>⬇️ 우측 상단에 표시한 아이콘 클릭하면 connection Inspector가 뜬다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/5b039690-5bd3-47d0-970a-6bc2795bc675/image.png" alt=""></p>
<p>⬇️ Sent Events -&gt; Did End on Exit 이벤트 옆 원을 누른 상태로 -&gt; 아래 사진처럼 뷰 컨트롤러 아이콘까지 드래그한다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/e1897f4e-8af3-4b51-8388-fddf7c22d463/image.png" alt=""></p>
<p>⬇️ 드래깅해서 연결하면 메소드 목록들이 뜬다. textFieldRetrun을 클릭한다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/3f1ccd0c-71c5-4fc1-80ac-469fbb04b984/image.png" alt=""></p>
<p>⬇️ 이벤트와 메소드가 연결된 것을 connection Inspector에서 확인할 수 있다.</p>
<p>이제 run 해보자</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/23914c3f-1d50-40fe-8647-1f33226ad0a8/image.png" alt=""></p>
<p>⬇️ 텍스트를 처보고 return키를 눌러보자(스페이스 바 오른쪽 버튼)</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/18038b51-4686-4e15-aece-bf88ba202d19/image.png" alt=""></p>
<p>⬇️ 사라짐요 ~</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/3b696bc6-d88b-43af-8ff2-717ae16951cc/image.png" alt=""></p>
<h2 id="사용자가-백그라운드-화면-터치했을-때-키보드-감추는-동작-구현">사용자가 백그라운드 화면 터치했을 때 키보드 감추는 동작 구현</h2>
<p>⬇️ ❌ 코드 추후 설명 ❌</p>
<p>사용자가 터치한 객체가 edtText가 아니라는 것을 검사한 후 키보드를 감추기 위한 resignFirstResponder()를 호출한다.</p>
<p>🦠 마지막 줄 주석처리 안하면 컴파일 에러남 개어이없음 ㅜ</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/3c68f4cd-260e-4684-b1b0-259008e91dbb/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios/Objective-C] Objective-C로 화씨->섭씨로 변환하는 간단한 앱 구현하기]]></title>
            <link>https://velog.io/@se_bb/iosObj-C-iOS</link>
            <guid>https://velog.io/@se_bb/iosObj-C-iOS</guid>
            <pubDate>Fri, 30 Jun 2023 06:04:48 GMT</pubDate>
            <description><![CDATA[<h1 id="포스팅에-앞서">포스팅에 앞서..</h1>
<p>회사 특정 상 Objective-C로 아이폰 운영을 할 줄 알아야하는 상황이다.
2012, 2013년도에 출간된 책이 그나마 최신일뿐만 아니라 구글링을 해봐도 따라하면서 배울 수 있는 꾸준한 포스팅을 못 찾았다 ㅠㅠ
그래서 회사 선배들이 사셨던 Obj-C iOS 책들을 두 세권(알라딘 중고로 구함..) 사서 세 개를 돌려보면서 포스팅을 올릴 예정이다.
복습용이라서 부정확한 용어 사용했을 수도 있으니까 참고만 해주세여</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/c7edd767-7843-4c61-ada1-49175c19d384/image.png" alt=""></p>
<p>File -&gt; New -&gt; Project...를 누름
App 개발 할 사람 : &quot;iOS&quot; - &quot;App&quot; 선택
Objective-C 연습 할 사람 : &quot;macOS&quot; - &quot;App&quot; 선택</p>
<p>난 App개발</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/077e53cc-8468-45ba-b668-fb71ceb40307/image.png" alt=""></p>
<p>Product Name : 마음대로
Organization identifer : 대부분 회사 도메인 거꾸로 씀 없으면 마음대로
interface : Storyboard
Langauage : Objective-C</p>
<p>이름 짓는 거 빼고 다 디폴트로 두고 Next 클릭</p>
<p><br><br><br></p>
<p>보안 상 다음 화면은 캡쳐 안했는데, 프로젝트 저장할 위치 지정하면 됨.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/9077e570-aff5-4f50-88cf-61b5adbc989b/image.png" alt=""></p>
<p>프로젝트 생성 후 첫 화면이다 !
여기는 환경설정하는 화면</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/4858cb2e-f65c-49dc-8fdf-f78c1132fd6c/image.png" alt=""></p>
<p>왼쪽 상단 프로젝트 네비게이터 -&gt; main 파일</p>
<p>UI를 보여주고 이런저런 컨트롤을 배치할 수 있는 화면이다.
이 화면에서 레이블, 버튼, 입력필드 등등을 배치하면 된다.
이제 이 화면 위에 몇 가지 필요한 컨트롤들을 배치해보자.</p>
<p>오른쪽 상단 &quot;+&quot;(Library) 버튼 클릭</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/beb3f3d6-26be-4dea-970a-3a90bd6f6340/image.png" alt=""></p>
<p>text field : 사용자로부터 입력 받을 수 있는 컨트롤
이거 드래그 해서 흰 아이폰 화면 위에 얹어놓기</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/fe872e67-a9ea-4cb3-a244-4d66b4fdef1c/image.png" alt=""></p>
<p>오른쪽 보면 갑자기 복잡스러운 게 생겼다..
방금 얹은 text field에 대한 속성들이다.</p>
<p>난 숫자만 입력하도록 하고 싶으니, 속성값을 바꿔서
숫자 키패드가 뜨도록 수정해봄</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/bc73d4c5-6b27-4eba-9381-afe4e1529f08/image.png" alt=""></p>
<p>Text Input Traits - Keyboard Type : Number Pad
-&gt; 숫자 키패드가 뜨도록 설정 완료</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/23dd5641-4952-4b97-92f7-57402862fae4/image.png" alt=""></p>
<p>추가로 버튼 1개, label 1개를 더 추가했다.
label 텍스트 정렬을 중앙 정렬로 변경했다.
이건 위 스샷 오른쪽 속성 유심히 보면 있음.</p>
<p>조잡하지만 UI 완성..</p>
<p>버튼을 눌렀을 때 화씨를 섭씨로 변환하는 동작을 구현해보자</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/7b2dad0a-230d-4206-8a2e-12293acc9243/image.png" alt=""></p>
<p>여러 밑줄 아이콘 -&gt; assistant 클릭</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/b8d0925c-f9a7-4de4-ad10-257d506bf943/image.png" alt=""></p>
<p>오른쪽에 ViewController.m 을 열어준다.
물론 왼쪽에 프로젝트 네비게이터에서 직접 파일을 클릭해서 열어도 됨.
근데 화면이랑 코드 같이 보면 더 좋자나용</p>
<p>근데 .m 파일전에 .h파일에 정의 먼저 해야하니까 .h파일로 바꾸자</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/b14eded6-0242-4cd6-bc21-d96a4d9347da/image.png" alt=""></p>
<p>이제 섭씨 온도를 <strong>입력하고</strong> 버튼을 <strong>누르면</strong> 화씨 온도로 <strong>변환해서 보여주는</strong> 메소드를 구현해야한다.
그러기 위해선 1)아웃렛을 정의한 후 2) 메소드를 구현하는 과정이 필요하다.</p>
<p>아웃렛이 무엇일까 ? ㅜㅜ</p>
<h2 id="아웃렛">아웃렛</h2>
<p>ViewController 메소드에서 화면 위 컨트롤 객체에 접근하기 위해서는 아웃렛이 필요하다.
아래는 세 개의 컨트롤(label, button, text field)아웃렛을 만드는 과정이다.
아래 사진들은 컨트롤 Ctrl+클릭 -&gt; 드래그 @interface 구문 안에 위치 시켰을 때 뜨는 연결 상자이다.
<img src="https://velog.velcdn.com/images/se_bb/post/610c71c7-224a-4c16-8d67-d4184b149539/image.png" alt=""></p>
<p>버튼 컨트롤은 직접 접근해서 속성이나 값을 바꾼다기 보단, 눌렀을 때의 이벤트를 구현해야하니까
Connection : Action 으로 설정한다.
<img src="https://velog.velcdn.com/images/se_bb/post/e660469a-9765-48f6-b786-7c52bf867199/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/66013df2-8b18-4dc4-8671-50fda85dd62e/image.png" alt=""></p>
<pre><code class="language-c">#import &lt;UIKit/UIKit.h&gt;

@interface ViewController : UIViewController

@property (strong, nonatomic) IBOutlet UITextField *edtTemp;
@property (strong, nonatomic) IBOutlet UILabel *lblResult;


- (IBAction)btnOk:(id)sender;
@end
</code></pre>
<p><img src="https://velog.velcdn.com/images/se_bb/post/addba767-713d-42e1-bb96-d91b34b46cb1/image.png" alt=""></p>
<p>.m 파일로 오면 .h파일에서 정의했던 버튼 이벤트 틀이 구현되어 있다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/3291e9b5-4a31-4773-a405-bf1071c7f16a/image.png" alt=""></p>
<p>썹씨 -&gt; 화씨로 바꾸는 동작 구현 코드.
참고로 objective-C는 &quot;_edtTemp.text.doubleValue()&quot; == &quot;[_edtTemp.text doubleValue]&quot;    랑 같은 의미다.</p>
<p>&#39;.&#39;점을 쓰기 싫으면 &#39;[ ]&#39;로 묶어부고 &#39;.&#39;대신 띄어쓰기 쓰면 되나봄
<del><em>굳이;;</em></del></p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/2a74851e-1633-4cb9-9e1c-595f87c5aa3f/image.png" alt=""></p>
<p>왼쪽 상단의 재생 버튼 누르면 빌드가 되고 에뮬레이터가 생성되어서 가상 아이폰을 맥에 띄워 결과물을 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/f4656a19-a7d2-4912-9bf0-aca57c9d2805/image.png" alt=""></p>
<p>결과물 !</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/232cac25-bca5-4f2e-9640-27a3ff5c3417/image.png" alt=""></p>
<h1 id="끝✨">끝✨</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] - 공원 산책]]></title>
            <link>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EA%B3%B5%EC%9B%90-%EC%82%B0%EC%B1%85</link>
            <guid>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EA%B3%B5%EC%9B%90-%EC%82%B0%EC%B1%85</guid>
            <pubDate>Mon, 08 May 2023 13:40:44 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-설명">문제 설명</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/df303049-fa18-4ed0-ac6e-4d5f1daf2c4a/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/64e68ef6-85c8-40d7-b135-7d4ab18b03f1/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/dcd8e90f-08af-4262-aa31-5a5d9b9800b1/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/541c9930-5059-45c2-b0f2-4b3ebd781bcd/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/31a71c24-cc4a-4f52-b16c-20264a2337cb/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/572295a5-a5a5-4f0d-b9b9-fadd46060200/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/93f5fe17-72ff-4d39-9ca9-72e6b2507c3d/image.png" alt=""></p>
<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/172928">문제 링크로 넘어가기</a></p>
<h1 id="접근-방법">접근 방법</h1>
<ol>
<li>(park 반복문)강아지의 시작 위치 찾기</li>
<li>(route 반복문)좌표 이동<ul>
<li>동 서 남 북 case으로 나눠서 한 칸씩 이동하며
  1) 범위를 벗어났는지
  2) 이동한 칸에 장애물이 있는지
 검사하며 최종 좌표를 구한다.</li>
</ul>
</li>
</ol>
<h1 id="소스-코드">소스 코드</h1>
<pre><code class="language-java">import java.util.*;

class Solution {
    public int[] solution(String[] park, String[] routes) {
        int[] answer = new int[2];
        int x = -1;  //시작지점이자 최종 위치
        int y = -1;  //시작지점이자 최종 위치
        int height = park.length;   //공원 높이
        int weight = park[0].length();    //공원 넓이

        //공원 순회
        for(int i=0;i&lt;park.length;i++){
            if(park[i].indexOf(&#39;S&#39;) != -1){
                x = park[i].indexOf(&#39;S&#39;);
                y = i;
                break;
            }
        }



        // 강아지 명령 순회
        for(int i=0;i&lt;routes.length;i++){
            String[] temp = routes[i].split(&quot; &quot;);
            String vector = temp[0];        //방향
            int distance =  Integer.parseInt(temp[1]);  //거리
            int currX = x;
            int currY = y;

            if(vector.equals(&quot;E&quot;)){ //동
                boolean flag = true;
                for(int j=1;j&lt;=distance;j++){
                    currX++;
                    if(currX &gt;= weight){    //범위를 벗어났나
                        flag = false;
                        break;
                    }
                    // 장애물이 있나
                    else if(park[currY].charAt(currX) ==&#39;X&#39;){
                        flag = false;
                        break;
                    }

                }
                if (flag) {
                    x = currX;
                }
            }
            else if(vector.equals(&quot;W&quot;)){    //서
                boolean flag = true;
                for(int j=1;j&lt;=distance;j++){
                    currX--;
                    if(currX &lt; 0){
                        flag = false;
                        break;
                    }
                    else if(park[currY].charAt(currX) ==&#39;X&#39;){
                        flag = false;
                        break;
                    }

                }
                if (flag) {
                        x = currX;
                }
            }
            else if(vector.equals(&quot;S&quot;)){    //남
                boolean flag = true;
                for(int j=1;j&lt;=distance;j++){
                    currY++;
                    if(currY &gt;= height){
                        flag = false;
                        break;
                    }
                    else if(park[currY].charAt(currX) ==&#39;X&#39;){
                        flag = false;
                        break;
                    }

                }
                if (flag) {
                        y = currY;
                }
            }
            else if(vector.equals(&quot;N&quot;)){    //북
                boolean flag = true;
                for(int j=1;j&lt;=distance;j++){
                    currY--;
                    if(currY &lt; 0){
                        flag = false;
                        break;
                    }
                    else if(park[currY].charAt(currX) ==&#39;X&#39;){
                        flag = false;
                        break;
                    }

                }
                if (flag) {
                    y = currY;
                }
            }

        }

        answer[0] = y;
        answer[1] = x;

        return answer;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/MySQL] - 카테고리 별 상품 개수 구하기]]></title>
            <link>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4MySQL-%EC%B9%B4%ED%85%8C%EA%B3%A0%EB%A6%AC-%EB%B3%84-%EC%83%81%ED%92%88-%EA%B0%9C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4MySQL-%EC%B9%B4%ED%85%8C%EA%B3%A0%EB%A6%AC-%EB%B3%84-%EC%83%81%ED%92%88-%EA%B0%9C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 07 Mar 2023 14:23:06 GMT</pubDate>
            <description><![CDATA[<h1 id="문제설명">문제설명</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/07bd3c32-ee32-41ef-b3f8-334a33fd905d/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/94783460-f8b6-44b7-b076-5720aa372fee/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/45478cf2-7299-4aaf-a74b-be30c1a1323d/image.png" alt=""></p>
<h1 id="소스코드">소스코드</h1>
<pre><code class="language-sql">select substring(PRODUCT_CODE, 1, 2) as CATEGORY, count(*) as PRODUCTS
from PRODUCT
group by substring(PRODUCT_CODE, 1, 2)
order by PRODUCT_CODE asc;</code></pre>
<h1 id="필요했던-개념">필요했던 개념</h1>
<h2 id="substring컬럼명-시작idx-끝idx">substring(컬럼명, 시작idx, 끝idx)</h2>
<blockquote>
<p>컬럼을 &#39;시작idx&#39; 부터 &#39;끝idx&#39;까지 자른다.
<em>&#39;끝 idx&#39; 포함해서 자르니까 주의해야한다.</em></p>
</blockquote>
<h2 id="left컬럼명-idx">left(컬럼명, idx)</h2>
<blockquote>
<p>컬럼 값을 왼쪽에서부터 idx만큼 자른다</p>
</blockquote>
<h2 id="right컬럼명-idx">right(컬럼명, idx)</h2>
<blockquote>
<p>컬럼 값을 오른쪽에서부터 idx만큼 자른다</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] - 이진 변환 반복하기
]]></title>
            <link>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EC%9D%B4%EC%A7%84-%EB%B3%80%ED%99%98-%EB%B0%98%EB%B3%B5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EC%9D%B4%EC%A7%84-%EB%B3%80%ED%99%98-%EB%B0%98%EB%B3%B5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 08 Feb 2023 14:08:07 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/946c2394-fe55-4c3b-922b-b722618b3163/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/6d26fab8-b6a6-4eee-b160-0eba684c5df3/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/7284fb2a-e540-4f76-a726-a613c5825ab8/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/a31a84ff-7ecc-4f62-9e89-f4fa8acda19f/image.png" alt=""></p>
<h1 id="구현방식">구현방식</h1>
<p>입력 값 제한 사항을 보면, 어떤 문자열이 입력값으로 들어오던지 최소 한 번은 변환 과정을 거치기 때문에 <strong>do-while문</strong>을 사용했다.</p>
<h2 id="1번-과정-구현">1번 과정 구현</h2>
<p>문자열 s를 앞에서부터 하나씩 검사한다. &quot;0&quot;이면 count+1, &quot;1&quot;이면 새로운 문자열 변수에 &quot;1&quot;를 붙여써줘서 <strong>마치 기존 문자열에서 0을 제거한 것 처럼 만든다.</strong></p>
<p>이 사이에 변환 횟수 +1 했다.</p>
<h2 id="2번-과정-구현">2번 과정 구현</h2>
<p>1만 모아놓은 새로운 문자열의 길이를 구하고, for문을 활용해서 이진법으로 바꾼 문자열을 구한다. <em>사실 이진수로 변환하려면 2로 계속해서 나눴을 때 생기는 나머지 값들을 <strong>거꾸로</strong> 써야하지만 나의 경우, reverse하는 과정이 귀찮아서 그냥 나머지값들을 문자열에 냅다 박아놓은 후, 거꾸로 복사했다.</em></p>
<p>그렇게 구한 이진수를 가지고 1, 2번 과정을 <strong>&quot;1&quot;이 될 때까지 반복</strong>한다.</p>
<p>반복이 끝났다면 1번 과정에서 구한 <strong>0 제거 횟수</strong>와, <strong>변환 횟수</strong>를 배열에 넣어서 반환한다.</p>
<h1 id="코드">코드</h1>
<pre><code class="language-java">import java.util.*;

class Solution {
    public int[] solution(String s) {
        int[] answer = new int[2];
        int zeroCount = 0;              // 제거한 0의 개수
        int changeCount = 0;
        String newStr = &quot;&quot;;

        do{
            for(int i=0;i&lt;s.length();i++){
                if(s.charAt(i) == &#39;0&#39;){
                    zeroCount++;
                }
                else{
                    newStr += &quot;1&quot;;
                }
            }
            String binaryStr = &quot;&quot;;
            s = newStr;
            newStr = &quot;&quot;;            //초기화

            //이진변환
            int c = s.length();
            while(c!=0){
                binaryStr += (c%2);
                c /= 2;
            }

            changeCount++;         //이진변환 횟수 +1
            s = &quot;&quot;;

            for(int i=binaryStr.length()-1;i&gt;=0;i--){
                s += binaryStr.charAt(i);          //거꾸로 저장된 이진수 변환
            }  

        }while(!s.equals(&quot;1&quot;));

        answer[0] = changeCount;
        answer[1] = zeroCount;

        return answer;
    }
}</code></pre>
<h1 id="회고">회고</h1>
<p>처음에 변환 횟수가 기댓값보다 -1만큼 나와서 헤맸다. 알고보니 입력값이 &quot;1&quot;이어도 변환 과정은 무조건 한 번은 count된다는 것을 간과한 것이 원인이었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] - 기능개발]]></title>
            <link>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EA%B8%B0%EB%8A%A5%EA%B0%9C%EB%B0%9C</link>
            <guid>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EA%B8%B0%EB%8A%A5%EA%B0%9C%EB%B0%9C</guid>
            <pubDate>Wed, 04 Jan 2023 14:48:16 GMT</pubDate>
            <description><![CDATA[<h1 id="문제설명">문제설명</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/04cae193-650a-452d-a804-9cddc71bbf34/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/783a4bc5-d9b6-4b26-881b-28b0879bdeff/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/dc7955a3-99a6-445c-b51e-6863df5ae94a/image.png" alt=""></p>
<h1 id="문제접근">문제접근</h1>
<p>큐로 사부작사부작..해보다가 내 풀이 방식은 큐가 필요 없기도 하고 큐로 풀 수가 없어서 단순 배열로 풀었다.
작업량 <strong>더하고</strong>-&gt; 배포 가능 상태인지 <strong>검사하고</strong> -&gt; ...를 마지막 순서 작업을 배포할 때 까지 반복하는 게 핵심이었다.</p>
<p>다 풀고 나서 생각해보니까 ArrayList는 원소를 삭제할 경우 알아서 빈자리를 땡겨주기 때문에 걍 ArrayList에서 배포 가능한 원소를 삭제해가며 진행했어도 괜찮았을 것 같다. 그럼 굳이 변수 idx를 사용하지 않아도 괜찮았겠지...?</p>
<h1 id="소스코드">소스코드</h1>
<pre><code class="language-java">import java.util.*;

class Solution {
    public int[] solution(int[] progresses, int[] speeds) {
        ArrayList&lt;Integer&gt; answer = new ArrayList&lt;&gt;();      //답의 개수를 모르니까 ArrayList로 선언
        int[] answer2;  //최종 리턴할 answer 리턴 타입
        int idx = 0;    //가장 앞에 있는 기능의 인덱스
        do {
            for(int i=0;i&lt;progresses.length;i++){
                progresses[i] += speeds[i];     //각 기능에 개발속도 더하기
            }

            int cnt = 0;    //배포 가능한 기능의 개수
            while(progresses[idx] &gt;= 100){
                    cnt++;      //배포 기능 개수 +1
                    idx++;      //가장 앞에 있는 기능 인덱스 +1
                    if(idx &gt;= progresses.length){       //인덱스 범위를 벗어났다면 모든 기능이 배포된 것이므로
                        break;      //종료
                    }
            }

           if(cnt &gt; 0){     //배포 가능한 기능(들)이 있으면
               answer.add(cnt);     //배고 가능한 기능 개수 저장
               cnt = 0;        // 초기화
           }

        }while(idx &lt; progresses.length);        //모든 기능들을 배포할 때 까지 반복

        answer2 = new int[answer.size()];       //ArrayList -&gt; Array로 변한하기 위해

        for(int i=0;i&lt;answer.size();i++){       //최종 리턴 값 Array에 담기
            answer2[i] = answer.get(i);
        }

        return answer2;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/MySQL] - 3월에 태어난 여성 회원 목록 출력하기]]></title>
            <link>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4MySQL-3%EC%9B%94%EC%97%90-%ED%83%9C%EC%96%B4%EB%82%9C-%EC%97%AC%EC%84%B1-%ED%9A%8C%EC%9B%90-%EB%AA%A9%EB%A1%9D-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4MySQL-3%EC%9B%94%EC%97%90-%ED%83%9C%EC%96%B4%EB%82%9C-%EC%97%AC%EC%84%B1-%ED%9A%8C%EC%9B%90-%EB%AA%A9%EB%A1%9D-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 02 Jan 2023 12:30:26 GMT</pubDate>
            <description><![CDATA[<h1 id="문제설명">문제설명</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/9c3178c5-2ad6-4e0a-b6b1-bdd2ec2eee22/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/7efadde3-99ba-4d3f-b989-e74925fd2737/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/85f24db0-01b8-4fcf-91a5-9c6186d8cfe2/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/cd17798b-dfb4-413c-9712-73d7f857984b/image.png" alt=""></p>
<h1 id="핵심">핵심</h1>
<h2 id="date_formate컬럼이름-format">date_formate(컬럼이름, &quot;format&quot;)</h2>
<p><a href="https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4MYSQL-DATETIME%EC%97%90%EC%84%9C-DATE%EB%A1%9C-%ED%98%95-%EB%B3%80%ED%99%98">[프로그래머스/MySQL] - DATETIME에서 DATE로 형 변환</a> 문제에 정리해놓았으니, 중복해서 정리하지 말자^^!</p>
<h1 id="소스코드">소스코드</h1>
<pre><code class="language-mysql">select MEMBER_ID, MEMBER_NAME, GENDER, date_format(DATE_OF_BIRTH, &quot;%Y-%m-%d&quot;) as DATE_OF_BIRTH
from MEMBER_PROFILE
where TLNO is not null and
gender = &quot;W&quot; and
date_format(DATE_OF_BIRTH, &quot;%m&quot;) = &quot;03&quot;
order by MEMBER_ID ASC;</code></pre>
<h1 id="회고">회고</h1>
<p>다 풀어놓고 회원 성별 체크 안해서 스펠링 하나하나 뜯어봤다.
문제를 좀 꼼꼼히 읽자.. 이어폰 좀 빼구 ㅋ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/MYSQL] - DATETIME에서 DATE로 형 변환]]></title>
            <link>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4MYSQL-DATETIME%EC%97%90%EC%84%9C-DATE%EB%A1%9C-%ED%98%95-%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4MYSQL-DATETIME%EC%97%90%EC%84%9C-DATE%EB%A1%9C-%ED%98%95-%EB%B3%80%ED%99%98</guid>
            <pubDate>Mon, 02 Jan 2023 12:05:13 GMT</pubDate>
            <description><![CDATA[<h1 id="문제설명">문제설명</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/f7745af7-4fe3-4063-af89-f4843b3c39ca/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/881cc875-9b14-4396-ae36-b91d8df9b11e/image.png" alt=""></p>
<h1 id="핵심">핵심</h1>
<h2 id="date_formatdatetime-format">date_format(DATETIME, &quot;format&quot;)</h2>
<blockquote>
</blockquote>
<p>%Y : 4자리 년도
%y : 2자리 년도
%M : 영문 월(January ~ December)
%m : 숫자 월(00 ~ 12)
%d : 숫자 일(00 ~ 31)
%H : 시 (00 ~ 24)
%h : 시 (00 ~ 12)
%i : 분 (00 ~ 59)
%s : 초 (00 ~ 59)</p>
<pre><code class="language-mysql">select date_format(BIRTH, &quot;%Y-%m-%d&quot;)
from people;        //&quot;2023-01-02&quot; 형태로 출력

select date_format(BIRTH, &quot;%Y/%m/%d&quot;)
from people;        //&quot;2023/01/02&quot; 형태로 출력

select date_format(BIRTH, &quot;%Y.%m.%d&quot;)
from people;        //&quot;2023.01.02&quot; 형태로 출력
</code></pre>
<p><strong>구분자는 내갸 원하는 걸로 선택하면 된다.</strong></p>
<h1 id="소스코드">소스코드</h1>
<pre><code class="language-mysql"> SELECT ANIMAL_ID, NAME, date_format(DATETIME,&quot;%Y-%m-%d&quot;) as &quot;날짜&quot;
 from ANIMAL_INS
 order by ANIMAL_ID;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] - 가장 가까운 같은 글자]]></title>
            <link>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EA%B0%80%EC%9E%A5-%EA%B0%80%EA%B9%8C%EC%9A%B4-%EA%B0%99%EC%9D%80-%EA%B8%80%EC%9E%90</link>
            <guid>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EA%B0%80%EC%9E%A5-%EA%B0%80%EA%B9%8C%EC%9A%B4-%EA%B0%99%EC%9D%80-%EA%B8%80%EC%9E%90</guid>
            <pubDate>Mon, 02 Jan 2023 11:43:44 GMT</pubDate>
            <description><![CDATA[<h1 id="문제설명">문제설명</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/543aed71-2bbe-4b68-8b43-0c754e62e5fe/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/fc67e5c6-59cf-4c37-8974-d107477eb2a9/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/2b73a20a-7664-4042-bdc6-454853b72ce4/image.png" alt=""></p>
<h1 id="문제접근방식">문제접근방식</h1>
<h2 id="1-이중-for문">1) 이중 for문</h2>
<p>초반엔 각 문자 앞에서부터 하나하나 비교하기 위해 이중 for문으로 구현했다. 근데 통과 못함..ㅋ</p>
<h2 id="2-string-메소드-활용">2) string 메소드 활용</h2>
<p>string 객체의 lastIndexOf()를 활용해서 다시 구현했더니 된다.</p>
<h1 id="소스코드">소스코드</h1>
<pre><code class="language-java">class Solution {
    public int[] solution(String s) {
        int[] answer = new int[s.length()];

        for(int i=0;i&lt;s.length();i++){
            if(i !=0){
                int idx = s.substring(0,i).lastIndexOf(s.charAt(i));
                if(idx != -1){
                    answer[i] = i-idx;

                }
                else{
                    answer[i] = idx;
                }
            }
            else{
                answer[i] = -1;
            }
        }

        return answer;
    }
}</code></pre>
<h1 id="핵심">핵심</h1>
<h2 id="lastindexofstring-s">lastIndexOf(string s)</h2>
<pre><code class="language-java">string s = &quot;banana&quot;;
s.lastIndexOf(&quot;a&quot;);        //5
s.lastIndexOf(&quot;f&quot;);        //없으면 -1 반환</code></pre>
<h2 id="charatint-index">charAt(int index)</h2>
<pre><code class="language-java">string s = &quot;apple&quot;;
s.charAt(3);        // &#39;l&#39; 반환</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Lua Script] 2장 타입과 값]]></title>
            <link>https://velog.io/@se_bb/Lua-Script-2%EC%9E%A5-%ED%83%80%EC%9E%85%EA%B3%BC-%EA%B0%92</link>
            <guid>https://velog.io/@se_bb/Lua-Script-2%EC%9E%A5-%ED%83%80%EC%9E%85%EA%B3%BC-%EA%B0%92</guid>
            <pubDate>Mon, 11 Jul 2022 05:39:05 GMT</pubDate>
            <description><![CDATA[<h1 id="변수-타입">변수 타입</h1>
<p>루아 스크립트는 동적 언어로, 변수를 선언할 때 변수 타입을 지정하지 않는다.</p>
<p>변수 타입 종류로는</p>
<ul>
<li>nil</li>
<li>boolean</li>
<li>number</li>
<li>string</li>
<li>userdata</li>
<li>function</li>
<li>thread</li>
<li>table</li>
</ul>
<p>8가지가 있다.</p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/aee7f646-da7a-4676-b375-546ad063703c/image.png" alt=""></p>
<p>마지막 print()의 경우, <strong>type()는 항상 string 값을 리턴하기 때문에</strong> &quot;string&quot;이 출력된다.</p>
<p><br><br></p>
<p><img src="https://velog.velcdn.com/images/se_bb/post/ef50ec1f-3b97-4903-9ce4-607090f2af59/image.png" alt=""></p>
<p>변수 a에 여러 타입의 값을 대입한 예제이다.
변수를 선언할 때 값을 지정하지 않으면 nil값으로 초기화된다.</p>
<h1 id="nil">nil</h1>
<p>루아에서는 <strong>변수가 현재 값이 없는 상태를 나타내는</strong> 값으로 nil을 사용한다.</p>
<h1 id="boolean">boolean</h1>
<p>참, 거짓을 표현하는 타입으로 true, false값을 가진다.
그런데 루아에서는 boolean 타입 값 뿐만 아니라 다른 값으로도 참, 거짓을 나타낼 수 있다.
조건문에서 nil 값도 false로 판별하고, 그 외의 모든 값은 true로 판별한다.
<strong>0과 빈 문자열도 true로 판별하니 주의하자</strong></p>
<h1 id="실수">실수</h1>
<p>... 실수나 정수 둘다 number 타입이다 정도까지만 훑고 넘어가자</p>
<h1 id="문자열">문자열</h1>
<p>말 그대로 문자들의 순열이다.
루아에서는 문자열을 수정할 수 없다.
다른 언어의 경우 부분 문자열을 수정할 수 있지만, 루아는 바꿀 수 없다.
그 대신 수정하길 원하는 내용으로 새 문자열을 만들어서 쓸 수는 있다.</p>
<pre><code class="language-java">a = &quot;one string&quot;
b = string.gsub(a, &quot;one&quot;, &quot;another&quot;)    -- 문자열 a의 &quot;one&quot; -&gt; &quot;another&quot;로 바꿔달라
print(a)
print(b)</code></pre>
<p><del>velog는 루아스크립트를 지원하지 않는듯해서,, java로 처리함 ㅠ</del></p>
<pre><code class="language-java">a = &quot;Hello&quot;
print(#a)  --변수 값의 길이 구하기
a = 358
-- print(#a)  -- a 값이 문자열이 아니라서 에러남</code></pre>
<p>&quot;#&quot; 연산자를 활용해서 문자열의 길이를 구할 수 있다.
단, 값이 문자열일 때만 가능하다.</p>
<p>루아도 이스케이프 문자가 있다.</p>
<pre><code class="language-java">print(&quot;one line\nnext line\n\&quot;in quotes\&quot;, &#39;in quotes&#39;&quot;)
print(&quot;a backlash inside quotes: \&#39;\\\&#39;&quot;)
print(&quot;a simpler way: &#39;\\&#39;&quot;)</code></pre>
<h2 id="구간-문자열">구간 문자열</h2>
<p>구간 주석을 썼을 때처럼 대괄호 두 개로 감싸서 문자열 상수를 구분할 수 있다.
이렇게 대괄호로 표현된 문자열은 여러 줄로 작성될 수 있고, 이스케이프 문자도 해석하지 않는다.
아래 예제처럼 코드의 일부분을 문자열로 담을 때 편리하다.</p>
<pre><code class="language-javascript">page = [[
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;An HTML Page&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;a href=&quot;http://www.lua.org&quot;&gt;Lua&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;

]]

print(page)</code></pre>
<p>만약 구간 문자열 내에 [[ 나 ]] 가 문자열 자체로 포함되어 있는 경우가 있다.
이럴 때는 [==[ 이런식으로 = 기호를 넣어주면 된다.</p>
<pre><code class="language-javascript">page = [==[
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;An HTML Page&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;a href=&quot;http://www.lua.org&quot;&gt;Lua&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;

]==]    -- &quot;=&quot; 개수 안맞춰주면 에러남

print(page)</code></pre>
<h2 id="강제-변환">강제 변환</h2>
<p>타입이 서로 다른 값들끼리 연산을 하는 경우, 한 쪽 타입으로 강제 변환하여 연산하는데,
루아는 문자열에 수치 연산을 적용하면 숫자로의 변환을 시도한다.</p>
<pre><code class="language-javascript">print(&quot;10&quot;+1)  --수치로써 연산 후 결과 값 출력
print(&quot;10 +1&quot;)  -- 단순 문자열 출력
print(&quot;-5.3e-10&quot;*&quot;2&quot;)  --수치로써 연산 후 결과 값 출력
-- print(&quot;hello&quot;+1)  -- 에러 남</code></pre>
<p>반대로 문자열이 필요한 곳에 실수 값이 있으면 실수 값을 문자열로 변환한다.</p>
<pre><code class="language-javascript">print(10 .. 20)</code></pre>
<p>루아에서 &quot;..&quot;는 문자열을 이어 붙이는 연산자이다.
숫자와 이 연산자를 이어 붙이면 소수점으로 오해하므로 공백을 줘야 한다 ❕</p>
<p>하지만 강제 변환은 비추...하고
명시적 변환을 꼭 해주자</p>
<pre><code class="language-javascript">a = &quot;15468000&quot;  --문자열
print(tonumber(a)+1)  --명시적 변환 후 연산</code></pre>
<h3 id="tonumber"><strong>tonumber()</strong></h3>
<ul>
<li>문자열을 실수로 변환하는 함수</li>
<li>문자열이 실수가 아닌 경우 nil 리턴</li>
</ul>
<h3 id="tostring"><strong>tostring()</strong></h3>
<ul>
<li>실수를 문자열로 변환하는 함수</li>
</ul>
<p>tostring() 외에 <strong>10 .. &quot;&quot;</strong> 이런식으로 실수와 빈 문자열을 연결하면 문자열로 변환된다.</p>
<h1 id="테이블">테이블</h1>
<p>루아에서 배열, 리스트, 레코드, 객체를 테이블이라고 한다.
배열의 인덱스로 nil를 제외한 모든 값(실수, 문자열 등등)을 사용할 수 있다.
따라서 <strong>array[x] != array[&quot;x&quot;]</strong> 인 셈이다.</p>
<pre><code class="language-javascript">arr = {}  -- 테이블 생성 및 &#39;arr&#39;로 참조
k = &quot;x&quot;
arr[k] = 10  --인덱스 키가 &quot;x&quot;이고 값이 10인 원소 저장
arr[20] = &quot;great&quot;  --인덱스 키가 20이고 값이 &quot;great&quot;인 원소 저장
print(arr[&quot;x&quot;])  -- 10 출력
k = 20
print(arr[k])  -- &quot;great&quot; 출력
arr[&quot;x&quot;] = arr[&quot;x&quot;] + 1  -- 10+1
print(arr[&quot;x&quot;])  -- 11 출력</code></pre>
<pre><code class="language-javascript">arr = {}  -- 테이블 생성 및 &#39;arr&#39;로 참조
arr[&quot;x&quot;] = 10
b = arr  -- 변수 &#39;arr&#39;와 &#39;b&#39;는 이제 같은 테이블을 참조함
print(b[&quot;x&quot;])  -- 10 출력
b[&quot;x&quot;]  = 20
print(arr[&quot;x&quot;])  -- 20 출력
arr = nil  -- 변수 arr는 더 이상 테이블을 참조 X, b만 참조
b = nil  -- 테이블을 참조하는 변수 모두 사라짐, 테이블은 알아서 삭제됨</code></pre>
<p>테이블을 참조하는 변수가 사라지면, 루아의 가비지 콜렉터에 의해 테이블이 삭제된다.</p>
<pre><code class="language-javascript">a = {}  -- 빈 테이블

--  원소 1000개 추가
for i =1, 1000 do a[i] = i*2 end
print(a[9])  -- 18 출력
a[&quot;x&quot;] = 10
print(a[&quot;x&quot;])  -- 10 출력
print(a[&quot;y&quot;])  -- nil 출력</code></pre>
<p>위 예제는 원소를 추가하지 않은 인덱스에 접근하면 어떻게 되는지를 확인함을 위해서다.
a[&quot;y&quot;] 라는 원소를 추가한 적이 없기 때문에 nil이 출력된다.</p>
<p>루아에서는 a.name과 a[&quot;name&quot;]은 같은 문법을 의미한다.
단, a[name]는 아니다. 매우 다른 것..</p>
<pre><code class="language-javascript">a = {}
a.x = 10
print(a.x)  -- 10 출력
print(a[&quot;x&quot;])  -- 10 출력</code></pre>
<pre><code class="language-javascript">a = {}
x = &quot;y&quot;
a[x] = 10
print(a[x])  -- 10 출력
print(a.x) -- nil 출력
print(a.y) -- 10 출력</code></pre>
<p>밑 예제가 더 어려운 케이스다.
변수 x냐, 문자열 &quot;x&quot;냐 이걸 제대로 구분하지 않으면 헷갈릴듯..</p>
<p>일반적으로 배열 인덱스는 정수를 넣는다.
하지만 루아는 인덱스 키로 1, &quot;+1&quot;, &quot;1&quot; 모두 가능하고 엄연히 서로 다른 것으로 간주한다.
인간의 경우는 그렇지 않기 때문에 실수가 발생할 수 있으므로 <strong>명시적 변환</strong>을 통해 실수를 방지하자.</p>
<p>아래 예제 참고 !</p>
<pre><code class="language-javascript">i = 10; j = &quot;10&quot;; k=&quot;+10&quot;
a = {}
a[i] = &quot;one value&quot;
a[j] = &quot;another value&quot;
a[k] = &quot;yet another value&quot;
print(a[i]) -- &quot;one value&quot; 출력
print(a[j])  --&quot;another value&quot; 출력
print(a[k])  -- &quot;yet another value&quot; 출력

print(a[tonumber(j)])  -- &quot;one value&quot; 출력
print(a[tonumber(k)])  -- &quot;one value&quot; 출력</code></pre>
<h1 id="함수">함수</h1>
<p>루아에서의 함수는 1급 값이다.
즉,</p>
<ul>
<li>함수를 변수에 저장</li>
<li>다른 함수의 인자로 넘겨주기</li>
<li>함수를 반환 받기</li>
</ul>
<p>이런 기능을 제공한다.</p>
<p>일단 여기까지만 짚고 넘어가자</p>
<h1 id="유저데이터와-스레드">유저데이터와 스레드</h1>
<h2 id="유저데이터">유저데이터</h2>
<p>C 데이터를 루아 변수에 저장하는 데 유저데이터 타입을 사용한다.
여기까지만 짚고 넘어가자...</p>
<p>스레드는 완전 뒤에서....</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준/Java] 병사 배치하기 - 18353]]></title>
            <link>https://velog.io/@se_bb/%EB%B0%B1%EC%A4%80Java-%EB%B3%91%EC%82%AC-%EB%B0%B0%EC%B9%98%ED%95%98%EA%B8%B0-18353</link>
            <guid>https://velog.io/@se_bb/%EB%B0%B1%EC%A4%80Java-%EB%B3%91%EC%82%AC-%EB%B0%B0%EC%B9%98%ED%95%98%EA%B8%B0-18353</guid>
            <pubDate>Tue, 21 Jun 2022 03:30:02 GMT</pubDate>
            <description><![CDATA[<h1 id="문제설명">문제설명</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/2ce4e1a6-898a-4c05-9573-113f34bc06f6/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/7f3c6964-7cf1-47d9-80db-e4d09da678c6/image.png" alt=""></p>
<h1 id="문제풀이">문제풀이</h1>
<p>DP를 공부하면서 연습문제로 풀은 문제이다.
DP는 둘째치고 LIS(Longest Increasing Subsequence) 알고리즘을 알고 있어야 했었다.
이 분제는 전투력을 <strong>내림차순</strong>으로 정렬해야하기 때문에</p>
<p>1) LIS 알고리즘을 변형하거나, 2) 전투력 배열을 거꾸로 뒤집어서 LIS 알고리즘을 적용하거나 하면 된다.
LIS 알고리즘은 따로 정리 할 예정이다.</p>
<h1 id="소스코드">소스코드</h1>
<pre><code class="language-java">import java.util.*;

public class Main{
    public static void main(String[] args) {
        /* 병사 배치하기 */
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();   //병사의 수 입력
        int[] power = new int[n];   //각 병사들의 전투력 배열
        int[] dp = new int[n];  //i번째일 때 최장 증가 부분수열 길이 저장

        for(int i=n-1;i&gt;=0;i--){
            power[i] = sc.nextInt();    //전투력 거꾸로 입력받기
            dp[i] = 1;  //부분 수열 길이 초기화
        }

        /*
        for(int i=0;i&lt;n;i++){
           System.out.print(power[i]+&quot; &quot;);
        }
        */

        //LIS 알고리즘 적용
        for(int i=1;i&lt;n;i++){
            //i 앞의 모든 값들에 대해
            for(int j=0;j&lt;i;j++){
                if(power[j]&lt;power[i]){
                    //i번째 값에 대한 가장 긴 증가 부분 수열 길이 구하기
                    dp[i] = Math.max(dp[i], dp[j]+1);
                    //System.out.println(i+&quot; 일 때    &quot;+ dp[i]);
                }
            }
        }

        //dp[]에서 최댓값 구하기
        int max = dp[0];
        for(int i=1;i&lt;n;i++){
            max = Math.max(max, dp[i]);
        }
        System.out.println(n-max);
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] 문자열 압축]]></title>
            <link>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%95%95%EC%B6%95</link>
            <guid>https://velog.io/@se_bb/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%95%95%EC%B6%95</guid>
            <pubDate>Sun, 29 May 2022 14:06:05 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-설명">문제 설명</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/be2b9c87-aef9-4d21-98f9-2c62245b45a2/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/67be5e23-e38e-481e-a58f-06fe4bee8065/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/39664842-590b-4d8b-b3be-20d8e9e3b587/image.png" alt="">
<img src="https://velog.velcdn.com/images/se_bb/post/f2d8bc0b-ee68-4716-a09d-e7ceec3cfd4e/image.png" alt=""></p>
<h1 id="풀이">풀이</h1>
<p>크게 봤을 때, 자르자 -&gt; 비교하자 -&gt; (같은 문자열) 개수 세자 -&gt; 압축하자 -&gt; 문자열 비교해서 작은 거 찾자
이 로직이다.</p>
<p>자를 땐 1개씩 잘라보기 -&gt; 2개씩 잘라보기 -&gt; 3개씩 -&gt; ... -&gt; 문자열 절반길이씩 잘라보기를 위해 for문 (1)을 사용한다.</p>
<p>자르고 나선 무엇을 해야 하는가?</p>
<p>잘려진 부분 문자열 모두를 반복문으로 순회하면서 앞 혹은 뒤와 비교하면서 개수를 세면 된다.
나는 현재(i) 부분 문자열과 뒤에 있는(i+1)에 있는 부분 문자열과 비교했다.
이 때 i가 배열의 마지막 값인지 아닌지 판별해주어야 한다. (i+1) 때문에 인덱스 아웃 오븡 ㅓ 어쩌구 예외가 발생하기 때문❗ </p>
<p>이런식으로 압축하고 나서 압축된 문자열 길이 확인하고 현 시점까지의 최소 길이와 비교해주면 된다.</p>
<p>압축하는 과정에서 개수 세는 과정이 이 문제의 핵심이었던 것 같다.</p>
<h1 id="소스코드">소스코드</h1>
<pre><code class="language-java">import java.util.*;

class Solution {
    public int solution(String s) {
        int answer = 0;
        int minLen = s.length();    //최소 압출 길이 초기화
        int len = s.length();
        //1 자를 수 있는 모든 단위만큼 반복
        for(int i=1;i&lt;=s.length()/2;i++){
            //배열 크기 확정 못하기 때문에 ArrayList로
           ArrayList&lt;String&gt; tokens = new ArrayList&lt;&gt;();

            //2-1 i단위만큼 문자열 token으로 나누기
            for(int j=0;j&lt;len;j += i){
                if(j+i&lt;len){
                    tokens.add(s.substring(j, j+i));
                }
                else{
                    tokens.add(s.substring(j));
                }
            }
            //System.out.println(tokens);
            String result =&quot;&quot;;  //압축한 문자열 저장
            //2-2 부분 문자열 같은지 체크하고 압축 문자열 만드는 for문

            int cnt = 1;
            for(int z=0;z&lt;tokens.size();z++){ 

                if(z &lt; tokens.size()-1){    //마지막 토큰이 아닐 때
                    if(tokens.get(z).equals(tokens.get(z+1))){
                        cnt++;
                    }
                    else{
                        if(cnt==1){
                            result += tokens.get(z);    //앞과 다른 문자열이라 바로 저장

                        }
                        else{
                            result += cnt+&quot;&quot;+tokens.get(z);    //앞에 상수 붙여서 문자열 저장  
                            cnt = 1;    //중복 개수 초기화
                        }
                    }
                }
                //마지막 토큰일 때는
                else{
                    if(cnt==1){
                            result += tokens.get(z);    //앞과 다른 문자열이라 바로 저장

                        }
                        else{
                            result += Integer.toString(cnt)+tokens.get(z);    //앞에 상수 붙여서 문자열 저장
                        }
                }
            }
            minLen = Math.min(minLen, result.length()); //더 작은 문자열 길이 찾기
        }
        answer = minLen;
        return answer;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준/Java] 럭키 스트레이트]]></title>
            <link>https://velog.io/@se_bb/%EB%B0%B1%EC%A4%80Java-%EB%9F%AD%ED%82%A4-%EC%8A%A4%ED%8A%B8%EB%A0%88%EC%9D%B4%ED%8A%B8</link>
            <guid>https://velog.io/@se_bb/%EB%B0%B1%EC%A4%80Java-%EB%9F%AD%ED%82%A4-%EC%8A%A4%ED%8A%B8%EB%A0%88%EC%9D%B4%ED%8A%B8</guid>
            <pubDate>Sun, 29 May 2022 10:58:39 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-설명">문제 설명</h1>
<p>어떤 게임의 아웃복서 캐릭터에게는 럭키 스트레이트라는 기술이 존재한다. 이 기술은 매우 강력한 대신에 항상 사용할 수는 없으며, 현재 게임 내에서 점수가 특정 조건을 만족할 때만 사용할 수 있다.</p>
<p>특정 조건이란 현재 캐릭터의 점수를 N이라고 할 때 점수 N을 자릿수를 기준으로 반으로 나누어 왼쪽 부분의 각 자릿수의 합과 오른쪽 부분의 각 자릿수의 합을 더한 값이 동일한 상황을 의미한다. 예를 들어 현재 점수가 123,402라면 왼쪽 부분의 각 자릿수의 합은 1+2+3, 오른쪽 부분의 각 자릿수의 합은 4+0+2이므로 두 합이 6으로 동일하여 럭키 스트레이트를 사용할 수 있다.</p>
<p>현재 점수 N이 주어졌을 때, 럭키 스트레이트를 사용할 수 있는 상태인지 아닌지를 알려주는 프로그램을 작성하시오. 럭키 스트레이트를 사용할 수 있다면 &quot;LUCKY&quot;를, 사용할 수 없다면 &quot;READY&quot;라는 단어를 출력한다. 또한 점수 N의 자릿수는 항상 짝수 형태로만 주어진다. 예를 들어 자릿수가 5인 12,345와 같은 수는 입력으로 들어오지 않는다.</p>
<h2 id="입력-조건">입력 조건</h2>
<p>첫째 줄에 점수 N이 정수로 주어진다. (10 ≤ N ≤ 99,999,999) 단, 점수 N의 자릿수는 항상 짝수 형태로만 주어진다.</p>
<h2 id="출력-조건">출력 조건</h2>
<p>첫째 줄에 럭키 스트레이트를 사용할 수 있다면 &quot;LUCKY&quot;를, 사용할 수 없다면 &quot;READY&quot;라는 단어를 출력한다.</p>
<h1 id="풀이">풀이</h1>
<p>String으로 입력 받은 숫자를 char[]로 변환한 후,
배열 길이 절반 왼쪽 숫자들과 오른쪽 숫자들의 <strong>아스키코드</strong>값을 각각 저장한다.
굳이 int형으로 변환하지 않아도 아스코드 값도 숫자마다 고유하기 때문에 문제가 없다.</p>
<h1 id="소스코드">소스코드</h1>
<pre><code class="language-java">import java.util.*;

public class Main {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        String score = sc.nextLine();   //숫자 String으로 입력 받기

        char[] nums = score.toCharArray();  //String -&gt; char[] 변환

        int left = 0;   //왼쪽 숫자 합 저장할 변수
        int right = 0;  //오른쪽 숫자 합 저장할 변수

        //배열 전체 순회
        for(int i=0;i&lt;nums.length;i++){
            //배열 왼쪽 숫자면
            if(i &lt; nums.length/2){
                left += nums[i];    //값 저장(아스키코드 값이어도 상관없음)
            }
            //배열 오른쪽 숫자면
            else{
                right += nums[i];
            }
        }
        //값이 같은지 비교
        if(left == right){
            System.out.println(&quot;LUCKY&quot;);
        }
        else{
            System.out.println(&quot;READY&quot;);
        }



    }
}</code></pre>
<h1 id="결과">결과</h1>
<p><img src="https://velog.velcdn.com/images/se_bb/post/32841b9d-8659-435b-9fac-5880bc35608d/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>