<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ooing.log</title>
        <link>https://velog.io/</link>
        <description>HICE 19</description>
        <lastBuildDate>Wed, 30 Oct 2024 15:44:03 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ooing.log</title>
            <url>https://velog.velcdn.com/images/ooing-0720/profile/ff67c509-04b1-4dec-8162-2aba25622382/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ooing.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ooing-0720" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Ruby] 객체 지향 프로그래밍: class, module]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@ooing-0720/Ruby-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Wed, 30 Oct 2024 15:44:03 GMT</pubDate>
            <description><![CDATA[<h1 id="클래스-class">클래스: class</h1>
<h2 id="접근-제한자-public-private">접근 제한자: public, private</h2>
<pre><code class="language-ruby">class NewClass
    def initialize(name)    
        @name = name
    end

    public
    def public_method
        puts &quot;public&quot;
    end

    private
    def private_method
        @private_value = 1
    end
end</code></pre>
<h2 id="값-읽기-attr_reader">값 읽기: attr_reader</h2>
<pre><code class="language-ruby">class NewClass
    def initialize(name)
        @name = name
     end

     def name
         @name
     end
end</code></pre>
<p>위 코드의 <code>name</code> 메소드를 <code>attr_reader</code>를 이용해 한 줄로 작성 가능</p>
<p><strong>리팩토링</strong></p>
<pre><code class="language-ruby">class NewClass
    attr_reader :name

    def initialize(name)
        @name = name
     end
end</code></pre>
<h2 id="값-접근-attr_writer">값 접근: attr_writer</h2>
<p><code>attr_reader</code>와 마찬가지로, 값 수정 역시 한 줄로 가능하다.</p>
<pre><code class="language-ruby">class NewClass
    def name=(value)
        @name = value
    end

    # 한 줄로 리팩토링
    attr_writer :name
end</code></pre>
<h2 id="읽기-및-접근-모두-가능-attr_accessor">읽기 및 접근 모두 가능: attr_accessor</h2>
<pre><code class="language-ruby">class NewClass
    attr_accessor :name

    # initialize 메소드
end</code></pre>
<h1 id="모듈-module">모듈: module</h1>
<p>모듈: 클래스에서 사용할 기능들(메소드)을 제공하기 위해 만듦.
다양한 클래스에서 사용가능한 메소드를 제공하는 라이브러리.</p>
<h2 id="모듈-예시-math">모듈 예시: Math</h2>
<pre><code class="language-ruby">puts Math::PI</code></pre>
<p>루비에는 <code>Math::PI</code>와 <code>Circle::PI</code>가 있으므로, 혼동하지 않기 위해 <code>네임스페이스</code>를 지정해준다(<code>Math::</code> </p>
<h2 id="모듈-사용-require">모듈 사용: require</h2>
<pre><code class="language-ruby">require &#39;date&#39;</code></pre>
<h2 id="클래스에-모듈을-포함-include">클래스에 모듈을 포함: include</h2>
<pre><code class="language-ruby">class Angle
    include Math

    def initialize(radians)
    @radians = radians
  end

  def cosine
    cos(@radians)
  end
end</code></pre>
<p>이렇게 작성할 경우, <code>Math::</code>라고 네임스페이스를 작성하지 않고 모듈의 메소드?를 사용 가능.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] 객체 지향 프로그래밍: class]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-class</link>
            <guid>https://velog.io/@ooing-0720/Ruby-class</guid>
            <pubDate>Tue, 29 Oct 2024 16:01:48 GMT</pubDate>
            <description><![CDATA[<h1 id="클래스-class">클래스: class</h1>
<p><strong>클래스의 기본 구조</strong></p>
<pre><code class="language-ruby">class NewClass
    # Class 내부 코드 작성
end</code></pre>
<p>클래스 내부에는 당연하게도 (생성자를 포함한) 함수 선언이 가능하다.
인스턴스 변수의 선언에는 <code>@</code>을 사용한다.</p>
<p><strong>생성자 선언</strong></p>
<pre><code class="language-ruby">class NewClass
    def initialize(param)
        @param = param
    end
end

# 생성자로 객체 생성
class = newClass.new(&quot;param1&quot;)</code></pre>
<h2 id="변수---">변수: @, @@, $</h2>
<p>인스턴스 변수: <code>@</code>
클래스 변수: <code>@@</code>
전역 변수: <code>$</code> </p>
<pre><code class="language-ruby">class NewClass
    $global_value = &quot;global&quot;
    @@class_value = &quot;class&quot;

    def initialize(instance_value)
        @instance_value = instance_value
    end
end

puts $global_value</code></pre>
<h2 id="클래스-상속">클래스 상속: &lt;</h2>
<pre><code class="language-ruby">class InheritClass &lt; NewClass
end</code></pre>
<p>함수 오버라이딩은 함수명을 그대로 써서 재정의?하면 된다.</p>
<pre><code class="language-ruby">class NewClass
    def method1
        return &quot;Hello&quot;
     end

     def method2(param)
         return &quot;Hello #{param}&quot;
 end

 class InheritClass &lt; NewClass
     # 오버라이딩 1
     def method1
        return &quot;Hi&quot;
    end

    # 오버라이딩 2
    def method2(param)
        super(param)
    end
end</code></pre>
<h2 id="클래스-메소드-클래스명메소드명">클래스 메소드: 클래스명.메소드명</h2>
<pre><code class="language-ruby">class NewClass
    def NewClass.method
    end
end</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] 블록, 프로세스, 람다: yield, proc, lambda]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-yield-proc-lambda</link>
            <guid>https://velog.io/@ooing-0720/Ruby-yield-proc-lambda</guid>
            <pubDate>Mon, 28 Oct 2024 13:55:28 GMT</pubDate>
            <description><![CDATA[<h1 id="새로운-배열을-반환하며-순회-collect-map">새로운 배열을 반환하며 순회: .collect, .map</h1>
<p>collect와 map은 같은 기능</p>
<pre><code class="language-ruby">my_nums = [1, 2, 3]
my_nums.collect {|x| x ** 2}
# ==&gt; [1, 4, 9]를 반환, but 원본 배열(my_nums)은 변경되지 않음

new_nums = my_nums.collect {|x| x ** 2}
# new_nums = [1, 4, 9]
# my_nums = [1, 2, 3]

my_nums.collect! {|x| x ** 2|
# !를 붙이면 원래 배열을 변형</code></pre>
<h1 id="메소드의-제어권을-전달-yield">메소드의 제어권을 전달: yield</h1>
<pre><code class="language-ruby">def block_test
    puts &quot;a&quot;
    puts &quot;b&quot;
    yield
    puts &quot;c&quot;
end

block_test {puts &quot;d&quot;}
# a -&gt; b -&gt; d -&gt; c</code></pre>
<p><code>yield</code>를 통해 파라미터를 전달하는 것도 가능!</p>
<pre><code class="language-ruby">def yield_test(name)
    puts &quot;Hello&quot;
    yield(name)
    puts &quot;Bye&quot;
    yield(&quot;Rou&quot;)
end

yield_test(&quot;Sho&quot;) {|n| puts &quot;My name is #{n}&quot;}

# Hello
# My name is Sho
# Bye
# My name is Rou</code></pre>
<h1 id="프로세스-proc">프로세스: proc</h1>
<p><code>Proc</code>: 코드 블록을 객체로 만들어서 변수에 저장하거나 전달할 수 있도록 하는 기능 =&gt; Ruby의 객체지향!</p>
<h2 id="프로세스-정의-new">프로세스 정의: .new</h2>
<pre><code class="language-ruby">floasts = [1.2, 3.45, 5.6, 2.7]

round_down = Proc.new { |x| x.floor }

ints = floats.collect(&amp;round_down)</code></pre>
<h2 id="프로세스-호출-call">프로세스 호출: .call</h2>
<pre><code class="language-ruby">hi = Proc.new {puts &quot;Hello!&quot;}
hi.call
# Hello!</code></pre>
<h2 id="메소드를-전달-method_name">메소드를 전달: &amp;:method_name</h2>
<pre><code class="language-ruby">string = [&quot;1&quot;, &quot;2&quot;, &quot;3&quot;]
int = string.map(&amp;:to_i)
# int = [1, 2, 3]</code></pre>
<h1 id="람다-lambda">람다: lambda</h1>
<p><code>lambda</code>: 코드 블록을 객체로 만들어서 변수에 저장하거나 전달할 수 있도록 하는 기능 =&gt; Ruby의 객체지향!</p>
<h2 id="람다-정의-lambda">람다 정의: lambda</h2>
<pre><code class="language-ruby">my_lambda = lambda { |param| block }

my_array = [&quot;string1&quot;, :symbol1, &quot;string2&quot;, :symbol2]

symbol_filter = lambda {|param| param.is_a? Symbol}

symbols = my_array.select(&amp;symbol_filter)
# symbols = [:symbol1, :symbol2]</code></pre>
<h1 id="proc과-lambda의-차이">proc과 lambda의 차이</h1>
<ol>
<li><p>인수 처리 방식</p>
<ul>
<li>lambda : 인수 검사를 엄격히 함. 인수 수가 맞지 않으면 <code>ArgumentError</code> 발생</li>
<li>proc : 누락된 인수는 <code>nil</code>로 처리</li>
</ul>
</li>
<li><p>return 동작 방식</p>
<ul>
<li>lambda : lambda의 return은 호출된 위치로 돌아가 다음 코드를 실행</li>
<li>proc : proc의 return은 정의된 메소드 전체를 즉시 종료시킴</li>
</ul>
</li>
</ol>
<pre><code class="language-ruby">def test_lambda
    my_lambda = lambda { return &quot;Lambda finished&quot;}
    result = my_lambda.call
    &quot;Result after lambda: #{result}&quot;  # 이 줄까지 모두 실행
end

puts test_lambda
# Result after lambda: Lambda finished


def test_proc
    my_proc = Proc.new { return &quot;Proc finished&quot;}
    result = my_proc.call  # test_proc 메소드 즉시 종료
    &quot;Result after proc: #{result}&quot;  # 이 줄은 실행되지 않음
end

puts test_proc
# Proc finished</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] Ruby의 철학: Refactoring]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-Ruby%EC%9D%98-%EC%B2%A0%ED%95%99-Refactoring</link>
            <guid>https://velog.io/@ooing-0720/Ruby-Ruby%EC%9D%98-%EC%B2%A0%ED%95%99-Refactoring</guid>
            <pubDate>Mon, 28 Oct 2024 11:47:30 GMT</pubDate>
            <description><![CDATA[<h1 id="ifunless-문을-간결하게">if/unless 문을 간결하게</h1>
<pre><code class="language-ruby"># 기존 if 문 작정
if condition
    # Do Something
end

# if 문을 더 간단하게 리팩토링
expression if boolean

# 기존 unless 문 작성
unless condition
    # Do Something
end

# if 문을 더 간단하게 리팩토링
expression unless boolean

# 삼항연산자
puts 3 &lt; 4 ? &quot;true&quot; : &quot;false&quot;
# true 출력</code></pre>
<h1 id="case-문을-간결하게">case 문을 간결하게</h1>
<pre><code class="language-ruby"># 기존 case 문 작성
case language
    when &quot;JS&quot;
        puts &quot;websites!&quot;
    when &quot;python&quot;
        puts &quot;ai&quot;
    else    
          puts &quot;I don&#39;t know!&quot;
end

# case 문을 더 간단하게 리팩토링
case language
    when &quot;JS&quot; then puts &quot;websites!&quot;
    when &quot;python&quot; then puts &quot;ai&quot;
       else puts &quot;I don&#39;t know!&quot;
end</code></pre>
<h1 id="대입-연산자conditional-assignment-">대입 연산자(conditional assignment): ||=</h1>
<p>값이 없는 경우(<code>nil</code>인 경우) 대입, 그렇지 않은 경우는 유지</p>
<pre><code class="language-ruby">object = nil
object ||= &quot;name&quot;
puts object
# Output: name

object ||= &quot;age&quot;
puts object
# Output: name

object = &quot;age&quot;
puts object
# Output: age</code></pre>
<h1 id="함수-리팩토링-return-제거">함수 리팩토링: return 제거</h1>
<pre><code class="language-ruby">def add(x, y)
    return x + y
end

# 리팩토링: return 제거
def add(x, y)
    x + y
end</code></pre>
<h1 id="범위-upto-downto">범위: .upto, .downto</h1>
<p><code>.upto(num)</code>은 num까지 +1 되는거
예를 들어, <code>95.upto(100)</code>이면, 95, 96, 97, 98, 99, 100이 해당</p>
<p><code>.downto(num)</code>은 num까지 -1 되는거</p>
<p>숫자뿐만 아니라 문자의 오름차순, 내림차순도 가능하다.</p>
<pre><code class="language-ruby">&quot;L&quot;.upto(&quot;P&quot;) {|c| print c}
# LMNOP</code></pre>
<h1 id="특정-메소드를-응답할-수-있는지-확인-respond_tomethod명">특정 메소드를 응답할 수 있는지 확인: respond_to?(:method명)</h1>
<pre><code class="language-ruby">age = 140

age.respond_to?(:next)
# true</code></pre>
<h1 id="추가-push-">추가: push, +=, &lt;&lt;</h1>
<pre><code class="language-ruby">array = [1, 2, 3]
array.push(4)
array &lt;&lt; 5

string = &quot;My name &quot;
string += &quot;is &quot;
string &lt;&lt; &quot;Ruby!&quot;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] 조건문: case]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-%EC%A1%B0%EA%B1%B4%EB%AC%B8-case</link>
            <guid>https://velog.io/@ooing-0720/Ruby-%EC%A1%B0%EA%B1%B4%EB%AC%B8-case</guid>
            <pubDate>Sat, 26 Oct 2024 14:40:49 GMT</pubDate>
            <description><![CDATA[<h1 id="case--when">case ... when</h1>
<p><code>switch</code>와 비슷</p>
<pre><code class="language-ruby">case choice
when &quot;add&quot;
  puts &quot;Added!&quot;
when &quot;update&quot;
  puts &quot;Updated!&quot;
when &quot;display&quot;
  puts &quot;Movies!&quot;
when &quot;delete&quot;
  puts &quot;Deleted!&quot;
else
  puts &quot;Error!&quot;
end</code></pre>
<h1 id="입력받을-때-값을-지정할-수-있음">입력받을 때 값을 지정할 수 있음</h1>
<pre><code class="language-ruby">title = gets.chomp.to_sym # 입력받은 값을 symbol 타입으로 지정
rating = gets.chomp.to_i # 입력받은 값을 정수형으로 지정</code></pre>
<h1 id="해시에-값이-존재하는지-확인-nil">해시에 값이 존재하는지 확인: .nil?</h1>
<pre><code class="language-ruby">heroes = {
    Dytica: 4,
    Oriens: 4,
    Krisis: 3
}

if heroes[&quot;TUA&quot;.to_sym].nil?
    puts &quot;ERROR&quot;
end
# heroes 해시에 TUA라는 심볼을 key로 갖는 값이 없으므로 ERROR 출력</code></pre>
<h2 id="해시에서-값-삭제-deletekey">해시에서 값 삭제: .delete(key)</h2>
<pre><code class="language-ruby">heroes.delete(key)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] 데이터 구조: hash, symbol]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-%ED%95%B4%EC%8B%9C</link>
            <guid>https://velog.io/@ooing-0720/Ruby-%ED%95%B4%EC%8B%9C</guid>
            <pubDate>Sat, 26 Oct 2024 11:21:54 GMT</pubDate>
            <description><![CDATA[<h1 id="symbol">symbol</h1>
<p><code>:</code>으로 시작하는 문자열, immutable(변경 불가능)
메모리에 한 번만 저장됨</p>
<pre><code class="language-ruby"># string과 symbol 비교
puts &quot;string&quot;.object_id
puts &quot;string&quot;.object_id
# 두 개의 object_id의 값은 다름

puts :symbol.object_id
puts :symbol.obkect_id
# 두 개의 object_id의 값은 같음</code></pre>
<pre><code class="language-ruby"># symbol 생성
my_symbol = :symbol

symbol_hash = {
    :one =&gt; 1,
    :two =&gt; 2,
    :three =&gt; 3
}</code></pre>
<h2 id="string을-symbol로-변환-to_sym-intern">string을 symbol로 변환: to_sym, intern</h2>
<pre><code class="language-ruby">strings = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]

symbols = []
strings.each do |s|
    symbols.push s.to_sym
    # symbols.push s.intern 도 동일하게 작동!
end</code></pre>
<h2 id="조건에-맞는-값만-필터링-select">조건에 맞는 값만 필터링: .select</h2>
<pre><code class="language-ruby">grades = {
    sho: 100,
    rou: 80,
    rai: 70,
    getsu: 50
}

good = grades.select { |name, grade| grade &gt; 60}</code></pre>
<h2 id="each_key-each_value">.each_key, .each_value</h2>
<pre><code class="language-ruby">grades = {
    sho: 100,
    rou: 80,
    rai: 70,
    getsu: 50
}

grades.each_key {|key| puts key}
# sho \n rou \n ...

grades.each_value {|value| puts value}
# 100 \n 80 \n ...</code></pre>
<h1 id="hash의-모양">hash의 모양?</h1>
<p><strong><code>hash rocket</code> 타입</strong></p>
<pre><code class="language-ruby">hash_rocket = {
    &quot;one&quot; =&gt; 1,
    &quot;two&quot; =&gt; 2
}</code></pre>
<p><strong>Ruby 1.9. 버전부터 바뀐 syntax : 더 간단해짐</strong></p>
<pre><code class="language-ruby">new_hash = {
    one: 1,
    two: 2,
    three: 3
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] 메소드: def, 코드 블록: do-end, {}]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-def-do-end</link>
            <guid>https://velog.io/@ooing-0720/Ruby-def-do-end</guid>
            <pubDate>Thu, 24 Oct 2024 08:08:35 GMT</pubDate>
            <description><![CDATA[<h1 id="메소드-정의-def">메소드 정의: def</h1>
<p><code>def</code>를 이용하여 메소드를 정의함</p>
<pre><code class="language-ruby">def print_text
    print &quot;Print Method!&quot;
end

print_text
#Print Method!</code></pre>
<h2 id="파라미터가-있는-메소드">파라미터가 있는 메소드</h2>
<pre><code class="language-ruby">def friend(name)
    puts &quot;Hello #{name}&quot;
end

def friends(greeting, *friends)
    friends.each {|friend| puts &quot;#{greeting}, #{friend}!&quot;}
end

# greeting에 해당하는 파라미터(&quot;Hello&quot;) 이외의 파라미터는
# 모두 freinds 배열의 파라미터로 전달
friends(&quot;Hello&quot;, &quot;Rube&quot;, &quot;Rou&quot;, &quot;Rai&quot;)

# 파라미터에 default 값 지정
def alphabetize(arr, rev = false)

end</code></pre>
<h2 id="반환값이-있는-메소드">반환값이 있는 메소드</h2>
<pre><code class="language-ruby">def add(x, y)
    return x + y
end

puts add(1, 2)</code></pre>
<h1 id="결합-비교-연산자combined-comparision-operator-">결합 비교 연산자(Combined Comparision Operator): &lt;=&gt;</h1>
<p><code>&lt;=&gt;</code>: 두 개의 Ruby 객체를 비교하는 연산자</p>
<blockquote>
<p><code>a &lt;=&gt; b</code>의 경우,
첫번재 피연산자(이하 a)와 두번째 피연산자(이하 b)가 같은 경우: <code>0</code>
a가 b보다 큰 경우: <code>1</code>
a가 b보다 작은 경우: <code>-1</code></p>
</blockquote>
<p><strong>&lt;=&gt;를 이용하여 정렬</strong></p>
<pre><code class="language-ruby">num = [2, 3, 1, 5, 4]

# 오름차순 정렬
num.sort! do |x, y|
    x &lt;=&gt; y
end

# 내림차순 정렬
num.reverse!</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] 데이터 구조: array, hash]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-array-hash</link>
            <guid>https://velog.io/@ooing-0720/Ruby-array-hash</guid>
            <pubDate>Thu, 24 Oct 2024 06:34:04 GMT</pubDate>
            <description><![CDATA[<h1 id="array">array</h1>
<pre><code class="language-ruby">my_array = [1, 2, 3]

# index로 접근
print my_array[0]

string_array = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]
array_array = [[0, 0, 0, 0], [1, 1, 1, 1], [2, 2, 2, 2]]

# array_array 출력
array_array.each { |x| puts &quot;#{x}&quot;}
# [0, 0, 0, 0]
# [1, 1, 1, 1]
# [2, 2, 2, 2]

# 2차원 배열의 각 원소에 접근
array_array.each {|element|
    element.each {
        |x| puts x
    }
}
# {} 대신 do, end로 작성해도 됨</code></pre>
<h1 id="hash">hash</h1>
<pre><code class="language-ruby"># 빈 hash 생성
hash = Hash.new

# defalut 값 지정
hash = Hash.new(0)
hash = Hash.new(&quot;default value&quot;)

# 처음부터 값이 있는 hash 생성
hash = {
    key1 =&gt; value1,
    key2 =&gt; value2,
    key3 =&gt; value3
}

# hash에 key-value pair 추가
hash[&quot;key4&quot;] = &quot;value4&quot;

hash.each {|x| puts x}
# [key1, value1]
# [key2, value2]

hash.each {|x, y| puts &quot;#{x}: #{y}&quot;}
# key1: value1
# key2: value2</code></pre>
<h1 id="정렬-sort-sort_by">정렬: sort, sort_by</h1>
<p>array 정렬: <code>sort</code>
hash 정렬: <code>sort_by</code></p>
<pre><code class="language-ruby">colors = {
    &quot;red&quot; =&gt; 3,
    &quot;blue&quot; =&gt; 2,
    &quot;pruple&quot; =&gt; 1
}

# 오름차순
colors = colors.sort_by do |key, value| value end
# 내림차순
colors.reverse!</code></pre>
<h1 id="문자열로-변환-to_s">문자열로 변환: to_s</h1>
<pre><code>num = 3
puts num.to_s</code></pre><h1 id="array로-변환-to_a">array로 변환: to_a</h1>
<pre><code>array = (1..10).to_a</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] 반복문: while, until, for, loop]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-while-until-for-loop</link>
            <guid>https://velog.io/@ooing-0720/Ruby-while-until-for-loop</guid>
            <pubDate>Tue, 22 Oct 2024 14:57:36 GMT</pubDate>
            <description><![CDATA[<p><code>+=</code>, <code>-=</code> 가능</p>
<h1 id="while">while</h1>
<p>주어진 조건이 성립하는 동안(true) while 문 내부 동작 수행</p>
<pre><code class="language-ruby">counter = 0

while counter &lt; 10
    puts counter
    counter = counter + 1
end

# 0 ~ 9 출력</code></pre>
<h1 id="until">until</h1>
<p> 주어진 조건이 성립할 때까지(false) until 문 내부 동작 수행</p>
<pre><code class="language-ruby"> counter = 0

 until counter == 10
     puts counter 
    counter = counter + 1
 end
 # 0 ~ 9 출력</code></pre>
<h1 id="for">for</h1>
<p> 주어진 범위나 배열을 사용하여 반복적인 동작 수행</p>
<pre><code class="language-ruby"> # ... : 마지막 수를 범위에 포함하지 않음 [1, 10)
 for num in 1 ... 10
     puts num
 end
 # 1 ~ 9 출력

 # .. : 마지막 수를 범위에 포함 [1, 10]
 for num in 1 .. 10
     puts num
 end</code></pre>
<h1 id="loop">loop</h1>
<p> while true와 같은 무한 루프, break문을 통해 탈출 가능</p>
<pre><code class="language-ruby"> num = 0

 loop do
     num -= 1
    puts num
    break if num &lt;= 0
 end</code></pre>
<h1 id="next">next</h1>
<p> 특정 조건이 성립하면 스킵 (continue)</p>
<pre><code class="language-ruby"> for i in 1 .. 5
     next if i % 2 == 0
    puts i
 end</code></pre>
<h1 id="배열-each">배열: .each</h1>
<p> <code>my_array = [1, 2, 3, 4, 5]</code></p>
<p> 배열의 값을 이용하여 반복문 실행</p>
<pre><code class="language-ruby"> numbers = [1, 2, 3, 4, 5]

 numbers.each{|item| print item}

 numbers.each do |item|
     puts item
 end</code></pre>
<h1 id="times">.times</h1>
<p> super compact for 반복문이라고 한다.
 <code>10.times</code>이면 10번 반복</p>
<pre><code class="language-ruby"> 10.times {puts &quot;abc&quot;}</code></pre>
<h1 id="문자열-분리-split">문자열 분리: .split</h1>
<pre><code class="language-ruby"> text = &quot;Hello, Ruby!&quot;
 words = text.split(&quot; &quot;)
 # words = [&quot;Hello&quot;, &quot;Ruby!&quot;]</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] 조건문: Control Flow in Ruby]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-Control-Flow-in-Ruby</link>
            <guid>https://velog.io/@ooing-0720/Ruby-Control-Flow-in-Ruby</guid>
            <pubDate>Tue, 22 Oct 2024 13:54:24 GMT</pubDate>
            <description><![CDATA[<h1 id="조건문">조건문</h1>
<h2 id="if">if</h2>
<p>boolean 값: <code>true</code>, <code>false</code></p>
<pre><code class="language-ruby">if 1 &lt; 2
    print &quot;1 is less than 2&quot;
end</code></pre>
<h2 id="else">else</h2>
<pre><code class="language-ruby">user_num = Integer(gets.chomp)

if user_num &lt; 100
    print &quot;#{user_num} is less than 100&quot;
else
    print &quot;#{user_num} is bigger than 100&quot;
end</code></pre>
<h2 id="elsif">elsif</h2>
<p>elsif는 또 처음 본다</p>
<pre><code class="language-ruby">user_num = Integer(gets.chomp)

if user_num &lt; 100
    print &quot;#{user_num} is less than 100&quot;
elsif user_num &gt; 100
    print &quot;#{user_num} is bigger than 100&quot;
else
    print &quot;#{user_num] is 100&quot;
end</code></pre>
<h2 id="unless">unless</h2>
<p>if not(false 체크)을 의미하는 조건문이다
좀 헷갈리긴 한데
<code>if</code>의 경우 <code>if (true == true)</code>
<code>unless</code>의 경우 <code>unless (false == false)</code>
라고 생각하면 될 것 같다</p>
<pre><code class="language-ruby">hungry = false

unless hungry 
    print &quot;I&#39;m not hungry&quot;
else
    print &quot;It&#39;s time to eat&quot;
end</code></pre>
<h2 id="true-false">true, false</h2>
<pre><code class="language-ruby">is_true = 2 != 3
is_false = 2 == 3</code></pre>
<h1 id="연산자">연산자</h1>
<h2 id="비교-연산자">비교 연산자</h2>
<p>&lt;, &lt;=, &gt;, &gt;=</p>
<h2 id="논리-연산자">논리 연산자</h2>
<p>&amp;&amp;, ||, !</p>
<h1 id="메소드">메소드</h1>
<p><strong>입력</strong>: <code>gets.chomp</code>
<strong>특정 문자열을 포함하는지 확인</strong>: <code>string_to_check.include? &quot;substring&quot;</code>
<strong>문자열 일부 교체</strong>: <code>string_to_change.gsub!(/s/, &quot;th&quot;)</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] 입출력: Putting the Form in Formatter]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-Putting-the-Form-in-Formatter</link>
            <guid>https://velog.io/@ooing-0720/Ruby-Putting-the-Form-in-Formatter</guid>
            <pubDate>Sun, 20 Oct 2024 15:05:37 GMT</pubDate>
            <description><![CDATA[<h1 id="출력-puts-print">출력: puts, print</h1>
<p>다시 한 번 출력 메소드의 차이를 정리하자면</p>
<blockquote>
<p><strong>puts</strong>: 주어진 문자열 출력 및 <strong>개행</strong>
<strong>print</strong>: 주어진 문자열 출력</p>
</blockquote>
<pre><code class="language-ruby">puts &quot;Hello Ruby!&quot;
puts &quot;Hello&quot; + &quot;Ruby!&quot;

name = Ooing
puts &quot;Hello #{name}!&quot;
# Output: Hello Ooing!</code></pre>
<h1 id="입력-getschomp">입력: gets.chomp</h1>
<blockquote>
<p><strong>gets</strong>: 엔터 입력 전까지의 내용을 input으로 받음, 자동적으로 <strong>빈 줄(blank line)</strong>을 추가
<strong>chomp</strong>: 추가 라인(blank line)을 제거하는 역할</p>
</blockquote>
<pre><code class="language-ruby">
print &quot;What&#39;s your name?&quot;
name = gets.chomp

# Oupput: What&#39;s your name? (값 입력 + enter)
# name에 입력된 값 저장</code></pre>
<h1 id="첫-문자를-대문자로-capitalize">첫 문자를 대문자로: .capitalize</h1>
<blockquote>
<p>새로운 변수에 값을 할당하는 경우: <code>new_value = value.capitalize</code>
기존 값을 변경하는 경우: <code>value.capitalize!</code></p>
</blockquote>
<p>```ruby
name = &quot;ruby&quot;</p>
<h1 id="name2에-name의-첫-문자를-대문자로-변환한-문자열을-할당">name2에 name의 첫 문자를 대문자로 변환한 문자열을 할당</h1>
<p>name2 = name.capitalize</p>
<h1 id="name에-그대로-첫-문자를-대문자를-변환하여-할당">name에 그대로 첫 문자를 대문자를 변환하여 할당</h1>
<p>name.capitalize!</p>
<p>puts &quot;My name is #{name}.&quot;
puts &quot;My name is #{name2}.&quot;</p>
<h1 id="output-my-name-is-ruby">Output: My name is Ruby.</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ruby] 변수, 출력, 메소드, 주석: Introduction to Ruby]]></title>
            <link>https://velog.io/@ooing-0720/Ruby-Introduction-to-Ruby</link>
            <guid>https://velog.io/@ooing-0720/Ruby-Introduction-to-Ruby</guid>
            <pubDate>Sun, 20 Oct 2024 14:35:45 GMT</pubDate>
            <description><![CDATA[<p>Codeacademy의 &lt;<a href="https://www.codecademy.com/enrolled/courses/learn-ruby">Learn Ruby</a>&gt;를 정리한 글입니다.</p>
<h1 id="ruby">Ruby</h1>
<p>Ruby는 웹/인터넷 개발, 텍스트 처리, 게임 개발 및 웹 개발 프레임워크인 Ruby on Rails로 사용할 수 있는 유연한 프로그래밍 언어.</p>
<h2 id="특징">특징</h2>
<ol>
<li><strong>고급 프로그래밍 언어(High-Level)</strong> : 사람이 이해하기 쉽게 작성된 언어 = 영어랑 비슷</li>
<li><strong>인터프리트 언어</strong> : 코드 작성 및 실행에 컴파일러 필요 X</li>
<li><strong>객체 지향</strong> : 사용자가 데이터 구조(객체)를 조작하여 프로그램을 빌드 및 실행 가능, 루비의 모든 것이 객체</li>
<li><strong>사용하기 쉬움</strong> : 컴퓨터의 필요보다 인간의 필요를 강조</li>
</ol>
<h1 id="변수-타입-int-string-boolean-등">변수 타입: int, string, boolean 등</h1>
<p>객체 지향 언어이기 때문에, 모든 데이터 타입은 클래스 기반.</p>
<blockquote>
<p>변수 선언 시 타입 선언 필요 X</p>
</blockquote>
<pre><code class="language-ruby"># Integer type
count = 1

# Float type
rating = 1.5

# Boolean type
isBig = count &gt; 2

# Print
puts isBig
# Output : false


# Both float and integer types
miles = 127
hours = 2.5
miles_per_hour = miles/hours

# Print
puts &quot;Miles per hour : #{miles_per_hour}&quot;
# Output : Miles per hour: 50.8


# String type
name = &quot;Ruby&quot;

puts name
# Output : Ruby
</code></pre>
<h1 id="연산자">연산자</h1>
<blockquote>
<p>+(덧셈), -(뺄셈), *(곱셈), /(나눗셈), **(거듭제곱), %(모듈로)</p>
</blockquote>
<p>연산자는 대부분 프로그래밍 언어와 같고, <strong>\</strong>(거듭제곱)을 지원**</p>
<h1 id="기본-메소드">기본 메소드</h1>
<p>기본적으로 메소드는 <code>.</code>을 사용하여 호출.</p>
<h2 id="출력-puts-print">출력: puts, print</h2>
<blockquote>
<p>puts: 주어진 문자열 출력 및 개행
print: 주어진 문자열 출력</p>
</blockquote>
<pre><code class="language-ruby">puts &quot;Hello&quot;
puts &quot;Ruby&quot;
# Output:
# Hello
# Ruby

print &quot;Hello&quot;
print &quot;Ruby&quot;
# Output:
# HelloRuby</code></pre>
<h2 id="크기-length">크기: .length</h2>
<pre><code class="language-ruby">puts &quot;Hello Ruby&quot;.length
# Output: 10</code></pre>
<h2 id="거꾸로-뒤집기-reverse">거꾸로 뒤집기: .reverse</h2>
<pre><code class="language-ruby">puts &quot;Ruby&quot;.reverse
# Output: ybuR</code></pre>
<h2 id="대소문자-변환-upcase-downcase">대소문자 변환: .upcase, .downcase</h2>
<pre><code class="language-ruby"># 모두 대문자로
puts &quot;Ruby&quot;.upcase
# Output: RUBY

# 모두 소문자로
puts &quot;Ruby&quot;.downcase
# Output: ruby</code></pre>
<h1 id="주석">주석</h1>
<h2 id="한-줄-주석">한 줄 주석</h2>
<p><code>#</code>으로 한 줄 주석 작성 가능</p>
<pre><code class="language-ruby"># 지금까지 계속 쓰고 있던
# 한 줄 주석</code></pre>
<h2 id="여러-줄-주석">여러 줄 주석</h2>
<p><code>=begin ~~ =end</code>으로 여러 줄 주석 작성 가능</p>
<pre><code class="language-ruby">=begin
여러 줄 주석을
작성하는 방법
=end</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] Addressable 다운로드 프로그레스 바와 이것저것]]></title>
            <link>https://velog.io/@ooing-0720/Unity-Addressable-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%A0%88%EC%8A%A4-%EB%B0%94%EC%99%80-%EC%9D%B4%EA%B2%83%EC%A0%80%EA%B2%83</link>
            <guid>https://velog.io/@ooing-0720/Unity-Addressable-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%A0%88%EC%8A%A4-%EB%B0%94%EC%99%80-%EC%9D%B4%EA%B2%83%EC%A0%80%EA%B2%83</guid>
            <pubDate>Mon, 22 Apr 2024 14:06:10 GMT</pubDate>
            <description><![CDATA[<p>Addressable Asset Bundle 적용 초반에 하면서 헷갈렸던(+ 어려웠던) 것들을 정리하고자 한다.
개념적인 것들은 블로그, 유튜브에 잘 정리돼있으므로! (본인은 감귤오렌지 님의 유튜브, 블로그가 아~~주 많은 도움이 되었다. 감사합니다!!!!)
<a href="https://youtu.be/GsKofci_HSg?si=biox7_4mEwhO-mOo">감귤오렌지 님의 Addressable 설명 유튜브</a></p>
<h1 id="addressable-asset-system">Addressable Asset System</h1>
<p><del>이 글을 (만약) 보는 사람들이 있다면 이런 내용은 다 알겠지.. 그러므로 간단히 작성한다.</del></p>
<p>Addressable Asset System을 이용하면 <strong>실행 시간에 필요한 리소스들을</strong> 프로그램(앱) 내부에 저장하고있지 않아도 사용 가능하다. <strong>로컬 또는 원격에서 다운로드</strong>할 수 있기 때문!</p>
<p>이로 인해 Addressable을 사용하는 데에는 이점이 꽤나 많은데..</p>
<blockquote>
</blockquote>
<ol>
<li>프로그램의 <strong>크기</strong>를 줄일 수 있다 (본인은 Addressable을 도입하여 약 1/10으로 앱의 크기를 줄였다!)</li>
<li>리소스 다운로드를 위해 앱을 <strong>재설치</strong>할 필요가 없다 (런타임에서 다운로드 가능하므로)</li>
</ol>
<h1 id="무엇을-addressable-asset으로-만들까">무엇을 Addressable Asset으로 만들까?</h1>
<p>prefab, image뿐만 아니라 scene, animation, animator.. 거의 모든 것들을 Addressable로 지정할 수 있다. (스크립트는 안 됨)</p>
<p>그래서 상황에 맞게, 본인의 필요에 맞게 어떤 것을 addressable asset으로 만들지 결정해야한다.</p>
<p>첫번째 프로젝트에서는 prefab을, 두번째 프로젝트에서는 scene을 addressable화 했다.</p>
<p>prefab을 addressable asset으로 만들면 프로젝트의 용량을 확실히 줄일 수 있다. (2500개 이상이었기 때문에)
또한, prefab을 리소스에 포함해서 빌드하면 수정할 때마다 새로 빌드 &amp; 출시해야하는데, addressable로 관리하면 프리팹 수정으로 새로 빌드할 필요가 없어진다!</p>
<p>scene을 addressable asset으로 만드는 것 역시, 용량면에서 매우 훌륭하다.(씬에 포함되는 모든 것들을 프로젝트에서 제외하고 빌드할 수 있으므로)
scene을 addressable asset으로 만들면 scene의 다운로드 속도가 느린 것 아닌가? 라고 생각할 수 있는데(일단 본인이 이렇게 생각했었다) 전혀 아니다! 위의 prefab 하나만 addressable해서 다운로드하는 것과 거의 차이가 없다.(유니티 Addressable 공식 문서에도 SceneManager.LoadScene과 Addressables.LoadScene()의 성능 차이가 거의 없다고 적혀있다)</p>
<h1 id="addressable-group-label">Addressable? Group? Label?</h1>
<p>첫번째 프로젝트에서는 하나의 group에 하나의 asset만 배치했다.
<img src="https://velog.velcdn.com/images/ooing-0720/post/cd378c59-0272-4673-8490-5d3dc4679c21/image.png" alt=""></p>
<p>이렇게 하면 group 생성하는게 번거롭긴 해도, 선택한 1개만 다운로드하기에는 효율적이다.
(여러 asset을 group으로 묶으면 하나를 다운로드받기 위해 같은 group에 속한 모든 asset을 다운로드하기 때문에)
<del>그룹 생성하는건 왜 번거로웠냐면.. 무려 에셋과 번들이 2500개 이상이었기 때문이다.</del></p>
<p>두 번째 프로젝트에서는 하나의 group에 여러개의 asset을 배치했다.</p>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/096a52b2-692a-4878-a72f-937bb964a2f5/image.png" alt=""></p>
<p>하나의 group에 속한 asset들을 모두 동시에 다운로드하기 위해!
이 경우의 이점은 뭐냐면, 같은 그룹에 속한 asset을 모두 한 번에 다운로드할 수 있어서 초기에 모두 로딩하고 이후에 사용 시점에 불러오는 시간이 들지 않는다!</p>
<p>예를 들면, 게임을 실행할 때 앱스토어에서 업데이트하지 않고 패치 파일을 다운로드하는 것과 비슷하다.</p>
<h1 id="addressable-다운로드-스크립트">Addressable 다운로드 스크립트</h1>
<h1 id="프로그레스-바">프로그레스 바</h1>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/fed87a64-c146-4723-ac26-3c7a08a7306c/image.gif" alt="이건 앱에 구현해서 넣은 프로그레스바이다"></p>
<p>이런 식으로 Addressable bundle의 다운로드 상황에 맞게 프로그레스 바가 보였으면 좋겠다고 생각했다. <del>(다음 담당자가 서치하다가 이 글을 볼 일은.. 없겠지..?🥹)</del></p>
<h1 id="메인-프로젝트와-addressable-프로젝트-분리">메인 프로젝트와 Addressable 프로젝트 분리</h1>
<p>난 주로 메인 프로젝트와 Addressable 프로젝트를 분리해서 작업을 했다.</p>
<p>분리헸더니갑자기 InvalidKeyException이 발생하는 경우가 있는데, 대부분 Addressable Build를 하지 않아서이다. Load Path를 변경한 뒤, build를 해야 제대로 적용이 된다.</p>
<blockquote>
<p><strong><code>InvalidKeyException</code> 이 발생하는 경우</strong><br/></p>
</blockquote>
<ol>
<li>Key 값이 잘못 됨 <pre><code class="language-cs"> Addressables.InstantiateAsync(&quot;KEY&quot;, new Vector3(0, 0, 0), Quaternion.identity);</code></pre>
</li>
<li>Remote Load Path가 잘못 됨</li>
<li>Bundle Build 시의 Remote Load Path와 현재 설정된 Remote Load Path가 다름</li>
<li>모든게 제대로 설정돼있음에도 오류가 발생하는 경우, Cache 삭제!
 (C:/Users/user/AppData/LocalLow/회사 이름/앱 이름)</li>
</ol>
<p>어차피 혼자 작업하면서 왜? 라는 생각이 들 수 있지만.. 프로젝트 사이즈가 너무 커서 한 프로젝트에서 관리하면 감당이 안 됐다..😱 프로젝트 여는데만 10분.. 20분...</p>
<p>프리팹을 Addressable 에셋으로 변환하는데는 별 문제 없었다. 애니메이션도 잘 적용되고, 레이어 순서가 깨지지도 않고 등등. Addressable을 잘 몰라서 헤맨 것 제외하고는 잘 됐다. (뭘 헤맸는지도 후술 예정)</p>
<p>씬을 Addressable 에셋으로 변환하는데는 생각보다 다양한 문제가 뒤따랐다.</p>
<ul>
<li>버튼 OnClick 동작 안 함</li>
<li>스크립트 변환 적용 안 됨</li>
<li>레이어 순서 깨짐 &lt;- 😫</li>
</ul>
<h1 id="addressable을-더-잘-이용하고-싶다">Addressable을 더 잘 이용하고 싶다.</h1>
<p>이게 무슨 말이냐면, 콘텐츠의 업데이트만 있을 경우 앱을 새로 빌드하고 싶지 않다는 뜻이다. Addressable 에셋을 다운로드받기만 하면 업데이트가 적용되는.</p>
<p>이걸 적용하기 위해선 스크립트를 변경할 필요가 있었다. 기존 코드는 매~우 하드코딩이었기 때문.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준/바킹독] 0329 이분 탐색]]></title>
            <link>https://velog.io/@ooing-0720/%EB%B0%B1%EC%A4%80%EB%B0%94%ED%82%B9%EB%8F%85-0329-%EC%9D%B4%EB%B6%84-%ED%83%90%EC%83%89</link>
            <guid>https://velog.io/@ooing-0720/%EB%B0%B1%EC%A4%80%EB%B0%94%ED%82%B9%EB%8F%85-0329-%EC%9D%B4%EB%B6%84-%ED%83%90%EC%83%89</guid>
            <pubDate>Fri, 29 Mar 2024 10:48:03 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>오늘의 문제</strong>
<a href="https://www.acmicpc.net/problem/2295">2295 세 수의 합</a>
<a href="https://www.acmicpc.net/problem/1654">1654 랜선 자르기</a>
<a href="https://www.acmicpc.net/problem/18869">18869 멀티버스 Ⅱ</a></p>
</blockquote>
<h1 id="2295-세-수의-합">2295 세 수의 합</h1>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/b0ff4dbd-4cd1-4310-a374-6a88af8d5b4c/image.png" alt=""></p>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int n;
vector&lt;int&gt; arr, two;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin &gt;&gt; n;
    arr = vector&lt;int&gt;(n, 0);
    for (int i = 0; i &lt; n; i++) cin &gt;&gt; arr[i];
    sort(arr.begin(), arr.end());
    arr.erase(unique(arr.begin(), arr.end()), arr.end());

    for (int i = 0; i &lt; arr.size(); i++) {
        for (int j = i; j &lt; arr.size(); j++) {
            two.emplace_back(arr[i] + arr[j]);
        }
    }
    sort(two.begin(), two.end());
    two.erase(unique(two.begin(), two.end()), two.end());

    for (int i = arr.size() - 1; i &gt;= 0; i--) {
        for (int j = arr.size() - 2; j &gt;= 0; j--) {
            if (binary_search(two.begin(), two.end(), arr[i] - arr[j])) {
                cout &lt;&lt; arr[i];
                return 0;
            }
        }
    }
}</code></pre>
<h1 id="1654-랜선-자르기">1654 랜선 자르기</h1>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/8d40e63b-2150-4428-9338-adf59c0a9124/image.png" alt=""></p>
<h2 id="코드-1">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

long long k, n, arr[10002];

int count(int len) {
    long long cnt = 0;
    for (int i = 0; i &lt; k; i++) {
        cnt += arr[i] / len;
    }
    return cnt;
}

int main() {
    cin &gt;&gt; k &gt;&gt; n;
    for (int i = 0; i &lt; k; i++) cin &gt;&gt; arr[i];
    sort(arr, arr + k);
    long long s = 1, e = arr[k - 1];
    while (s &lt; e) {
        long long mid = (s + e + 1) / 2;
        if (count(mid) &gt;= n) s = mid;
        else e = mid - 1;
    }
    cout &lt;&lt; s;
}</code></pre>
<p>이런 문제를 <strong>Parametric Search</strong>라고 한다고 한다.</p>
<h1 id="18869-멀티버스-ⅱ">18869 멀티버스 Ⅱ</h1>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/ed1f0e8b-731b-4038-96a7-af6c69b95fef/image.png" alt=""></p>
<h2 id="코드-2">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int m, n;
vector &lt; vector&lt;int&gt;&gt; arr;


int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin &gt;&gt; m &gt;&gt; n;
    for (int i = 0; i &lt; m; i++) {
        vector&lt;int&gt; v;
        for (int j = 0; j &lt; n; j++) {
            int a;
            cin &gt;&gt; a;
            v.emplace_back(a);
        }
        arr.emplace_back(v);
        sort(v.begin(),v .end());
        for (int j = 0; j &lt; n; j++) {
            arr[i][j] = lower_bound(v.begin(), v.end(), arr[i][j]) - v.begin();
        }
    }
    int ans = 0;
    for (int i = 0; i &lt; m - 1; i++) {
        for (int j = i + 1; j &lt; m; j++) {
            bool same = true;
            for (int k = 0; k &lt; n; k++) {
                if (arr[i][k] != arr[j][k]) {
                    same = false;
                    break;
                }
            }
            if (same) ++ans;
        }
    }
    cout &lt;&lt; ans;
}</code></pre>
<p>처음에는 그냥 인덱스 저장 후 정렬해서 순서대로 인덱스가 같은지 확인했는데, 이렇게 할 경우 10 10 / 20 10 을 같다고 처리한다! 그렇기 때문에 단순 정렬이 아닌 좌표 압축을 해서 <code>lower_bound</code>를 비교해야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준/바킹독] 0327 수학]]></title>
            <link>https://velog.io/@ooing-0720/%EB%B0%B1%EC%A4%80%EB%B0%94%ED%82%B9%EB%8F%85-0327-%EC%88%98%ED%95%99</link>
            <guid>https://velog.io/@ooing-0720/%EB%B0%B1%EC%A4%80%EB%B0%94%ED%82%B9%EB%8F%85-0327-%EC%88%98%ED%95%99</guid>
            <pubDate>Fri, 29 Mar 2024 05:33:33 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>오늘의 문제</strong>
<a href="https://www.acmicpc.net/problem/6064">6064 카잉 달력</a>
<a href="https://www.acmicpc.net/problem/11051">11051 이항 계수 2</a></p>
</blockquote>
<h1 id="6064-카잉-달력">6064 카잉 달력</h1>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/5cf1a35b-747a-4e43-b242-3273901c3cdd/image.png" alt=""></p>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int t, m, n, x, y;

int last(int a, int b) {
    int tmp, ta, tb;
    if (a &gt; b) {
        ta = a; tb = b;
    }
    else {
        ta = b; tb = a;
    }
    while (ta != 0) {
        tmp = tb % ta;
        tb = ta;
        ta = tmp;
    }
    return (a * b) / tb;
}

int main() {
    cin &gt;&gt; t;
    while (t--) {
        cin &gt;&gt; m &gt;&gt; n &gt;&gt; x &gt;&gt; y;
        int mn = last(m, n);
        if (m == x &amp;&amp; n == y) {
            cout &lt;&lt; mn &lt;&lt; &quot;\n&quot;;
            continue;
        }
        int ans = -1;
        for (int i = x; i &lt;= mn; i += m) {
            if (i % n == y || (n == y &amp;&amp; i % n == 0)) {
                ans = i;
                break;
            }
        }
        cout &lt;&lt; ans &lt;&lt; &quot;\n&quot;;
    }
}</code></pre>
<h1 id="11051-이항-계수-2">11051 이항 계수 2</h1>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/3d8aa393-f6a9-4573-b484-7f0eea7d18bf/image.png" alt=""></p>
<h2 id="코드-1">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;
#define ll long long

int n, k, dp[1002][1002];

int main() {
    cin &gt;&gt; n &gt;&gt; k;
    dp[1][0] = 1;
    dp[1][1] = 1;
    for (int i = 2; i &lt;= n; i++) {
        for (int j = 0; j &lt;= i; j++) {
            dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1]) % 10007;
        }
    }
    cout &lt;&lt; dp[n][k];
}</code></pre>
<p>문득.. nCk = n-1Ck + n-1Ck-1 이라는 공식이 떠올랐다..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 0326 DP 6]]></title>
            <link>https://velog.io/@ooing-0720/%EB%B0%B1%EC%A4%80-0326-DP-6-076v4y6u</link>
            <guid>https://velog.io/@ooing-0720/%EB%B0%B1%EC%A4%80-0326-DP-6-076v4y6u</guid>
            <pubDate>Tue, 26 Mar 2024 09:27:07 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>오늘의 문제</strong>
<a href="https://www.acmicpc.net/problem/1005">1005 ACM Craft</a>
<a href="https://www.acmicpc.net/problem/1029">1029 그림 교환</a></p>
</blockquote>
<h1 id="1005-acm-craft">1005 ACM Craft</h1>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/3ae80bd5-bbf5-43ae-a57d-0beecc97d0c2/image.png" alt=""></p>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int t, n, k, w;
int arr[1002], dp[1002];
vector&lt;vector&lt;int&gt;&gt; adj;

int dfs(int d) {
    ios::sync_with_stdio(0);
    cin.tie(0);
    if (dp[d] != -1) return dp[d];
    if (adj[d].empty()) {
        dp[d] = arr[d];
        return dp[d];
    }
    int now = 0;
    for (int i : adj[d]) {
        now = max(now, dfs(i));
    }
    dp[d] = arr[d] + now;
    return dp[d];
}

int main() {
    cin &gt;&gt; t;
    while (t--) {
        cin &gt;&gt; n &gt;&gt; k;
        adj = vector&lt;vector&lt;int&gt;&gt;(n, vector&lt;int&gt;(0, 0));
        fill(dp, dp + n, -1);
        for (int i = 0; i &lt; n; i++) cin &gt;&gt; arr[i];
        while (k--) {
            int a, b;
            cin &gt;&gt; a &gt;&gt; b;
            adj[b - 1].emplace_back(a - 1);
        }
        cin &gt;&gt; w;
        cout &lt;&lt; dfs(w - 1) &lt;&lt; &quot;\n&quot;;
    }
}</code></pre>
<p>그래프를 역방향으로 만들었다.</p>
<h1 id="1029-그림-교환">1029 그림 교환</h1>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/2ded0731-1079-47eb-9bf7-ec5f26a9aa6a/image.png" alt=""></p>
<h2 id="코드-1">코드</h2>
<p><strong>시간 초과</strong></p>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int n, arr[16][16], max_num;
int vis[16];

void dfs(int k, int p, int num) {
    if (k == n) {
        max_num = max(num, max_num);
        return;
    }
    vis[k] = 1;
    for (int i = 0; i &lt; n; i++) {
        if (!vis[i] &amp;&amp; arr[k][i] &gt;= p) {
            dfs(i, arr[k][i], num + 1);
            vis[i] = 0;
        }
    }
    max_num = max(max_num, num);
}

int main() {
    cin &gt;&gt; n;
    for (int i = 0; i &lt; n; i++) {
        string s;
        cin &gt;&gt; s;
        for (int j = 0; j &lt; n; j++) {
            arr[i][j] = s[j] - &#39;0&#39;;
        }
    }
    dfs(0, 0, 1);
    cout &lt;&lt; max_num;
}</code></pre>
<p>처음에 dfs만 이용해서 풀었는데, 시간 초과가 발생했다. 당연히 중복 연산이 많았겠지.. 라고 생각하며 해당 코드에 dp를 적용하려고 했는데..??</p>
<p>도무지 모르겠어서 구글링으로 참고했다!! 그랬더니 방문한 사람을 비트 마스크를 이용해서 푸는 방법을 이용하더라. 방문을 표시할 필요가 있고, 사람 수가 적은 경우는 비트 마스크를 사용할 수 있다는 것을 배웠다.</p>
<p><strong>비트 마스크 이용 및 성공</strong></p>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int n, arr[16][16], dp[16][10][1 &lt;&lt; 16];

int dfs(int k, int p, int vis) {
    int&amp; ret = dp[k][p][vis];
    if (ret != -1) return ret;
    ret = 0;
    for (int i = 0; i &lt; n; i++) {
        if (!(vis &amp; (1 &lt;&lt; i)) &amp;&amp; arr[k][i] &gt;= p) {
            int nv = vis | (1 &lt;&lt; i);
            ret = max(ret, dfs(i, arr[k][i], nv) + 1);
        }
    }
    return ret;
}

int main() {
    cin &gt;&gt; n;
    for (int i = 0; i &lt; n; i++) {
        string s;
        cin &gt;&gt; s;
        for (int j = 0; j &lt; n; j++) {
            arr[i][j] = s[j] - &#39;0&#39;;
        }
    }
    memset(dp, -1, sizeof(dp));
    dfs(0, 0, 1);

    cout &lt;&lt; dp[0][0][1] + 1;
}</code></pre>
<p>비트 마스크 이용하는 문제들을 더 풀어봐야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 2, 2022 KAKAO TECH INTERNSHIP]]></title>
            <link>https://velog.io/@ooing-0720/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-2022-KAKAO-TECH-INTERNSHIP</link>
            <guid>https://velog.io/@ooing-0720/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-2022-KAKAO-TECH-INTERNSHIP</guid>
            <pubDate>Mon, 25 Mar 2024 11:40:29 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>오늘의 문제</strong>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/118667">두 큐 합 같게 만들기</a>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/152996">시소 짝꿍</a></p>
</blockquote>
<h1 id="두-큐-합-같게-만들기">두 큐 합 같게 만들기</h1>
<p><strong>문제 설명</strong>
길이가 같은 두 개의 큐가 주어집니다. 하나의 큐를 골라 원소를 추출(pop)하고, 추출된 원소를 다른 큐에 집어넣는(insert) 작업을 통해 각 큐의 원소 합이 같도록 만들려고 합니다. 이때 필요한 작업의 최소 횟수를 구하고자 합니다. 한 번의 pop과 한 번의 insert를 합쳐서 작업을 1회 수행한 것으로 간주합니다.</p>
<p>큐는 먼저 집어넣은 원소가 먼저 나오는 구조입니다. 이 문제에서는 큐를 배열로 표현하며, 원소가 배열 앞쪽에 있을수록 먼저 집어넣은 원소임을 의미합니다. 즉, pop을 하면 배열의 첫 번째 원소가 추출되며, insert를 하면 배열의 끝에 원소가 추가됩니다. 예를 들어 큐 <code>[1, 2, 3, 4]</code>가 주어졌을 때, pop을 하면 맨 앞에 있는 원소 1이 추출되어 <code>[2, 3, 4]</code>가 되며, 이어서 5를 insert하면 <code>[2, 3, 4, 5]</code>가 됩니다.</p>
<p>다음은 두 큐를 나타내는 예시입니다.</p>
<pre><code>queue1 = [3, 2, 7, 2]
queue2 = [4, 6, 5, 1]</code></pre><p>두 큐에 담긴 모든 원소의 합은 30입니다. 따라서, 각 큐의 합을 15로 만들어야 합니다. 예를 들어, 다음과 같이 2가지 방법이 있습니다.</p>
<p>queue2의 4, 6, 5를 순서대로 추출하여 queue1에 추가한 뒤, queue1의 3, 2, 7, 2를 순서대로 추출하여 queue2에 추가합니다. 그 결과 queue1은 [4, 6, 5], queue2는 [1, 3, 2, 7, 2]가 되며, 각 큐의 원소 합은 15로 같습니다. 이 방법은 작업을 7번 수행합니다.
queue1에서 3을 추출하여 queue2에 추가합니다. 그리고 queue2에서 4를 추출하여 queue1에 추가합니다. 그 결과 queue1은 [2, 7, 2, 4], queue2는 [6, 5, 1, 3]가 되며, 각 큐의 원소 합은 15로 같습니다. 이 방법은 작업을 2번만 수행하며, 이보다 적은 횟수로 목표를 달성할 수 없습니다.
따라서 각 큐의 원소 합을 같게 만들기 위해 필요한 작업의 최소 횟수는 2입니다.</p>
<p>길이가 같은 두 개의 큐를 나타내는 정수 배열 <code>queue1</code>, <code>queue2</code>가 매개변수로 주어집니다. 각 큐의 원소 합을 같게 만들기 위해 필요한 작업의 최소 횟수를 return 하도록 solution 함수를 완성해주세요. 단, 어떤 방법으로도 각 큐의 원소 합을 같게 만들 수 없는 경우, -1을 return 해주세요.</p>
<p><strong>제한사항</strong>
1 ≤ <code>queue1</code>의 길이 = <code>queue2</code>의 길이 ≤ 300,000
1 ≤ <code>queue1</code>의 원소, <code>queue2</code>의 원소 ≤ 109
주의: 언어에 따라 합 계산 과정 중 산술 오버플로우 발생 가능성이 있으므로 long type 고려가 필요합니다.</p>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int solution(vector&lt;int&gt; queue1, vector&lt;int&gt; queue2) {
    int answer = 0, max_ans = queue1.size() * 3;
    long long total = 0, sum1 = 0, sum2 = 0;
    queue&lt;int&gt; q1, q2;
    for(int i = 0; i &lt; queue1.size(); i++){
        total += queue1[i];
        total += queue2[i];
        sum1 += queue1[i];
        sum2 += queue2[i];
        q1.push(queue1[i]);
        q2.push(queue2[i]);
    }
    if(total % 2 == 1) return -1;

    while(1) {
        if(sum1 == sum2) return answer;
        if(sum1 &gt; sum2) {          
            sum1 -= q1.front(); sum2 += q1.front();
            q2.push(q1.front()); q1.pop();
        }
        else {
            sum2 -= q2.front(); sum1 += q2.front();
            q1.push(q2.front()); q2.pop();
        }
        if(answer &gt; max_ans) return -1;
        ++answer;
    }
    return answer;
}</code></pre>
<p>문제가 문제인지라 큐로 푸는게 편할 것 같아 큐를 이용했다.</p>
<h1 id="시소-짝꿍">시소 짝꿍</h1>
<p><strong>문제 설명</strong>
어느 공원 놀이터에는 시소가 하나 설치되어 있습니다. 이 시소는 중심으로부터 2(m), 3(m), 4(m) 거리의 지점에 좌석이 하나씩 있습니다.
이 시소를 두 명이 마주 보고 탄다고 할 때, 시소가 평형인 상태에서 각각에 의해 시소에 걸리는 토크의 크기가 서로 상쇄되어 완전한 균형을 이룰 수 있다면 그 두 사람을 시소 짝꿍이라고 합니다. 즉, 탑승한 사람의 무게와 시소 축과 좌석 간의 거리의 곱이 양쪽 다 같다면 시소 짝꿍이라고 할 수 있습니다.
사람들의 몸무게 목록 <code>weights</code>이 주어질 때, 시소 짝꿍이 몇 쌍 존재하는지 구하여 return 하도록 solution 함수를 완성해주세요.</p>
<p><strong>제한 사항</strong></p>
<ul>
<li>2 ≤ <code>weights</code>의 길이 ≤ 100,000</li>
<li>100 ≤ <code>weights[i]</code> ≤ 1,000<ul>
<li>몸무게 단위는 N(뉴턴)으로 주어집니다.</li>
<li>몸무게는 모두 정수입니다.</li>
</ul>
</li>
</ul>
<h2 id="코드-1">코드</h2>
<p><strong>이중 for문</strong></p>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

long long solution(vector&lt;int&gt; weights) {
    sort(weights.begin(), weights.end());
    long long answer = 0;

    for(int i = 0; i &lt; weights.size() - 1; i++){
        for(int j = i + 1; j &lt; weights.size(); j++){ 
            if(weights[i] * 4 &lt; weights[j]) break;
            if(weights[i] == weights[j] || weights[i] * 3 == weights[j] * 2 || 
               weights[i] * 4 == weights[j] * 2 || weights[i] * 4 == weights[j] * 3) ++answer;
        }
    }

    return answer;
}</code></pre>
<p>백준이었으면 시간 초과 났을 것 같은데..? 싶어서 배열을 이용하는 방법으로도 풀어보았다.
실제로 위의 코드는 최대 8000ms의 시간이 걸렸지만, 배열을 이용한 코드에서는 최대 0.41ms밖에 걸리지 않았다.</p>
<p><strong>배열 이용</strong></p>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

long long solution(vector&lt;int&gt; weights) {
    long long answer = 0;
    vector&lt;long long&gt; arr(1001, 0);
    for(int i : weights) ++arr[i];

    for(int i = 100; i &lt;= 1000; i++){ 
        if(!arr[i]) continue;
        if(arr[i] &gt; 1) answer += arr[i] * (arr[i] - 1) / 2;
        if(i * 2 &lt;= 1000 &amp;&amp; arr[i * 2]) answer += arr[i] * arr[i * 2];
        if(i * 3 / 2 &lt;= 1000 &amp;&amp; (i * 3) % 2 == 0 &amp;&amp; arr[i * 3 / 2]) answer += arr[i] * arr[i * 3 / 2];
        if(i * 4 / 3 &lt;= 1000 &amp;&amp; (i * 4) % 3 == 0 &amp;&amp; arr[i * 4 / 3]) answer += arr[i] * arr[i * 4 / 3];
    }

    return answer;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 0324 Level 2]]></title>
            <link>https://velog.io/@ooing-0720/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-0324-Level-2</link>
            <guid>https://velog.io/@ooing-0720/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-0324-Level-2</guid>
            <pubDate>Sun, 24 Mar 2024 13:34:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>오늘의 문제</strong>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/155651">호텔 대실</a>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/154540">무인도 여행</a>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/154539">뒤에 있는 큰 수 찾기</a></p>
</blockquote>
<h1 id="호텔-대실">호텔 대실</h1>
<p><strong>문제 설명</strong>
호텔을 운영 중인 코니는 최소한의 객실만을 사용하여 예약 손님들을 받으려고 합니다. 한 번 사용한 객실은 퇴실 시간을 기준으로 10분간 청소를 하고 다음 손님들이 사용할 수 있습니다.
예약 시각이 문자열 형태로 담긴 2차원 배열 <code>book_time</code>이 매개변수로 주어질 때, 코니에게 필요한 최소 객실의 수를 return 하는 solution 함수를 완성해주세요.</p>
<p><strong>제한사항</strong></p>
<ul>
<li>1 ≤ <code>book_time</code>의 길이 ≤ 1,000<ul>
<li><code>book_time[i]</code>는 [&quot;HH:MM&quot;, &quot;HH:MM&quot;]의 형태로 이루어진 배열입니다<ul>
<li>[대실 시작 시각, 대실 종료 시각] 형태입니다.</li>
</ul>
</li>
<li>시각은 HH:MM 형태로 24시간 표기법을 따르며, &quot;00:00&quot; 부터 &quot;23:59&quot; 까지로 주어집니다.<ul>
<li>예약 시각이 자정을 넘어가는 경우는 없습니다.</li>
<li>시작 시각은 항상 종료 시각보다 빠릅니다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

bool cmp (vector&lt;string&gt; t1, vector&lt;string&gt; t2) {
    if(t1[1].substr(0, 2) == t2[1].substr(0, 2)) {
        return t1[1].substr(3) &lt; t2[1].substr(3); 
    }
    return t1[1].substr(0, 2) &lt; t2[1].substr(0, 2);
}

bool same(vector&lt;string&gt; t1, vector&lt;string&gt; t2) {
    int fh = stoi(t1[1].substr(0, 2));
    int fm = stoi(t1[1].substr(3)) + 10;
    if(fm &gt;= 60) {
        fm -= 60; fh += 1;
    }
    int ih = stoi(t2[0].substr(0, 2));
    int im = stoi(t2[0].substr(3));

    if(fh &lt; ih) return true;
    else if(fh == ih) return fm &lt;= im;
    else return false;
}

int solution(vector&lt;vector&lt;string&gt;&gt; book_time) {
    sort(book_time.begin(), book_time.end(), cmp);

    vector&lt;vector&lt;string&gt;&gt; room;
    room.emplace_back(book_time[0]);
    for(int i = 1; i &lt; book_time.size(); i++){
        for(int j = room.size() - 1; j &gt;= 0 ; j--) {
            if(same(room[j], book_time[i])) {
                room.erase(room.begin() + j);
                break;
            }
        }
        room.emplace_back(book_time[i]);
    }
    return room.size();
}</code></pre>
<p>시간을 다 int형으로 나타내서 priority_queue를 쓸 걸<del>!</del>!</p>
<h1 id="무인도-여행">무인도 여행</h1>
<p><strong>문제 설명</strong>
메리는 여름을 맞아 무인도로 여행을 가기 위해 지도를 보고 있습니다. 지도에는 바다와 무인도들에 대한 정보가 표시돼 있습니다. 지도는 1 x 1크기의 사각형들로 이루어진 직사각형 격자 형태이며, 격자의 각 칸에는 &#39;X&#39; 또는 1에서 9 사이의 자연수가 적혀있습니다. 지도의 &#39;X&#39;는 바다를 나타내며, 숫자는 무인도를 나타냅니다. 이때, 상, 하, 좌, 우로 연결되는 땅들은 하나의 무인도를 이룹니다. 지도의 각 칸에 적힌 숫자는 식량을 나타내는데, 상, 하, 좌, 우로 연결되는 칸에 적힌 숫자를 모두 합한 값은 해당 무인도에서 최대 며칠동안 머물 수 있는지를 나타냅니다. 어떤 섬으로 놀러 갈지 못 정한 메리는 우선 각 섬에서 최대 며칠씩 머물 수 있는지 알아본 후 놀러갈 섬을 결정하려 합니다.</p>
<p>지도를 나타내는 문자열 배열 <code>maps</code>가 매개변수로 주어질 때, 각 섬에서 최대 며칠씩 머무를 수 있는지 배열에 오름차순으로 담아 return 하는 solution 함수를 완성해주세요. 만약 지낼 수 있는 무인도가 없다면 -1을 배열에 담아 return 해주세요.</p>
<p><strong>제한사항</strong></p>
<ul>
<li>3 ≤ <code>maps</code>의 길이 ≤ 100<ul>
<li>3 ≤ <code>maps[i]</code>의 길이 ≤ 100</li>
<li><code>maps[i]</code>는 &#39;X&#39; 또는 1 과 9 사이의 자연수로 이루어진 문자열입니다.</li>
<li>지도는 직사각형 형태입니다.</li>
</ul>
</li>
</ul>
<h2 id="코드-1">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int n, m;
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
vector&lt;vector&lt;int&gt;&gt; vis;
vector&lt;string&gt; _maps;

int bfs(int x, int y) {
    queue&lt;pair&lt;int, int&gt;&gt; q;
    q.push({x, y});
    int sz = _maps[x][y] - &#39;0&#39;;
    vis[x][y] = 1;

    while(!q.empty()) {
        x = q.front().first;
        y = q.front().second;
        q.pop();

        for(int i = 0; i &lt; 4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx &lt; 0 || nx &gt;= n || ny &lt; 0 || ny &gt;= m) continue;
            if(vis[nx][ny] || _maps[nx][ny] == &#39;X&#39;) continue;

            q.push({nx, ny});
            sz += _maps[nx][ny] - &#39;0&#39;;
            vis[nx][ny] = 1;
        }
    }
    return sz;
}

vector&lt;int&gt; solution(vector&lt;string&gt; maps) {
    n = maps.size(); m = maps[0].size(); _maps = maps;
    vis = vector&lt;vector&lt;int&gt;&gt;(n, vector&lt;int&gt;(m, 0));
    vector&lt;int&gt; answer;

    for(int i = 0; i &lt; n; i++){ 
        for(int j = 0; j &lt; m; j++){
            if(!vis[i][j] &amp;&amp; maps[i][j] != &#39;X&#39;) {
                answer.emplace_back(bfs(i, j));
            }
        }
    }
    if(answer.empty()) return {-1};
    sort(answer.begin(), answer.end());
    return answer;
}</code></pre>
<p>평범한 bfs 문제였다</p>
<h1 id="뒤에-있는-큰-수-찾기">뒤에 있는 큰 수 찾기</h1>
<p><strong>문제 설명</strong>
정수로 이루어진 배열 <code>numbers</code>가 있습니다. 배열 의 각 원소들에 대해 자신보다 뒤에 있는 숫자 중에서 자신보다 크면서 가장 가까이 있는 수를 뒷 큰수라고 합니다.
정수 배열 <code>numbers</code>가 매개변수로 주어질 때, 모든 원소에 대한 뒷 큰수들을 차례로 담은 배열을 return 하도록 solution 함수를 완성해주세요. 단, 뒷 큰수가 존재하지 않는 원소는 -1을 담습니다.</p>
<p><strong>제한사항</strong></p>
<ul>
<li>4 ≤ <code>numbers</code>의 길이 ≤ 1,000,000<ul>
<li>1 ≤ <code>numbers[i]</code>≤ 1,000,000</li>
</ul>
</li>
</ul>
<h2 id="코드-2">코드</h2>
<p><strong>테스트 21, 22에서 시간 초과</strong></p>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

vector&lt;int&gt; solution(vector&lt;int&gt; numbers) {
    vector&lt;int&gt; answer(numbers.size(), -1);
    for(int i = numbers.size() - 2; i &gt;= 0; i--) {
        if(numbers[i] &lt; numbers[i + 1]) answer[i] = numbers[i + 1];
        else if(numbers[i] == numbers[i + 1]) answer[i] = answer[i + 1];
        else {
            if(numbers[i] &gt;= answer[i + 1]) {
                for(int j = i + 1; j &lt; numbers.size(); j++){
                    if(numbers[i] &lt; numbers[j]) {
                        answer[i] = numbers[j];
                        break;
                    }
                }
            }
            else answer[i] = answer[i + 1];
        }
    }
    return answer;
}</code></pre>
<p>시간 초과일 것 같다고 생각했다.. 
이 코드에서는 <code>else</code> 문에 들어갔을 때, <code>numbers[i]</code>보다 큰 값이 없는 경우 for문을 끝까지 돌기 때문에 중간에 탈출할 수 있는 구문을 만들어줘야겠다고 생각했다.</p>
<pre><code class="language-cpp"> else {
    if(numbers[i] &gt;= answer[i + 1]) {
        for(int j = i + 1; j &lt; numbers.size(); j++){
            if(numbers[i] &lt; numbers[j]) {
                answer[i] = numbers[j];
                break;
            }
            if(numbers[i] &gt;= numbers[j] &amp;&amp; answer[j] == -1) break;
    }
}</code></pre>
<p>이렇게 했더니 21번은 통과했다. 22번은 도대체 뭐지?!</p>
<p>잠깐 생각해본 결과 [5, 4, 1, 2, 3, 4, 5, 6] 이런 식으로 들어있으면 시간 초과가 발생할거라는 것을 알아냈다. 그래서 stack을 이용하기로 했다.</p>
<p><strong>성공</strong></p>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

vector&lt;int&gt; solution(vector&lt;int&gt; numbers) {
    vector&lt;int&gt; answer(numbers.size(), -1);
    stack&lt;int&gt; st;
    for(int i = numbers.size() - 2; i &gt;= 0; i--) {

        if(numbers[i] &lt; numbers[i + 1]) {
            answer[i] = numbers[i + 1];
            st.push(numbers[i + 1]);
        }
        else if(numbers[i] == numbers[i + 1]) answer[i] = answer[i + 1];
        else {
            if(numbers[i] &lt; answer[i + 1]) answer[i] = answer[i + 1];
            else {
                while(!st.empty()) {
                    if(numbers[i] &lt; st.top()) {
                        answer[i] = st.top();
                        st.push(answer[i]);
                        break;
                    }
                    st.pop();
                }
            }
        }
    }
    return answer;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 0322 Level 2, 2023 KAKAO BLIND RECRUITMENT]]></title>
            <link>https://velog.io/@ooing-0720/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-0322-Level-2</link>
            <guid>https://velog.io/@ooing-0720/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-0322-Level-2</guid>
            <pubDate>Fri, 22 Mar 2024 15:09:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>오늘의 문제</strong>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/160585">혼자서 하는 틱택토</a>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/159993">미로 탈출</a>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/150368">이모티콘 할인행사</a>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/150369">택배 배달과 수거하기</a></p>
</blockquote>
<h1 id="혼자서-하는-틱택토">혼자서 하는 틱택토</h1>
<p><strong>문제 설명</strong>
틱택토는 두 사람이 하는 게임으로 처음에 3x3의 빈칸으로 이루어진 게임판에 선공이 &quot;O&quot;, 후공이 &quot;X&quot;를 번갈아가면서 빈칸에 표시하는 게임입니다. 가로, 세로, 대각선으로 3개가 같은 표시가 만들어지면 같은 표시를 만든 사람이 승리하고 게임이 종료되며 9칸이 모두 차서 더 이상 표시를 할 수 없는 경우에는 무승부로 게임이 종료됩니다.</p>
<p>할 일이 없어 한가한 머쓱이는 두 사람이 하는 게임인 틱택토를 다음과 같이 혼자서 하려고 합니다.</p>
<ul>
<li>혼자서 선공과 후공을 둘 다 맡는다.</li>
<li>틱택토 게임을 시작한 후 &quot;O&quot;와 &quot;X&quot;를 혼자서 번갈아 가면서 표시를 하면서 진행한다.</li>
</ul>
<p>틱택토는 단순한 규칙으로 게임이 금방 끝나기에 머쓱이는 한 게임이 종료되면 다시 3x3 빈칸을 그린 뒤 다시 게임을 반복했습니다. 그렇게 틱택토 수 십 판을 했더니 머쓱이는 게임 도중에 다음과 같이 규칙을 어기는 실수를 했을 수도 있습니다.</p>
<ul>
<li>&quot;O&quot;를 표시할 차례인데 &quot;X&quot;를 표시하거나 반대로 &quot;X&quot;를 표시할 차례인데 &quot;O&quot;를 표시한다.</li>
<li>선공이나 후공이 승리해서 게임이 종료되었음에도 그 게임을 진행한다.</li>
</ul>
<p>게임 도중 게임판을 본 어느 순간 머쓱이는 본인이 실수를 했는지 의문이 생겼습니다. 혼자서 틱택토를 했기에 게임하는 과정을 지켜본 사람이 없어 이를 알 수는 없습니다. 그러나 게임판만 봤을 때 실제로 틱택토 규칙을 지켜서 진행했을 때 나올 수 있는 상황인지는 판단할 수 있을 것 같고 문제가 없다면 게임을 이어서 하려고 합니다.</p>
<p>머쓱이가 혼자서 게임을 진행하다 의문이 생긴 틱택토 게임판의 정보를 담고 있는 문자열 배열 <code>board</code>가 매개변수로 주어질 때, 이 게임판이 규칙을 지켜서 틱택토를 진행했을 때 나올 수 있는 게임 상황이면 1을 아니라면 0을 return 하는 solution 함수를 작성해 주세요.</p>
<p><strong>제한사항</strong></p>
<ul>
<li><code>board</code>의 길이 = <code>board[i]</code>의 길이 = 3<ul>
<li><code>board</code>의 원소는 모두 &quot;O&quot;, &quot;X&quot;, &quot;.&quot;으로만 이루어져 있습니다.</li>
</ul>
</li>
<li><code>board[i][j]</code>는 <code>i</code> + 1행 <code>j</code> + 1열에 해당하는 칸의 상태를 나타냅니다.<ul>
<li>&quot;.&quot;은 빈칸을, &quot;O&quot;와 &quot;X&quot;는 해당 문자로 칸이 표시되어 있다는 의미입니다.</li>
</ul>
</li>
</ul>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int solution(vector&lt;string&gt; board) {
    int onum = 0, xnum = 0;
    for(string s : board){
        for(char c : s){
            if(c == &#39;O&#39;) onum++;
            else if(c == &#39;X&#39;) xnum++;
        }
    }
    if(onum &lt; xnum || onum - xnum &gt; 1) return 0;

    bool owin = false, xwin = false;
    for(int i = 0; i &lt; 3; i++){
        if(board[i][0] != &#39;.&#39; &amp;&amp; board[i][0] == board[i][1] &amp;&amp; board[i][0] == board[i][2]) {
            if(board[i][0] == &#39;O&#39;) owin = true;
            else xwin = true;
        }
        if(board[0][i] != &#39;.&#39; &amp;&amp; board[0][i] == board[1][i] &amp;&amp; board[0][i] == board[2][i]) {
            if(board[0][i] == &#39;O&#39;) owin = true;
            else xwin = true;
        }
    }
    if(board[0][0] != &#39;.&#39; &amp;&amp; board[0][0] == board[1][1] &amp;&amp; board[0][0] == board[2][2]){
        if(board[0][0] == &#39;O&#39;) owin = true;
        else xwin = true;
    }
    if(board[2][0] != &#39;.&#39; &amp;&amp; board[2][0] == board[1][1] &amp;&amp; board[2][0] == board[0][2])  {
        if(board[2][0] == &#39;O&#39;) owin = true;
        else xwin = true;
    }

    if(owin){
        if(xwin) return 0;
        else if(onum &lt;= xnum) return 0;
    }
    else if(xwin &amp;&amp; onum != xnum) return 0;
    return 1;
}</code></pre>
<p>3x3의 작은 배열이므로 그냥 모든 경우의 수를 구해서 풀어도 된다.</p>
<h1 id="미로-탈출">미로 탈출</h1>
<p><strong>문제 설명</strong>
1 x 1 크기의 칸들로 이루어진 직사각형 격자 형태의 미로에서 탈출하려고 합니다. 각 칸은 통로 또는 벽으로 구성되어 있으며, 벽으로 된 칸은 지나갈 수 없고 통로로 된 칸으로만 이동할 수 있습니다. 통로들 중 한 칸에는 미로를 빠져나가는 문이 있는데, 이 문은 레버를 당겨서만 열 수 있습니다. 레버 또한 통로들 중 한 칸에 있습니다. 따라서, 출발 지점에서 먼저 레버가 있는 칸으로 이동하여 레버를 당긴 후 미로를 빠져나가는 문이 있는 칸으로 이동하면 됩니다. 이때 아직 레버를 당기지 않았더라도 출구가 있는 칸을 지나갈 수 있습니다. 미로에서 한 칸을 이동하는데 1초가 걸린다고 할 때, 최대한 빠르게 미로를 빠져나가는데 걸리는 시간을 구하려 합니다.</p>
<p>미로를 나타낸 문자열 배열 <code>maps</code>가 매개변수로 주어질 때, 미로를 탈출하는데 필요한 최소 시간을 return 하는 solution 함수를 완성해주세요. 만약, 탈출할 수 없다면 -1을 return 해주세요.</p>
<p>제한사항</p>
<ul>
<li>5 ≤ <code>maps</code>의 길이 ≤ 100<ul>
<li>5 ≤ <code>maps[i]</code>의 길이 ≤ 100</li>
<li><code>maps[i]</code>는 다음 5개의 문자들로만 이루어져 있습니다.<ul>
<li>S : 시작 지점</li>
<li>E : 출구</li>
<li>L : 레버</li>
<li>O : 통로</li>
<li>X : 벽</li>
</ul>
</li>
<li>시작 지점과 출구, 레버는 항상 다른 곳에 존재하며 한 개씩만 존재합니다.</li>
<li>출구는 레버가 당겨지지 않아도 지나갈 수 있으며, 모든 통로, 출구, 레버, 시작점은 여러 번 지나갈 수 있습니다.</li>
</ul>
</li>
</ul>
<h2 id="코드-1">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

vector&lt;string&gt; _maps;
int n, m, sx, sy, lx, ly, ex, ey;
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};

int bfs(int x, int y, int fx, int fy) {
    queue&lt;pair&lt;int, int&gt;&gt; q;
    vector&lt;vector&lt;int&gt;&gt; dis(n, vector&lt;int&gt;(m, -1));
    q.push({x, y});
    dis[x][y] = 0;

    while(!q.empty()){
        x = q.front().first;
        y = q.front().second;
        q.pop();

        if(x == fx &amp;&amp; y == fy) return dis[x][y];
        for(int i = 0; i &lt; 4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx &lt; 0 || nx &gt;= n || ny &lt; 0 || ny &gt;= m) continue;
            if(dis[nx][ny] != -1 || _maps[nx][ny] == &#39;X&#39;) continue;
            q.push({nx, ny});
            dis[nx][ny] = dis[x][y] + 1;
        }
    }
    return -1;
}

int solution(vector&lt;string&gt; maps) {
    _maps = maps;
    n = maps.size(); m = maps[0].size();
    for(int i = 0; i &lt; n; i++){
        for(int j = 0; j &lt; m; j++){
            if(maps[i][j] == &#39;S&#39;) {
                sx = i; sy = j;
            }
            else if(maps[i][j] == &#39;E&#39;) {
                ex = i; ey = j;
            }
            else if(maps[i][j] == &#39;L&#39;) {
                lx = i; ly = j;
            }
        }
    }
    int move1 = bfs(sx, sy, lx, ly);
    int move2 = bfs(lx, ly, ex, ey);
    if(move1 == -1 || move2 == -1) return -1;
    return move1 + move2;
}</code></pre>
<p>S에서 L까지의 최단 거리 + L에서 E까지의 최단 거리를 구하면 된다.</p>
<h1 id="이모티콘-할인행사">이모티콘 할인행사</h1>
<p><strong>문제 설명</strong>
카카오톡에서는 이모티콘을 무제한으로 사용할 수 있는 이모티콘 플러스 서비스 가입자 수를 늘리려고 합니다.
이를 위해 카카오톡에서는 이모티콘 할인 행사를 하는데, 목표는 다음과 같습니다.</p>
<ol>
<li>이모티콘 플러스 서비스 가입자를 최대한 늘리는 것.</li>
<li>이모티콘 판매액을 최대한 늘리는 것.</li>
</ol>
<p><strong>1번 목표가 우선이며, 2번 목표가 그 다음입니다.</strong></p>
<p>이모티콘 할인 행사는 다음과 같은 방식으로 진행됩니다.</p>
<ul>
<li><p><code>n</code>명의 카카오톡 사용자들에게 이모티콘 <code>m</code>개를 할인하여 판매합니다.</p>
</li>
<li><p>이모티콘마다 할인율은 다를 수 있으며, 할인율은 10%, 20%, 30%, 40% 중 하나로 설정됩니다.
카카오톡 사용자들은 다음과 같은 기준을 따라 이모티콘을 사거나, 이모티콘 플러스 서비스에 가입합니다.</p>
</li>
<li><p>각 사용자들은 자신의 기준에 따라 일정 비율 이상 할인하는 이모티콘을 모두 구매합니다.</p>
</li>
<li><p>각 사용자들은 자신의 기준에 따라 이모티콘 구매 비용의 합이 일정 가격 이상이 된다면, 이모티콘 구매를 모두 취소하고 이모티콘 플러스 서비스에 가입합니다.</p>
</li>
</ul>
<p>다음은 2명의 카카오톡 사용자와 2개의 이모티콘이 있을때의 예시입니다.</p>
<table>
<thead>
<tr>
<th>사용자</th>
<th>비율</th>
<th>가격</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>40</td>
<td>10,000</td>
</tr>
<tr>
<td>2</td>
<td>25</td>
<td>10,000</td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>이모티콘</th>
<th>가격</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>7,000</td>
</tr>
<tr>
<td>2</td>
<td>9,000</td>
</tr>
</tbody></table>
<p>1번 사용자는 40%이상 할인하는 이모티콘을 모두 구매하고, 이모티콘 구매 비용이 10,000원 이상이 되면 이모티콘 구매를 모두 취소하고 이모티콘 플러스 서비스에 가입합니다.
2번 사용자는 25%이상 할인하는 이모티콘을 모두 구매하고, 이모티콘 구매 비용이 10,000원 이상이 되면 이모티콘 구매를 모두 취소하고 이모티콘 플러스 서비스에 가입합니다.</p>
<p>1번 이모티콘의 가격은 7,000원, 2번 이모티콘의 가격은 9,000원입니다.</p>
<p>만약, 2개의 이모티콘을 모두 40%씩 할인한다면, 1번 사용자와 2번 사용자 모두 1,2번 이모티콘을 구매하게 되고, 결과는 다음과 같습니다.</p>
<table>
<thead>
<tr>
<th>사용자</th>
<th>구매한 이모티콘</th>
<th>이모티콘 구매 비용</th>
<th>이모티콘 플러스 서비스 가입 여부</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>1, 2</td>
<td>9,600</td>
<td>X</td>
</tr>
<tr>
<td>2</td>
<td>1, 2</td>
<td>9,600</td>
<td>X</td>
</tr>
</tbody></table>
<p>이모티콘 플러스 서비스 가입자는 0명이 늘어나고 이모티콘 판매액은 19,200원이 늘어납니다.</p>
<p>하지만, 1번 이모티콘을 30% 할인하고 2번 이모티콘을 40% 할인한다면 결과는 다음과 같습니다.</p>
<table>
<thead>
<tr>
<th>사용자</th>
<th>구매한 이모티콘</th>
<th>이모티콘 구매 비용</th>
<th>이모티콘 플러스 서비스 가입 여부</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>2</td>
<td>5,400</td>
<td>X</td>
</tr>
<tr>
<td>2</td>
<td>1, 2</td>
<td>10,300</td>
<td>O</td>
</tr>
</tbody></table>
<p>2번 사용자는 이모티콘 구매 비용을 10,000원 이상 사용하여 이모티콘 구매를 모두 취소하고 이모티콘 플러스 서비스에 가입하게 됩니다.
따라서, 이모티콘 플러스 서비스 가입자는 1명이 늘어나고 이모티콘 판매액은 5,400원이 늘어나게 됩니다.</p>
<p>카카오톡 사용자 <code>n</code>명의 구매 기준을 담은 2차원 정수 배열 <code>users</code>, 이모티콘 <code>m</code>개의 정가를 담은 1차원 정수 배열 <code>emoticons</code>가 주어집니다. 이때, 행사 목적을 최대한으로 달성했을 때의 이모티콘 플러스 서비스 가입 수와 이모티콘 매출액을 1차원 정수 배열에 담아 return 하도록 solution 함수를 완성해주세요.</p>
<p><strong>제한사항</strong></p>
<ul>
<li>1 ≤ <code>users</code>의 길이 = n ≤ 100<ul>
<li><code>users</code>의 원소는 [<code>비율</code>, <code>가격</code>]의 형태입니다.</li>
<li><code>users[i]</code>는 <code>i+1</code>번 고객의 구매 기준을 의미합니다.</li>
<li>비율% 이상의 할인이 있는 이모티콘을 모두 구매한다는 의미입니다.<ul>
<li>1 ≤ <code>비율</code> ≤ 40</li>
</ul>
</li>
<li>가격이상의 돈을 이모티콘 구매에 사용한다면, 이모티콘 구매를 모두 취소하고 이모티콘 플러스 서비스에 가입한다는 의미입니다.<ul>
<li>100 ≤ <code>가격</code> ≤ 1,000,000</li>
<li><code>가격</code>은 100의 배수입니다.</li>
</ul>
</li>
</ul>
</li>
<li>1 ≤ <code>emoticons</code>의 길이 = m ≤ 7<ul>
<li><code>emoticons[i]</code>는 <code>i+1</code>번 이모티콘의 정가를 의미합니다.</li>
<li>100 ≤ <code>emoticons</code>의 원소 ≤ 1,000,000</li>
<li><code>emoticons</code>의 원소는 100의 배수입니다.</li>
</ul>
</li>
</ul>
<h2 id="코드-2">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int n, eplus, price;
vector&lt;int&gt; sale, _emoticons;
vector&lt;vector&lt;int&gt;&gt; _users;
int pc[4] = {10, 20, 30, 40};

void buy(int k) {
    if(k == n) {
        int cnt = 0, emo = 0;
        for(vector&lt;int&gt; v : _users) {
            int now = 0;
            for(int i = 0; i &lt; n; i++){
                if(sale[i] &gt;= v[0]) now += (_emoticons[i] * (100 - sale[i]) / 100);
            }
            if(now &gt;= v[1]) ++cnt;
            else emo += now;
        }
        if(eplus &lt; cnt) {
            eplus = cnt; price = emo;
        }
        else if(eplus == cnt) price = max(price, emo);
        return;
    }
    for(int i = 0; i &lt; 4; i++){
        sale[k] = pc[i];
        buy(k + 1);
    }

}

vector&lt;int&gt; solution(vector&lt;vector&lt;int&gt;&gt; users, vector&lt;int&gt; emoticons) {
    n = emoticons.size();
    _users = users; _emoticons = emoticons;
    sale = vector&lt;int&gt;(n, 0);
    buy(0);

    return {eplus, price};
}</code></pre>
<p>이모티콘의 할인률이 4가지, 이모티콘 개수가 7개이므로 모든 이모티콘의 모든 할인률을 계산해서 최댓값을 구해도 4*7가지밖에 없기 때문에 연산량이 그다지 많지 않다. </p>
<h1 id="택배-배달과-수거하기">택배 배달과 수거하기</h1>
<p><strong>문제 설명</strong>
<img src="https://velog.velcdn.com/images/ooing-0720/post/005d592f-4c32-48d9-ab70-10b57b188e3a/image.png" alt=""></p>
<p>당신은 일렬로 나열된 <code>n</code>개의 집에 택배를 배달하려 합니다. 배달할 물건은 모두 크기가 같은 재활용 택배 상자에 담아 배달하며, 배달을 다니면서 빈 재활용 택배 상자들을 수거하려 합니다.
배달할 택배들은 모두 재활용 택배 상자에 담겨서 물류창고에 보관되어 있고, <code>i</code>번째 집은 물류창고에서 거리 <code>i</code>만큼 떨어져 있습니다. 또한 <code>i</code>번째 집은 <code>j</code>번째 집과 거리 <code>j - i</code>만큼 떨어져 있습니다. (1 ≤ <code>i</code> ≤ <code>j</code> ≤ n)
트럭에는 재활용 택배 상자를 최대 <code>cap</code>개 실을 수 있습니다. 트럭은 배달할 재활용 택배 상자들을 실어 물류창고에서 출발해 각 집에 배달하면서, 빈 재활용 택배 상자들을 수거해 물류창고에 내립니다. 각 집마다 배달할 재활용 택배 상자의 개수와 수거할 빈 재활용 택배 상자의 개수를 알고 있을 때, 트럭 하나로 모든 배달과 수거를 마치고 물류창고까지 돌아올 수 있는 최소 이동 거리를 구하려 합니다. 각 집에 배달 및 수거할 때, 원하는 개수만큼 택배를 배달 및 수거할 수 있습니다.</p>
<p>다음은 <code>cap</code>=4 일 때, 최소 거리로 이동하면서 5개의 집에 배달 및 수거하는 과정을 나타낸 예시입니다.</p>
<p><strong>배달 및 수거할 재활용 택배 상자 개수</strong></p>
<table>
<thead>
<tr>
<th></th>
<th>집 #1</th>
<th>집 #2</th>
<th>집 #3</th>
<th>집 #4</th>
<th>집 #5</th>
</tr>
</thead>
<tbody><tr>
<td>배달</td>
<td>1개</td>
<td>0개</td>
<td>3개</td>
<td>1개</td>
<td>2개</td>
</tr>
<tr>
<td>수거</td>
<td>0개</td>
<td>3개</td>
<td>0개</td>
<td>4개</td>
<td>0개</td>
</tr>
</tbody></table>
<p><strong>배달 및 수거 과정</strong></p>
<table>
<thead>
<tr>
<th></th>
<th>집 #1</th>
<th>집 #2</th>
<th>집 #3</th>
<th>집 #4</th>
<th>집 #5</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>남은 배달/수거</td>
<td>1/0</td>
<td>0/3</td>
<td>3/0</td>
<td>1/4</td>
<td>2/0</td>
<td>물류창고에서 택배 3개를 트럭에 실어 출발합니다.</td>
</tr>
<tr>
<td>남은 배달/수거</td>
<td>1/0</td>
<td>0/3</td>
<td>3/0</td>
<td>0/4</td>
<td>0/0</td>
<td>물류창고에서 5번째 집까지 이동하면서(거리 5) 4번째 집에 택배 1개를 배달하고, 5번째 집에 택배 2개를 배달합니다.</td>
</tr>
<tr>
<td>남은 배달/수거</td>
<td>1/0</td>
<td>0/3</td>
<td>3/0</td>
<td>0/0</td>
<td>0/0</td>
<td>5번째 집에서 물류창고까지 이동하면서(거리 5) 4번째 집에서 빈 택배 상자 4개를 수거한 후, 수거한 빈 택배 상자를 물류창고에 내리고 택배 4개를 트럭에 싣습니다.</td>
</tr>
<tr>
<td>남은 배달/수거</td>
<td>0/0</td>
<td>0/3</td>
<td>0/0</td>
<td>0/0</td>
<td>0/0</td>
<td>물류창고에서 3번째 집까지 이동하면서(거리 3) 1번째 집에 택배 1개를 배달하고, 3번째 집에 택배 3개를 배달합니다.</td>
</tr>
<tr>
<td>남은 배달/수거</td>
<td>0/0</td>
<td>0/0</td>
<td>0/0</td>
<td>0/0</td>
<td>0/0</td>
<td>3번째 집에서 물류창고까지 이동하면서(거리 3) 2번째 집에서 빈 택배 상자 3개를 수거한 후, 수거한 빈 택배 상자를 물류창고에 내립니다.</td>
</tr>
</tbody></table>
<p>16(=5+5+3+3)의 거리를 이동하면서 모든 배달 및 수거를 마쳤습니다. 같은 거리로 모든 배달 및 수거를 마치는 다른 방법이 있지만, 이보다 짧은 거리로 모든 배달 및 수거를 마치는 방법은 없습니다.</p>
<p>트럭에 실을 수 있는 재활용 택배 상자의 최대 개수를 나타내는 정수 <code>cap</code>, 배달할 집의 개수를 나타내는 정수 <code>n</code>, 각 집에 배달할 재활용 택배 상자의 개수를 담은 1차원 정수 배열 <code>deliveries</code>와 각 집에서 수거할 빈 재활용 택배 상자의 개수를 담은 1차원 정수 배열 <code>pickups</code>가 매개변수로 주어집니다. 이때, 트럭 하나로 모든 배달과 수거를 마치고 물류창고까지 돌아올 수 있는 최소 이동 거리를 return 하도록 solution 함수를 완성해 주세요.</p>
<p><strong>제한사항</strong></p>
<ul>
<li>1 ≤ <code>cap</code> ≤ 50</li>
<li>1 ≤ <code>n</code> ≤ 100,000</li>
<li><code>deliveries</code>의 길이 = <code>pickups</code>의 길이 = <code>n</code><ul>
<li><code>deliveries[i]</code>는 <code>i+1</code>번째 집에 배달할 재활용 택배 상자의 개수를 나타냅니다.</li>
<li><code>pickups[i]</code>는 <code>i+1</code>번째 집에서 수거할 빈 재활용 택배 상자의 개수를 나타냅니다.</li>
<li>0 ≤ <code>deliveries</code>의 원소 ≤ 50</li>
<li>0 ≤ <code>pickups</code>의 원소 ≤ 50</li>
</ul>
</li>
<li>트럭의 초기 위치는 물류창고입니다.</li>
</ul>
<h2 id="코드-3">코드</h2>
<p><strong>테스트 16, 17 시간 초과</strong></p>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

long long solution(int cap, int n, vector&lt;int&gt; deliveries, vector&lt;int&gt; pickups) {
    long long answer = 0;
    int idx = n - 1, del = 0, pic = 0;
    while(1) {
        int now = 0, box = 0, dis = 0;
        for(int i = n - 1; i &gt;= 0; i--) {
            if(now == cap &amp;&amp; box == cap) break;
            if(deliveries[i] &gt; 0 &amp;&amp; now &lt; cap) {
                dis = max(dis, i + 1);
                del = i;
                if(deliveries[i] + now &lt;= cap) {
                    now += deliveries[i];
                    deliveries[i] = 0;
                }
                else {
                    deliveries[i] -= (cap - now);
                    now = cap;
                }
            }
            if(pickups[i] &gt; 0 &amp;&amp; box &lt; cap) {
                dis = max(dis, i + 1);
                pic = i;
                if(pickups[i] + box &lt;= cap) {
                    box += pickups[i];
                    pickups[i] = 0;
                }
                else {
                    pickups[i] -= (cap - box);
                    box = cap;
                }
            }
        }
        idx = max(del, pic);
        if(dis == 0) break;
        else answer += (dis * 2);
    }
    return answer;
}</code></pre>
<p>n번째 집(idx : n-1)부터 시작하며 배달과 수거를 했다. 아무래도 계속 i = n-1부터 시작하므로 비효율적인 것 같았다.</p>
<p><strong>성공</strong></p>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

long long solution(int cap, int n, vector&lt;int&gt; deliveries, vector&lt;int&gt; pickups) {
    long long answer = 0, delnum = 0, picnum = 0;
    for(int i = 0; i &lt; n; i++){
        delnum += deliveries[i];
        picnum += pickups[i];
    }
    while(1) {
        int now = 0, box = 0, dis = 0;
        for(int i = idx; i &gt;= 0; i--) {
            if((now == cap || delnum &lt;= 0) &amp;&amp; (box == cap || picnum &lt;= 0)) break;
            if(deliveries[i] &gt; 0 &amp;&amp; now &lt; cap) {
                dis = max(dis, i + 1);
                if(deliveries[i] + now &lt;= cap) {
                    now += deliveries[i];
                    deliveries[i] = 0;
                }
                else {
                    deliveries[i] -= (cap - now);
                    now = cap;
                }
            }
            if(pickups[i] &gt; 0 &amp;&amp; box &lt; cap) {
                dis = max(dis, i + 1);
                if(pickups[i] + box &lt;= cap) {
                    box += pickups[i];
                    pickups[i] = 0;
                }
                else {
                    pickups[i] -= (cap - box);
                    box = cap;
                }
            }
        }
        idx = max(del, pic);
        if(dis == 0) break;
        else answer += (dis * 2);
        delnum -= cap; picnum -= cap;
    }
    return answer;
}</code></pre>
<p>처음에는 idx 변수를 이용해 시작하는 집만 변경하게 했다. 배달과 수거 중 해야하는 일이 남은(?) 집의 인덱스가 더 큰 곳을 저장하게 해서 해당 인덱스부터 다시 시작하게 했으나.. 17번에서 또 시간초과.</p>
<p>작성한 코드에서는 now(배달한 상자 수)와 box(수거한 상자 수)가 cap이 되어야만 for문에서 탈출하므로, 둘 중 하나의 작업이 모두 끝난 상태에서 다른 작업을 하는 경우 i = 0이 될 때까지 for문을 탈출할 수 없다. 이것 때문에 시간 초과가 발생하는 것으로 판단해서 남은 배달 수, 남은 수거 수를 나타내는 변수를 만들어 관리했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 0321 PCCP 기출 문제 등]]></title>
            <link>https://velog.io/@ooing-0720/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-0321-PCCP-%EA%B8%B0%EC%B6%9C-%EB%AC%B8%EC%A0%9C</link>
            <guid>https://velog.io/@ooing-0720/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-0321-PCCP-%EA%B8%B0%EC%B6%9C-%EB%AC%B8%EC%A0%9C</guid>
            <pubDate>Thu, 21 Mar 2024 15:31:46 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>오늘의 문제</strong>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/250136">[PCCP 기출문제] 2번 / 석유 시추</a>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/169199">리코쳇 로봇</a>
<a href="https://school.programmers.co.kr/learn/courses/30/lessons/169198">당구 연습</a></p>
</blockquote>
<h1 id="pccp-기출문제-2번--석유-시추">[PCCP 기출문제] 2번 / 석유 시추</h1>
<p><strong>문제 설명</strong>
[본 문제는 정확성과 효율성 테스트 각각 점수가 있는 문제입니다.]</p>
<p>세로길이가 <code>n</code> 가로길이가 <code>m</code>인 격자 모양의 땅 속에서 석유가 발견되었습니다. 석유는 여러 덩어리로 나누어 묻혀있습니다. 당신이 시추관을 수직으로 단 하나만 뚫을 수 있을 때, 가장 많은 석유를 뽑을 수 있는 시추관의 위치를 찾으려고 합니다. 시추관은 열 하나를 관통하는 형태여야 하며, 열과 열 사이에 시추관을 뚫을 수 없습니다.</p>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/89d36765-19d0-4b93-9e21-9495ac2597cc/image.png" alt=""></p>
<p>예를 들어 가로가 8, 세로가 5인 격자 모양의 땅 속에 위 그림처럼 석유가 발견되었다고 가정하겠습니다. 상, 하, 좌, 우로 연결된 석유는 하나의 덩어리이며, 석유 덩어리의 크기는 덩어리에 포함된 칸의 수입니다. 그림에서 석유 덩어리의 크기는 왼쪽부터 8, 7, 2입니다.</p>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/b131b12a-3db6-4a70-b90e-3f2742d520c9/image.png" alt=""></p>
<p>시추관은 위 그림처럼 설치한 위치 아래로 끝까지 뻗어나갑니다. 만약 시추관이 석유 덩어리의 일부를 지나면 해당 덩어리에 속한 모든 석유를 뽑을 수 있습니다. 시추관이 뽑을 수 있는 석유량은 시추관이 지나는 석유 덩어리들의 크기를 모두 합한 값입니다. 시추관을 설치한 위치에 따라 뽑을 수 있는 석유량은 다음과 같습니다.</p>
<table>
<thead>
<tr>
<th>시추관의 위치</th>
<th>획득한 덩어리</th>
<th>총 석유량</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>[8]</td>
<td>8</td>
</tr>
<tr>
<td>2</td>
<td>[8]</td>
<td>8</td>
</tr>
<tr>
<td>3</td>
<td>[8]</td>
<td>8</td>
</tr>
<tr>
<td>4</td>
<td>[7]</td>
<td>7</td>
</tr>
<tr>
<td>5</td>
<td>[7]</td>
<td>7</td>
</tr>
<tr>
<td>6</td>
<td>[7]</td>
<td>7</td>
</tr>
<tr>
<td>7</td>
<td>[7, 2]</td>
<td>9</td>
</tr>
<tr>
<td>8</td>
<td>[2]</td>
<td>2</td>
</tr>
<tr>
<td>오른쪽 그림처럼 7번 열에 시추관을 설치하면 크기가 7, 2인 덩어리의 석유를 얻어 뽑을 수 있는 석유량이 9로 가장 많습니다.</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p>석유가 묻힌 땅과 석유 덩어리를 나타내는 2차원 정수 배열 <code>land</code>가 매개변수로 주어집니다. 이때 시추관 하나를 설치해 뽑을 수 있는 가장 많은 석유량을 return 하도록 solution 함수를 완성해 주세요.</p>
<p><strong>제한사항</strong></p>
<ul>
<li>1 ≤ <code>land</code>의 길이 = 땅의 세로길이 = <code>n</code> ≤ 500<ul>
<li>1 ≤ <code>land[i]</code>의 길이 = 땅의 가로길이 = <code>m</code> ≤ 500</li>
<li><code>land[i][j]</code>는 <code>i+1</code>행 <code>j+1</code>열 땅의 정보를 나타냅니다.</li>
<li><code>land[i][j]</code>는 0 또는 1입니다.</li>
<li><code>land[i][j]</code>가 0이면 빈 땅을, 1이면 석유가 있는 땅을 의미합니다.</li>
</ul>
</li>
</ul>
<p>정확성 테스트 케이스 제한사항</p>
<ul>
<li>1 ≤ <code>land</code>의 길이 = 땅의 세로길이 = <code>n</code> ≤ 100<ul>
<li>1 ≤ <code>land[i]</code>의 길이 = 땅의 가로길이 = <code>m</code> ≤ 100</li>
</ul>
</li>
</ul>
<p>효율성 테스트 케이스 제한사항</p>
<ul>
<li>주어진 조건 외 추가 제한사항 없습니다.</li>
</ul>
<h2 id="코드">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int n, m, max_oil;
vector&lt;vector&lt;int&gt;&gt;  _land;
map&lt;int, int&gt; land_size;
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};

int bfs(int x, int y, int k){
    queue&lt;pair&lt;int, int&gt;&gt; q;
    q.push({x, y});
    _land[x][y] = k;
    int sz = 1;

    while(!q.empty()){
        int nowx = q.front().first;
        int nowy = q.front().second;
        q.pop();

        for(int i = 0; i &lt; 4; i++){
            int nx = nowx + dx[i];
            int ny = nowy + dy[i];

            if(nx &lt; 0 || nx &gt;= n || ny &lt; 0 || ny &gt;= m) continue;
            if( _land[nx][ny] != 1) continue;
            q.push({nx, ny});
            ++sz; _land[nx][ny] = k;
        }
    }
    return sz;
}

void bfs_all(){
    int k = 2;
    for(int i = 0; i &lt; n; i++){
        for(int j = 0; j &lt; m; j++){
            if(_land[i][j] == 1) {
                land_size.insert({k, bfs(i, j, k)});
                ++k;
            }
        }
    }
}


int solution(vector&lt;vector&lt;int&gt;&gt; land) {
    _land = land;
    n = land.size(); m = land[0].size();
    bfs_all();

    for(int i = 0; i &lt; m; i++){
        set&lt;int&gt; t;
        for(int j = 0; j &lt; n; j++){
            if(_land[j][i] != 0) t.insert(_land[j][i]);
        }
        int now = 0;
        for(int ti : t) now += land_size[ti];
        max_oil = max(max_oil, now);
    }

    return max_oil;
}</code></pre>
<p>효율성 테스트로 인해 <code>bfs</code>로 석유에 번호를 매기고, 각 석유 덩어리의 크기 map에 저장했다.</p>
<p>각 열 별로 순회하며 해당 열에 속한 석유의 번호를 set(중복 X)에 저장하고, 해당 석유의 크기를 모두 더해 max 값을 찾았다.</p>
<h1 id="리코쳇-로봇">리코쳇 로봇</h1>
<p><strong>문제 설명</strong>
리코쳇 로봇이라는 보드게임이 있습니다.</p>
<p>이 보드게임은 격자모양 게임판 위에서 말을 움직이는 게임으로, 시작 위치에서 목표 위치까지 최소 몇 번만에 도달할 수 있는지 말하는 게임입니다.</p>
<p>이 게임에서 말의 움직임은 상, 하, 좌, 우 4방향 중 하나를 선택해서 게임판 위의 장애물이나 맨 끝에 부딪힐 때까지 미끄러져 이동하는 것을 한 번의 이동으로 칩니다.</p>
<p>다음은 보드게임판을 나타낸 예시입니다.</p>
<pre><code>...D..R
.D.G...
....D.D
D....D.
..D....</code></pre><p>여기서 &quot;.&quot;은 빈 공간을, &quot;R&quot;은 로봇의 처음 위치를, &quot;D&quot;는 장애물의 위치를, &quot;G&quot;는 목표지점을 나타냅니다.
위 예시에서는 &quot;R&quot; 위치에서 아래, 왼쪽, 위, 왼쪽, 아래, 오른쪽, 위 순서로 움직이면 7번 만에 &quot;G&quot; 위치에 멈춰 설 수 있으며, 이것이 최소 움직임 중 하나입니다.</p>
<p>게임판의 상태를 나타내는 문자열 배열 <code>board</code>가 주어졌을 때, 말이 목표위치에 도달하는데 최소 몇 번 이동해야 하는지 return 하는 solution함수를 완성하세요. 만약 목표위치에 도달할 수 없다면 -1을 return 해주세요.</p>
<p><strong>제한 사항</strong></p>
<ul>
<li>3 ≤ <code>board</code>의 길이 ≤ 100<ul>
<li>3 ≤ <code>board</code>의 원소의 길이 ≤ 100</li>
<li><code>board</code>의 원소의 길이는 모두 동일합니다.</li>
<li>문자열은 &quot;.&quot;, &quot;D&quot;, &quot;R&quot;, &quot;G&quot;로만 구성되어 있으며 각각 빈 공간, 장애물, 로봇의 처음 위치, 목표 지점을 나타냅니다.</li>
<li>&quot;R&quot;과 &quot;G&quot;는 한 번씩 등장합니다.</li>
</ul>
</li>
</ul>
<h2 id="코드-1">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

int dx[4] = {0, 1, 0, -1};  // 동 남 서 북
int dy[4] = {1, 0, -1, 0};
int x, y, n, m;
vector&lt;vector&lt;int&gt;&gt; dis;
vector&lt;string&gt; _board;

int move(){
    queue&lt;pair&lt;int, int&gt;&gt; q;
    q.push({x, y});
    dis[x][y] = 0;

    while(!q.empty()){
        x = q.front().first;
        y = q.front().second;
        q.pop();

        if(_board[x][y] == &#39;G&#39;) return dis[x][y];

        for(int i = 0; i &lt; 4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx &lt; 0 || nx &gt;= n || ny &lt; 0 || ny &gt;= m || _board[nx][ny] == &#39;D&#39;) continue;

            while(1){
                if(nx + dx[i] &lt; 0 || nx + dx[i] &gt;= n || ny + dy[i] &lt; 0 || ny +dy[i] &gt;= m || _board[nx + dx[i]][ny + dy[i]] == &#39;D&#39;) {
                    if(dis[nx][ny] != -1) break;
                    dis[nx][ny] = dis[x][y] + 1;
                    q.push({nx, ny});
                    break;
                }
                nx += dx[i];
                ny += dy[i];
            }
        }
    }
    return -1;
}

int solution(vector&lt;string&gt; board) {
    _board = board;
    n = board.size(); m = board[0].size();
    dis = vector&lt;vector&lt;int&gt;&gt;(n, vector&lt;int&gt;(m, -1));
    for(int i = 0; i &lt; n; i++){
        for(int j = 0; j &lt; m; j++){
            if(board[i][j] == &#39;R&#39;) {
                x = i; y = j;
                break;
            }
        }
    }
    return move();
}</code></pre>
<h1 id="당구-연습">당구 연습</h1>
<p><strong>문제 설명</strong>
프로그래머스의 마스코트인 머쓱이는 최근 취미로 당구를 치기 시작했습니다.</p>
<p>머쓱이는 손 대신 날개를 사용해야 해서 당구를 잘 못 칩니다. 하지만 끈기가 강한 머쓱이는 열심히 노력해서 당구를 잘 치려고 당구 학원에 다니고 있습니다.</p>
<p>오늘도 당구 학원에 나온 머쓱이에게 당구 선생님이&quot;원쿠션&quot;(당구에서 공을 쳐서 벽에 맞히는 걸 쿠션이라고 부르고, 벽에 한 번 맞힌 후 공에 맞히면 원쿠션이라고 부릅니다) 연습을 하라면서 당구공의 위치가 담긴 리스트를 건네줬습니다. 리스트에는 머쓱이가 맞춰야 하는 공들의 위치가 담겨있습니다. 머쓱이는 리스트에 담긴 각 위치에 순서대로 공을 놓아가며 &quot;원쿠션&quot; 연습을 하면 됩니다. 이때, 머쓱이는 항상 같은 위치에 공을 놓고 쳐서 리스트에 담긴 위치에 놓인 공을 맞춥니다.</p>
<p>머쓱이와 달리 최근 취미로 알고리즘 문제를 풀기 시작한 당신은, 머쓱이가 친 공이 각각의 목표로한 공에 맞을 때까지 최소 얼마의 거리를 굴러가야 하는지가 궁금해졌습니다.</p>
<p>당구대의 가로 길이 <code>m</code>, 세로 길이 <code>n</code>과 머쓱이가 쳐야 하는 공이 놓인 위치 좌표를 나타내는 두 정수 <code>startX</code>, <code>startY</code>, 그리고 매 회마다 목표로 해야하는 공들의 위치 좌표를 나타내는 정수 쌍들이 들어있는 2차원 정수배열 <code>balls</code>가 주어집니다. &quot;원쿠션&quot; 연습을 위해 머쓱이가 공을 적어도 벽에 한 번은 맞춘 후 목표 공에 맞힌다고 할 때, 각 회마다 머쓱이가 친 공이 굴러간 거리의 최솟값의 제곱을 배열에 담아 return 하도록 solution 함수를 완성해 주세요.</p>
<p>단, 머쓱이가 친 공이 벽에 부딪힐 때 진행 방향은 항상 입사각과 반사각이 동일하며, 만약 꼭짓점에 부딪힐 경우 진입 방향의 반대방향으로 공이 진행됩니다. 공의 크기는 무시하며, 두 공의 좌표가 정확히 일치하는 경우에만 두 공이 서로 맞았다고 판단합니다. 공이 목표 공에 맞기 전에 멈추는 경우는 없으며, 목표 공에 맞으면 바로 멈춘다고 가정합니다.</p>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/d8196d71-6a98-47e9-b653-e94ca5e6715e/image.png" alt=""></p>
<p>위 그림은 친 공이 벽에 맞았을 때의 움직임을 나타낸 그림입니다. 치기 전 공의 위치가 점 A입니다.</p>
<p><img src="https://velog.velcdn.com/images/ooing-0720/post/71fff77b-4409-4145-ae91-51a4dcdf4b2c/image.png" alt=""></p>
<p>위 그림은 친 공이 꼭짓점에 맞았을 때의 움직임을 나타낸 그림입니다. 치기 전 공의 위치가 점 A입니다.</p>
<p><strong>제한사항</strong></p>
<ul>
<li>3 ≤ <code>m</code>, <code>n</code> ≤ 1,000</li>
<li>0 &lt; <code>startX</code> &lt; <code>m</code></li>
<li>0 &lt; <code>startY</code> &lt; <code>n</code></li>
<li>2 ≤ <code>balls</code>의 길이 ≤ 1,000</li>
<li><code>balls</code>의 원소는 [a, b] 형태입니다.<ul>
<li>a, b는 머쓱이가 맞춰야 할 공이 놓인 좌표를 의미합니다.</li>
<li>0 &lt; a &lt; <code>m</code>, 0 &lt; b &lt; <code>n</code></li>
<li>(a, b) = ( <code>startX</code>, <code>startY</code> )인 입력은 들어오지 않습니다.</li>
</ul>
</li>
</ul>
<h2 id="코드-2">코드</h2>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
using namespace std;

vector&lt;int&gt; solution(int m, int n, int startX, int startY, vector&lt;vector&lt;int&gt;&gt; balls) {
    vector&lt;int&gt; answer;
    for(vector&lt;int&gt; v : balls){
        int len = 0;
        if(startX == v[0]) {
            if(m - startX &lt; startX) len = pow(2 * (m - startX), 2) + pow(startY - v[1], 2);
            else len = pow(2 * startX, 2) + pow(startY - v[1], 2);
            if(startY &lt; v[1]) len = min(len, (int)(pow(startY + v[1], 2)));
            else len = min(len, (int)pow(2 * n - startY - v[1], 2));
        }
        else if(startY  == v[1]) {
            if(n - startY &lt; startY) len = pow(startX - v[0], 2) + pow(2 * (n - startY), 2);
            else len = pow(startX - v[0], 2) + pow(2 * startY, 2);
            if(startX &lt; v[0]) len = min(len, (int)(pow(startX + v[0], 2)));
            else len = min(len, (int)pow(2 * m - startX - v[0], 2));
        }
        else{
            len = min({pow(2 * m - startX - v[0], 2) + pow(startY - v[1], 2), pow(-startX - v[0], 2) + pow(startY - v[1], 2), pow(startX - v[0], 2) + pow(2 * n - startY - v[1], 2), pow(startX - v[0], 2) + pow(-startY - v[1], 2)});
        }
        answer.emplace_back(len);
    }

    return answer;
}</code></pre>
<p>입사각과 반사각이 같은 최단 거리를 구하는 방법은 시작점을 x = 0, x = n, y = 0, y = m으로 대칭이동한 점과의 거리 중 가장 짧은 거리를 구하면 된다.</p>
<p>그런데! x 좌표나 y 좌표가 같은 경우 목표 좌표 방향으로는 이동할 수 없고(한 번 튕겨야하므로), 반대 방향으로 튕기는 것도 고려해야한다.(이거 안하면 31번 이후 테스트케이스가 터진다)</p>
]]></description>
        </item>
    </channel>
</rss>