<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>_hennessy_.log</title>
        <link>https://velog.io/</link>
        <description>응애 초보 개발자</description>
        <lastBuildDate>Wed, 09 Aug 2023 16:35:55 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>_hennessy_.log</title>
            <url>https://velog.velcdn.com/images/_hennessy_/profile/b41bb09b-99ab-4361-b6bf-e2f744498055/image.gif</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. _hennessy_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/_hennessy_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[고민스러운 날들]]></title>
            <link>https://velog.io/@_hennessy_/%EA%B3%A0%EB%AF%BC%EC%8A%A4%EB%9F%AC%EC%9A%B4-%EB%82%A0%EB%93%A4</link>
            <guid>https://velog.io/@_hennessy_/%EA%B3%A0%EB%AF%BC%EC%8A%A4%EB%9F%AC%EC%9A%B4-%EB%82%A0%EB%93%A4</guid>
            <pubDate>Wed, 09 Aug 2023 16:35:55 GMT</pubDate>
            <description><![CDATA[<h3 id="순진했던-나의">순진했던 나의</h3>
<p>부트캠프를 끝낸지 언 3개월이란 시간이 흘렀다. 유료로 진행되는 곳에서 했던만큼 어쩌면 취업과 관련한
과도한 환상을 꿈꾸고 있었던 것 같다.</p>
<p><em>&#39;사실 알고 있었잖아?&#39;</em></p>
<p>뭐든 쉬운 일은 없는 것, 알고 있다. 그러나 소극적인 취업 지원 정책이 실망스러운 것도 어쩔 수가 없었다.
수료 후 두달 간은 포트폴리오와 이력서를 만지며, 내가 했던 프로젝트를 다시 보면서 지냈다.
그 두달을 꽉 채워 열심히 살았다고는 장담하지 못하지만, 그간의 노력에 약간의 운이라도 따라주진 않을까 기대했던 듯.
여러곳 이력서를 내고 구인 공고를 보고 수없이 떨어지면서 <em><del>이건 경제논리로도 말이 안된다는걸 알았다.</del></em></p>
<p><strong><em>수요와 공급이 애당초 맞질 않는다.</em></strong></p>
<p>내 스스로를 객관화해보면 커리어에 근본이 없다. 돌이켜보면 인생을 너무 &#39;어쩌다보니?&#39; 방식으로 살았던 것 아닌가?
그리고 나같은 사람은 분명히 이런 부트캠프에 많다. <del>이제라도 제대로 해보자.</del> 하며 뛰어든 사람들 말이다.
마침 요즘 코딩 광고도 많이 하고 나라에서 지원도 많이 하겠다, 배움에 있어 접근성도 엄청 좋다.
돈이 있으면 유료 코스, 없으면 국비. 뭐든 선택해서 배우기만 하면 취업된다고 그렇게 광고를 하는데
<em>&#39;어중띵한 커리어패스.. 이걸로 한번 제대로 해봐?&#39;</em> 하는 사람들이 얼마나 많겠나.
근데 그만큼 사람을 구하지 않는다.</p>
<p>당장에 적은 돈이라도 벌어야 하는 사람도 있다.
그리고 그런 사람들 중 몸값을 후려쳐서라도 취업을 하는 사람들이 있다. <strong><del><em>그렇게 생태계교란종이 된다.</em></del></strong></p>
<h3 id="베스">베스</h3>
<p>전공자와의 차이가 있으니 테이블이 당연히 다를 수도 있다. 그래 맞아. 난 현업은 보지 못했으니까.
그렇지만 내 생각은 그러하다. 괜히 생태계교란종이라 했겠는가?
이건 단순히 내가 많은 돈을 받겠다는 것이 아니라, 분야 자체의 테이블마저도 영향을 끼칠 수 있다고 생각하기 때문이다.
<del>전공자도 피해갈 수 없는 평가절하</del>
그리고 그 테이블이 의미하는 것은 내가 가진 기술의 가치이기도 하다.</p>
<p><em><strong>난 조금 벌어도 야근하고 다 할 수 있어요!</strong></em></p>
<p>이래놓고 인스타그램에 일하기 힘들다고 글쓸거면 돈 많이 받고 고생하자.</p>
<h3 id="관철중">관철중</h3>
<p>나도 베스가 되어버릴까 고민도 했다. 
당장 돈을 벌어야 했던 거. 그거 나였으니까.
그런데 이력서를 넣지도 않은 회사에서 입사제안이 왔다.
&#39;어! 이거 뭐야!&#39;
이것도 잠시다. 처참한 기업평가를 보고 고민하고 진짜 이건 아니었다.
내가 원하는, 스페셜리스트로서의 나의 모습은 물론 발전도 도모할 수 없을 것 같았다.
기업평가에 작성돼있던 <strong>&quot;뗄감&quot;</strong>이라는 그 단어 하나에.
활활 타다가 재가 되어 흩날려질 그런 존재로. 난 회사에 존재하고 싶지 않았다.</p>
<p>게다가 이 입사제안을 보고 뭔가 무의식적으로
&#39;나를 왜..?&#39;
라는 생각이 들었는데, 둘중에 하나 같다.
<strong>하도 떨어져서 자신감이 바닥을 쳤거나, 진짜 내 역량에 대해 자신이 없었거나.</strong></p>
<p>어쨌든 난 이 입사제안이 이제와서는 기회로도 느껴진다. 뭔가 각성이랄까.
&#39;이대로는 안된다.&#39;
그 생각이 머릿속에 가득했다.
내가 각종 서류전형에서 전부 탈락한 이유는 별거 없다.
내 능력이 부족해서, 내가 여태까지 한 것은 그저 학원에서 찍어낸 공장형 성과다.
&#39;이대로 잘 따라가면 되겠지&#39; 하는 안일한 생각, 
<strong>내 미래가 불안해서 400이라는 돈으로
그냥 나는 6개월동안 마음편해지려고 했던 것 아니냐고.</strong></p>
<p><strong>마음먹었고 난 곧죽어도 베스는 되지 않을 것이다.</strong>
요즘은 더해서 타언어 위주로 다른 기술들을 익히고 있다.
내가 당장 할 수 있는 것들을 찾아서 하고 있다.
주도적으로, 난 늘 그런 방식이 잘 됐다.</p>
<p>인터넷에는 여러 성공적인 일화가 넘쳐나서 어떻게 보면 이 글은 낙오된 자의 징징댐으로 보일 수 있겠으나,
난 아직 성공과 실패의 기로까지 오지도 못했다. <em><strong>그저 정진과 선택의 기로에 놓였을 뿐이지.</strong></em></p>
<p>고민스러운 날들은 계속 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[컴퓨터 언어 체제(1)]]></title>
            <link>https://velog.io/@_hennessy_/%EC%BB%B4%ED%93%A8%ED%84%B0%EC%96%B8%EC%96%B4%EC%B2%B4%EC%A0%9C</link>
            <guid>https://velog.io/@_hennessy_/%EC%BB%B4%ED%93%A8%ED%84%B0%EC%96%B8%EC%96%B4%EC%B2%B4%EC%A0%9C</guid>
            <pubDate>Sun, 19 Mar 2023 00:03:17 GMT</pubDate>
            <description><![CDATA[<h2 id="1-언어">1. 언어</h2>
<blockquote>
<ul>
<li><strong>Context</strong> : 프로그래밍 언어를 공부하다보면 <strong>&quot;Context(문맥)&quot;</strong> 라는 단어를 종종 마주치게 된다.
왜냐하면, 프로그래밍 언어도 우리가 일상적으로 사용하는 언어와 마찬가지로 문맥이 결과에 영향을 끼치기 때문이다.
예를 들어 &quot;눈&quot; 이라는 단어에는 두가지 의미가 있다. 신체 중 얼굴의 일부분을 뜻하는 &quot;눈&quot; 과 기상현상에 의해 하늘에서 내리는 무언가를 의미하는 &quot;눈&quot;. 만약 문맥을 파악하지 못한다면, 어떠한 문장에서 &quot;눈&quot; 이 의미하는 것이 무엇인지 알기 힘들어진다. 이를통해 문맥이 내장한 의미를 식별하는 데에 얼마나 중요한지를 알 수 있다.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li><strong>문자</strong> : &quot;집&quot; 이라는 단어를 분해하면 &#39;ㅈ&#39;, &#39;ㅣ&#39;, &#39;ㅂ&#39; 으로 나눌 수 있다. 세개의 기호를 조합하여 하자의 문자를 만드는 것이다. 하지만 이를 조합하는 데에는 순서 또한 중요하다. <strong>집이 빚으로 조합될 수도 있다!</strong> 때문에 문자는 그 조합과 순서 또한 중요하다. 지금 쓰는 한글의 구성요소가 <strong>(기호, 상자에 들어갈 기호, 상자의 순서)</strong> 이렇게 볼 수 있다면, 프로그래밍 언어 또한 똑같은 구성요소를 갖는다고 볼 수 있다.</li>
</ul>
</blockquote>
<h2 id="2-컴퓨터의-문자-bit">2. 컴퓨터의 문자 &quot;bit&quot;</h2>
<p><strong>Binary(2진법) + Digit(숫자) = Bit</strong></p>
<blockquote>
<ul>
<li>비트는 2진법을 사용한다. 비트 문자 상자에는 모스부호처럼 점(.)과 선(-) 처럼 두가지 기호 중에 하나만 담을 수 있다. 여기서 또한 조합과 순서가 중요하다. <strong>A는 &#39;-.&#39;이지만 &#39;.-&#39;은 N이 된다.</strong> 문맥도 중요한 것이, 기호는 추상적이기 때문에 그 문자 상자에 들어갈 수 있는 기호가 0/1 일 수도 있고, 쌀/보리 일 수도 있다. 문맥이 없다면 언어가 제대로 작동할 수 없다. 누구는 001 이라고 하지만 누구는 쌀쌀보리 라고 할 수도 있기 떄문이다.</li>
</ul>
</blockquote>
<h2 id="3-논리연산">3. 논리연산</h2>
<pre><code>public class Main {
    public static void main(String[] args) {
        boolean judge = true;
        int num1 = 1;
        int num2 = 1;

        if (num1 + num2 == 2){
            judge = true;
            int sum = num1 + num2;
            logic(sum);
        } else {
            judge = false;
        }
    }
    public static int logic(int sum){
        int answer = 0;
        answer = sum / 2;

        return answer;
    }
}</code></pre><blockquote>
<ul>
<li>프로그래밍 언어를 공부한다면 참과 거짓에 익숙하다. &quot;예&quot; 또는 &quot;아니오&quot; 로 대답할 수 있는 문장을 좀 더 확장시켜서 보자.</li>
</ul>
</blockquote>
<ul>
<li>위의 코드에는 if문을 사용하여, &quot;만약 num1 + num2가 2가 참이면 <strong>(확장)두 값의 합에 logic 메서드를 실행하라</strong>&quot; 라고 표현하는 것이다. 여기서 다른 비트들이 표현했던 내용으로 다른 비트를 만들어 내는 동작(logic)을 <strong>논리연산(logic operation)</strong> 이라고 한다.</li>
</ul>
<h2 id="4-george-boole이-만들어낸-boolean-algebra불리언-대수">4. George Boole이 만들어낸 Boolean algebra(불리언 대수)</h2>
<p><strong>결합법칙, 교환법칙, 분배법칙이 적용가능한 비트에 대해 사용할 수 있는 연산 규칙 집합</strong></p>
<blockquote>
<ul>
<li>기본 불리언 연산자:  <strong>NOT, AND, OR</strong>
합성연산자: <strong>XOR</strong></li>
</ul>
</blockquote>
<blockquote>
<ol>
<li><strong>NOT</strong>: 논리적 반대를 의미한다. 거짓에 NOT을 더하면 참이 되고 참에 NOT을 더하면 거짓이 된다.</li>
<li><strong>AND</strong>: 둘 이상의 비트에 작용하며 2비트 연산인 경우 모든 비트가 참인 경우만 참이 된다.</li>
<li><strong>OR</strong>: 둘 이상의 비트에 작용하며 첫번째 비트와 두번째 비트가 다른 값인 경우, 첫번째와 두번째가 둘다 참인 경우에 참이 된다. 더 많은 비트에 연산을 하는 경우 한 비트라도 참이면 결과도 참이다.</li>
<li><strong>XOR</strong>(exclusive or): OR는 둘 다 참인 경우에도 참이 되었지만 XOR은 둘 다 참이면 거짓이 된다.</li>
<li>불리언 진리표<img src="https://velog.velcdn.com/images/_hennessy_/post/3a96a5c2-a2c5-42b9-b305-c62307802903/image.jpg" alt=""></li>
</ol>
</blockquote>
<h2 id="5-de-morgans-law-드모르간-법칙">5. De Morgan&#39;s law 드모르간 법칙</h2>
<p><strong>불리언 대수에 적용할 수 있는 법칙: a AND b == NOT(NOT a OR NOT b)</strong></p>
<blockquote>
<ul>
<li><strong>드모르간의 법칙 진리표</strong><img src="https://velog.velcdn.com/images/_hennessy_/post/4be7c0be-6e7a-496f-a326-902ec180393d/image.png" alt=""></li>
</ul>
</blockquote>
<ul>
<li>드모르간의 법칙의 진리표를 보면 &quot;NOT 을 충분히 사용하면 AND 연산을 OR 연산으로 대신할 수 있다&quot; 는 것을 알 수 있다. 반대로 OR을 AND로 대신할 수도 있다.</li>
<li>입력이 &#39;쌀쌀하다&#39; 와 &#39;비가 온다&#39; 라는 형식일 수 있지만, &#39;NOT 쌀쌀하다&#39; 와 &#39;NOT 비가 온다&#39; 라는 형식이 될 수도 있다. 위의 예시에서 긍정적인 논리를 <strong>정논리</strong> , 부정적인 논리를 <strong>부논리</strong> 라고 짧게 부르기도 한다. </li>
<li><img src="https://velog.velcdn.com/images/_hennessy_/post/3b48684a-07f5-4363-a23f-e772a4a43896/image.png" alt=""></li>
<li>드모르간의 법칙은 부정적인 논리를 구현할 떄에 &#39;NOT NOT 춥다 OR NOT NOT 쌀쌀하다&#39; 로 OR를 사용해야 했을테지만, 연산을 최소로 사용하면 비용을 절약할 수 있다. NOT 연산은 실제 수행에 하드웨어에 비용이 들기 떄문이다. 연산은 연쇄적으로 사용하면 계산이 느려지는데 드모르간의 법칙은 <strong>연산비용을 최소화한다는 장점이 있다.</strong></li>
</ul>
<p><strong>참고서적</strong>
&quot;한권으로 읽는 컴퓨터 구조와 프로그래밍&quot;, 조너선 스타인하트</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[디자인패턴(2)_팩토리패턴]]></title>
            <link>https://velog.io/@_hennessy_/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B42%ED%8C%A9%ED%86%A0%EB%A6%AC%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@_hennessy_/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B42%ED%8C%A9%ED%86%A0%EB%A6%AC%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Tue, 07 Feb 2023 04:00:27 GMT</pubDate>
            <description><![CDATA[<h3 id="1-정의">1. 정의</h3>
<blockquote>
<ul>
<li>객체를 사용하는 코드에서 객체의 생성 부분을 뗴어놓고 추상화한 패턴</li>
</ul>
</blockquote>
<ul>
<li>상속관계의 두 클래스에서 상위 클래스가 큰 뼈대를 구성하고 </li>
<li>하위 클래스는 객체 생성에 관한 내용을 결정하는 패턴</li>
</ul>
<h3 id="2-특징">2. 특징</h3>
<blockquote>
<ol>
<li>상위 클래스와 하위 클래스의 분리로 느슨한 결합</li>
<li>하위 클래스만이 인스턴스 생성을 담당하고 있기에 상위 클래스는 인스턴트 생성 방식에 알 필요가 없어서 유연성 증가</li>
<li>객체를 생성하는 로직이 따로 있기 때문에 리팩터링시 한 곳만 고치면 돼 유지보수성의 증가</li>
</ol>
</blockquote>
<p>팩토리 패턴은 말 그래도 공장처럼 찍어낸다는 의미이다.
피자의 레시피, 파스타의 레시피가 하위 클래스에서 정의되고 있고,
상위 클래스에선 그 레시피에 따라 생산을 하는 기능을 한다고 볼 수 있다.
이를 그림으로 표현하면 아래와 같다</p>
<p><img src="https://velog.velcdn.com/images/_hennessy_/post/d0e5b186-37e0-40be-bdf2-65e554712246/image.jpg" alt=""></p>
<h3 id="3-자바에서의-코드">3. 자바에서의 코드</h3>
<pre><code>package FactoryPattern;

import static FactoryPattern.List.PASTA;
import static FactoryPattern.List.PIZZA;

abstract class Menu {
    public abstract int getPrice();

    @Override
    public String toString() {
        return &quot;This menu is &quot; + this.getPrice();
    }
}

class MenuFactory {
    public static Menu getCoffee(String type, int price) {
        if (PASTA.toString().equalsIgnoreCase(type)) return new Pasta(price);
        else if (PIZZA.toString().equalsIgnoreCase(type)) {
            return new Pizza(price);
        } else {
            return new DefaultMenu();
        }
    }
}

class DefaultMenu extends Menu {
    private int price;

    public DefaultMenu() {
        this.price = -1;
    }

    @Override
    public int getPrice() {
        return this.price;
    }
}

class Pasta extends Menu {
    private int price;

    public Pasta(int price) {
        this.price = price;
    }

    @Override
    public int getPrice() {
        return this.price;
    }
}

class Pizza extends Menu {
    private int price;

    public Pizza(int price) {
        this.price = price;
    }

    @Override
    public int getPrice() {
        return this.price;
    }
}

public class HelloWorld {
    public static void main(String[] args) {
        Menu pasta = MenuFactory.getCoffee(&quot;Pasta&quot;, 11000);
        Menu pizza = MenuFactory.getCoffee(&quot;Pizza&quot;, 20000);
        System.out.println(&quot;Factory Pasta:: &quot; + pasta);
        System.out.println(&quot;Factory Pizza:: &quot; + pizza);
    }
}
//출력
//Factory Pasta:: This menu is 11000
//Factory Pizza:: This menu is 20000</code></pre><h3 id="4-정리">4. 정리</h3>
<blockquote>
<p> 위의 코드에서 볼 수 있는 것과 같이 모든 팩토리패턴에서는 <strong>객체 생성을 &quot;캡슐화&quot;한다.</strong>
이러한 팩토리 패턴은 주로 제품 생산군에서 많이 사용되는 디자인 패턴이다.
중요한 것은 <strong>의존성 뒤집기 원칙</strong>이다.
간단히 말해 <strong>&quot;추상화된 것에 의존하도록 만들어라. 구상 클래스에 의존하도록 만들지 않도록 한다.&quot;</strong>는 것이다.
구상 클래스는 캡슐화된 객체 생성 로직을 말한다. 위의 코드는 이러한 의존성 뒤집기 원칙을 자세히 다룰 수 없기에 
이에 대하여 추후 블로그에 작성해보도록 하겠다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터베이스(1)_엔터티와 릴레이션]]></title>
            <link>https://velog.io/@_hennessy_/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A41%EC%97%94%ED%84%B0%ED%8B%B0%EC%99%80-%EB%A6%B4%EB%A0%88%EC%9D%B4%EC%85%98</link>
            <guid>https://velog.io/@_hennessy_/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A41%EC%97%94%ED%84%B0%ED%8B%B0%EC%99%80-%EB%A6%B4%EB%A0%88%EC%9D%B4%EC%85%98</guid>
            <pubDate>Fri, 23 Dec 2022 08:27:00 GMT</pubDate>
            <description><![CDATA[<h2 id="1-데이터베이스db">1. 데이터베이스(DB)</h2>
<blockquote>
<ul>
<li>규칙과 규약을 통해 구조화되어 저장되는 데이터의 모음</li>
</ul>
</blockquote>
<ul>
<li><p><strong>DBMS</strong>: 데이터 통합 시스템(DataBase Management System)
ex)MariaDB, MySQL  etc.</p>
</li>
<li><p><strong>쿼리언어(query language)</strong>를 통해 삽입, 삭제, 수정, 조회 등 수행</p>
<h2 id="2-데이터베이스와-dbms">2. 데이터베이스와 DBMS</h2>
<blockquote>
<p><img src="https://velog.velcdn.com/images/_hennessy_/post/20b8d0c0-3fdf-491f-a686-88c5facff693/image.jpg" alt="">
데이터베이스 위에는 DBMS가 있으며 그 위에 응용프램이 있다.
응용프로그램은 해당 데이터베이스 안에 있는 데이터를 DBMS를 이용하여 꺼내고,
이를 이용하여 로직을 구축한다.</p>
</blockquote>
</li>
</ul>
<h2 id="3-엔터티entity">3. 엔터티(Entity)</h2>
<p>: 여러개의 속성을 지닌 <strong>명사</strong></p>
<blockquote>
<h3 id="ex-자동차entity의-속성들">ex) 자동차(entity)의 속성들</h3>
</blockquote>
<ul>
<li>이름</li>
<li>연식</li>
<li>엔진형태 etc.
<img src="https://velog.velcdn.com/images/_hennessy_/post/35a47f80-b854-4d42-be3c-43459f700a6f/image.jpg" alt=""></li>
<li><em>많은 속성이 들어갈 수 있지만 서비스의 요구 사항에 따라 무관한 속성시 속성을 제거하기도 한다.*</em></li>
</ul>
<h2 id="32-약한-엔터티와-강한-엔터티">3.2. 약한 엔터티와 강한 엔터티</h2>
<blockquote>
<p><strong>개미는 무리를 지어 생활한다.
토미는 쾌활하고 부지런하다는 속성을 갖고 있는 개미이다.
하지만 함께 사는 무리가 없으면 개미굴을 팔 수도, 사냥을 할 수도 없다.
토미는 속성을 갖고 있음에도 무리가 없으면 생존하기 어렵다.
이 때에 토미는 약한 엔터티가 된다.
반면에 토미를 종속시키는 이 무리는 강한 엔터티라고 할 수 있다.</strong></p>
</blockquote>
<p>위의 예시처럼 A가 혼자서는 존재하지 못하고 B의 존재여부에 따라 종속적이라면 <strong>A는 약한 엔터티가 되고 B는 강한 엔터티가 된다.</strong></p>
<h2 id="4-릴레이션relation">4. 릴레이션(Relation)</h2>
<p>: 정보를 구분하여 저장하는 기본 단위이며, 엔터티 관련 데이터를 릴레이션 하나에 담아 관리한다.
<img src="https://velog.velcdn.com/images/_hennessy_/post/08f28b3b-da48-4417-b0bc-51e1bbf1e13f/image.jpg" alt=""></p>
<p>이처럼 자동차(엔터티)의 속성을 저장할 수 있게끔 속성내용들을 정리한 것을 릴레이션이라고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[운영체제(1)_역할과 구조]]></title>
            <link>https://velog.io/@_hennessy_/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C1%EC%97%AD%ED%95%A0%EA%B3%BC-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@_hennessy_/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C1%EC%97%AD%ED%95%A0%EA%B3%BC-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Thu, 22 Dec 2022 14:14:11 GMT</pubDate>
            <description><![CDATA[<h2 id="1-운영체제의-역할">1. 운영체제의 역할</h2>
<blockquote>
</blockquote>
<ul>
<li><strong>메모리 관리</strong>: 한정된 메모리를 어떤 프로세스에 얼만큼 할당해야 하는지 관리</li>
<li><strong>CPU 스케쥴링과 프로세스 관리</strong>: CPU소유권을 어느 프로세스에 할당할지, 프로세스 생성, 삭제, 자원 할당 및 반환 관리</li>
<li><strong>디스크 파일 관리</strong>: 디스크 파일을 어떤 방법으로 보관할지 관리</li>
<li><strong>I/O 디바이스 관리</strong>: I/O디바이스 간에 데이터를 주고받는 것을 관리</li>
</ul>
<h2 id="2-운영체제의-구조">2. 운영체제의 구조</h2>
<p><img src="https://velog.velcdn.com/images/_hennessy_/post/290b4152-d358-4238-a027-9c5bc29db977/image.jpg" alt=""></p>
<p>운영체제의 구조는 이러한 형태로 볼 수 있다.
이 구성요소들에 대해서 알아보자.</p>
<blockquote>
<h3 id="1-gui와-cui">1. GUI와 CUI</h3>
</blockquote>
<ul>
<li><strong>GUI</strong>: 사용자가 전자장치와 상호작용할 수 있도록 하는 사용자 인터페이스 형태 
ex) 아이콘을 마우스로 클릭하는 동작으로 컴퓨터와 상호작용할 수 있게 도와줌.</li>
<li><strong>CUI</strong>: GUI와 달리 그래픽으로 컴퓨터와 상호작용하는 것이 아닌 명령어로 처리하는 인터페이스
ex) 리눅스 서버 (CUI만 존재)</li>
</ul>
<blockquote>
<h3 id="2-시스템-콜">2. 시스템 콜</h3>
</blockquote>
<ul>
<li>운영체제가 커널에 접근하기 위한 인터페이스: 유저 프로그램이 운영체제의 서비스를 받기 위해 커널함수를 호출할 떄 사용</li>
<li>I/O요청으로 트랩(Trap)*이 발동하면 올바른 요청인지 확인 후 시스템 콜을 통해 커널 모드로 변환되어 함수 실행
<img src="https://velog.velcdn.com/images/_hennessy_/post/943506cf-b7bb-461a-a3b8-06850bbe9de8/image.jpg" alt=""></li>
</ul>
<p>위의 시스템콜 그림에 나와 있는 것처럼, 유저모드와 커널모드를 구분하여 얻는 이점에 대해 아래의 사례를 보자.</p>
<blockquote>
<p>이제 갓 두살이 된 아이가 있다.
맨날 주방에서 뚝딱거리며 맛있는 음식을 만들어 내는 엄마의 모습을 보고
이 아이도 맛있는 요리를 스스로 만들어 먹고 싶어한다.
하지만 두살인 아이에게 칼질을 하는 일이나, 불을 쓰는 일은 매우 위험한 일이다.
하지만 요리를 하기 위해선 필수적인 일이다. 그래서 칼질을 해야하거나 불을 쓸 필요가 있을 때에는
엄마를 부른다.</p>
</blockquote>
<p><strong>여기서 유저프로그램(요리)는 
&quot;칼질&quot;이라는 요청을 했다.
하지만 함부로 하면 안되는 행동이기 때문에 
유저모드(아이)에서 커널모드(엄마)로 모드를 변환하여
&quot;칼질&quot;이라는 파일시스템을 거쳐 
다시 유저모드(아이)에게 역할을 넘기는 것이다.</strong></p>
<p>아주 단적인 예로 볼 수 있지만 이밖에도, 다른 사람이 함부로 나의 물건을 사용할 수 없도록 사물함을 자물쇠로 잠구는 일처럼
모드의 변경은 악용을 방지하는 역할도 있다.</p>
<h3 id="21-modebit-유저모드와-커널모드를-구분하는-flag함수ex-boolean">2.1. modebit: 유저모드와 커널모드를 구분하는 flag함수(ex: boolean)</h3>
<blockquote>
<p>이러한 유저모드와 커널모드를 구분지어 주는 것이 <strong>&quot;modebit&quot;</strong>이다.
0 또는 1로 구성되어 무언가를 기억하거나, 다른 프로그램에 신호를 남기기 위한 용도로서,
쉬운 예시로 boolean을 생각해 낼 수 있다.
Trap이 발동하고 I/O요청에 이상이 없을 때에, boolean 변수를 true로 전환하여 커널모드로 진입하는 것으로 생각하면 된다.
<img src="https://velog.velcdn.com/images/_hennessy_/post/2eb59ece-684e-4647-ae90-dbd272e446c2/image.jpg" alt=""></p>
</blockquote>
<h2 id="3-커널">3. 커널</h2>
<blockquote>
<ul>
<li>운영체제의 핵심</li>
</ul>
</blockquote>
<ul>
<li>시스템콜 인터페이스 제공</li>
<li>보안, 메모리, 프로세스, 파일시스템, I/O 디바이스, I/O요청 관리 등</li>
<li>운영체제의 중추 역할</li>
</ul>
<h2 id="4-드라이버">4. 드라이버</h2>
<blockquote>
<ul>
<li>하드웨어를 제어하기 위한 소프트웨어</li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[디자인 패턴(1)_싱글톤 패턴]]></title>
            <link>https://velog.io/@_hennessy_/%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@_hennessy_/%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Wed, 21 Dec 2022 06:19:48 GMT</pubDate>
            <description><![CDATA[<h3 id="1-정의">1. 정의</h3>
<blockquote>
<p>싱글톤 패턴*(Singleton pattern)
&quot;하나의 클래스, 오직 하나의 인스턴스&quot;</p>
</blockquote>
<p>우리는 하나의 클래스에 여러 개의 인스턴스를 생성할 수 있다.
하지만 싱글톤 패턴은 하나의 클래스에 오직 하나의 인스턴스만을 만들어 로직을 만든다.
이러한 싱글톤 패턴은 주로 데이터베이스 연결에 많이 사용된다.
하나의 인스턴스를 기반으로 객채를 생성하기 때문에 인스턴스 생성 비용을 아낄 수 있다는 장점이 있다.</p>
<h3 id="2-특징">2. 특징</h3>
<blockquote>
<ul>
<li><strong>Test Driven Development(TDD)시에 걸림돌이 된다.</strong>
테스트를 할 때에는 각각의 테스트가 독립적이어야 하나, 싱글톤 패턴의 경우 하나의 인스턴스 만을 기반으로 만들어진
패턴이기 떄문에 <del>테스트마다 독립적인 인스턴스를 만들기가 어렵다.</del></li>
</ul>
</blockquote>
<ul>
<li><strong>의존성 주입</strong>
모듈간의 결합을 강하게 만든다는 단점이 있기 때문에 이때 <del>의존성 주입</del>을 통해 이 결합을 느슨하게 만들 수 있다.</li>
</ul>
<h3 id="3-의존성-주입">3. 의존성 주입</h3>
<p><img src="https://velog.velcdn.com/images/_hennessy_/post/e3cde0d9-1a9f-4d2a-a740-00914ee55e7c/image.jpg" alt=""></p>
<p>위 그림과 같이 메인모듈이 직접적으로 하위 모듈에 의존하기 보다는 의존성 주입자를 삽입하여 메인모듈이 간접적으로 의존성을 주입하는 방법이다. 이로서 메인모듈은 하위 모듈에 대한 의존성이 떨어지게 된다.
이를 <strong>&quot;디커플링&quot;</strong>이라고 한다.</p>
<blockquote>
<h3 id="의존성-주입의-장점">의존성 주입의 장점</h3>
</blockquote>
<ul>
<li>모듈을 쉽게 교체할 수 있는 구조로 테스팅이 용이함.</li>
<li>마이그레이션*이 수월해짐</li>
<li>구현시 추상화 레이어를 넣고 이를 기반으로 구현체를 넣기 때문에 애플리케이션의 의존성 방향이 일관됨.</li>
<li>애플리케이션을 쉽게 추론 가능</li>
<li>모듈 간의 관계 명확해짐<h3 id="의존성-주입의-단점">의존성 주입의 단점</h3>
</li>
<li>모듈들의 분리로 클래스 수가 증가 -&gt; 복잡성 증가(런타임 패널티 발생)<h3 id="의존성-주입-원칙">의존성 주입 원칙</h3>
</li>
<li><strong>&quot;상위 모듈은 하위 모듈에서 어떠한 것도 가져오지 않아야 한다. 또한 둘다(상위, 하위) 추상화에 의존해야 하며, 이 때 추상화는 세부 사항에 의존해선 안된다.&quot;</strong></li>
</ul>
<h3 id="4-싱글톤-패턴의-구현java">4. 싱글톤 패턴의 구현(JAVA)</h3>
<pre><code>class Singleton {
    private static class singleInstanceHolder{
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance(){
        return singleInstanceHolder.INSTANCE;
    }
}

public class HelloWorld{
    public static void main(String[] args) {
        Singleton a = Singleton.getInstance();
        Singleton b = Singleton.getInstance();
        System.out.println(a.hashCode());
        System.out.println(b.hashCode());

        if (a == b){
            System.out.println(true);
        }
    }
}

/*
1392838282
1392838282
true
*/</code></pre><p>*<em>결과값을 보면 결국 Singleton a와 b가 같은 해쉬코드</em>를 갖고 있음을 알 수 있다.
두개의 인스턴스가 아닌 &quot;하나&quot;의 인스턴스를 가리킨다.
**</p>
<p><del>....................................................................................................................................................................................................................................................................................................................................................................................................</del></p>
<p><em><strong>디자인패턴</strong>: 프로그램 설계 시에 발생했던 문제점들을 객체 간의 상호 관계를 이용, 해결할 수록 하나의 &quot;약속&quot; 형태로 만들어 놓은 것</em>
<em><strong>마이그레이션</strong>: 데이터를 한 위치에서 다른 위치로, 한 형식에서 다른 형식으로 또는 한 애플리케이션에서 다른 애플리케이션으로 이동하는 프로세스</em>
<em><strong>해쉬코드</strong>: 객체의 번지수</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[너비우선탐색 BFS]]></title>
            <link>https://velog.io/@_hennessy_/%EB%84%88%EB%B9%84%EC%9A%B0%EC%84%A0%ED%83%90%EC%83%89-BFS</link>
            <guid>https://velog.io/@_hennessy_/%EB%84%88%EB%B9%84%EC%9A%B0%EC%84%A0%ED%83%90%EC%83%89-BFS</guid>
            <pubDate>Wed, 14 Dec 2022 03:06:16 GMT</pubDate>
            <description><![CDATA[<h2 id="너비우선탐색에-대하여-알아보자">너비우선탐색에 대하여 알아보자!</h2>
<h3 id="bfs-breadth-first-search">BFS (Breadth First Search)</h3>
<blockquote>
<p>Ex) 지구상에 존재하는 모든 친구 관계를 그래프로 표현한 후 Ash와 Vanessa 사이에 존재하는 경로를 찾는 경우</p>
</blockquote>
<ul>
<li><p>DFS: 모든 친구 관계를 다 살펴봐야 할지도 모른다.</p>
</li>
<li><p>BFS: Ash와 가까운 관계부터 탐색</p>
</li>
<li><p>DFS: 정점부터 한 분기를 깊게 파고 들어 그 분기를 다 탐색한 후 다음 분기를 탐색한다.</p>
</li>
<li><p>BFS: 정점과 인접한 노드를 기준으로 탐색한다.</p>
</li>
</ul>
<h3 id="bfs의-특징">BFS의 특징</h3>
<ol>
<li>재귀적으로 동작하지 않는다.</li>
<li>Queue를 이용하기 때문에 First In First Out의 원리를 이용한다.</li>
<li>반드시 방문여부를 확인 해주는 검사 장치가 있어야 한다! (자칫하면 무한루프에 빠질 수 있다.)</li>
</ol>
<p><img src="https://velog.velcdn.com/images/_hennessy_/post/73dc03fa-21ca-460c-af8e-72f568389182/image.jpg" alt=""></p>
<h3 id="탐색원리">탐색원리</h3>
<ul>
<li>우선 정점의 노드를 Queue에 넣고,</li>
<li>이것을 poll() 해주면서</li>
<li>이 정점 노드와 연결된 노드들을 Queue에 삽입,</li>
<li>그렇다면 위 트리의 탐색 순서는
1 -&gt; 2 -&gt; 3 -&gt; 4-&gt; 5-&gt; 6-&gt; 7
<img src="https://velog.velcdn.com/images/_hennessy_/post/e3e61a89-f488-4771-94ae-43098476c8c2/image.png" alt=""></li>
</ul>
<blockquote>
<p>Queue 에는 처음 1이 들어가고 이를 다시 poll()해주면서 인접 노드들인 2, 3을 Queue에 삽입해주며 탐색, 이를 반복하는 것이다.</p>
</blockquote>
<p>이러한 BFS의 구현은 앞서 말했다시피 재귀적으로 불가능하다.
구현에 대한 자세한 내용은 아래 문제풀이 링크를 확인해보자!</p>
<p><a href="https://velog.io/@_hennessy_/%ED%8E%98%EC%96%B4%EC%BD%94%EB%94%A9%EC%8A%A4%ED%84%B0%EB%94%94%EA%B2%8C%EC%9E%84%EB%A7%B5-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC-%EA%B5%AC%ED%95%98%EA%B8%B0">https://velog.io/@_hennessy_/%ED%8E%98%EC%96%B4%EC%BD%94%EB%94%A9%EC%8A%A4%ED%84%B0%EB%94%94%EA%B2%8C%EC%9E%84%EB%A7%B5-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC-%EA%B5%AC%ED%95%98%EA%B8%B0</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[페어코딩스터디<게임맵 최단거리 구하기>]]></title>
            <link>https://velog.io/@_hennessy_/%ED%8E%98%EC%96%B4%EC%BD%94%EB%94%A9%EC%8A%A4%ED%84%B0%EB%94%94%EA%B2%8C%EC%9E%84%EB%A7%B5-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@_hennessy_/%ED%8E%98%EC%96%B4%EC%BD%94%EB%94%A9%EC%8A%A4%ED%84%B0%EB%94%94%EA%B2%8C%EC%9E%84%EB%A7%B5-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 07 Dec 2022 03:44:18 GMT</pubDate>
            <description><![CDATA[<h2 id="눈물의-문제풀이">눈물의 문제풀이</h2>
<p>문제를 처음 봤을 때 50x50x170의 직사각형 상자에 갇힌 기분이었다.
도대체 이게 뭔 소릴까...
이제 그래프를 막 배우고 dfs와 bfs의 개념정리도 제대로 되어있지 않은 상태로 
이 문제를 풀려니 너무 어려웠다.
애초에 왜 bfs를 쓰는가에 대하여도 이해를 못하고 있었다.
테스트에 좌표문제는 필수인 것 같은데 좌표만 보면 덜덜 떨린다....
그래서 이 문제를 잡고 몇시간을 고민하면서 진짜 눈물흘릴 뻔했다..
내 스스로 머리가 안돌아가는 느낌도 괴로웠지만,
&#39;정말 아무것도 모르겠다!&#39;
이 생각밖에 안들었다.
고민해서 해결되지 않을 것 같아서 최고의 선생님, 구글을 찾았다...
일단 보고 분석하고 백지에서 다시 써보자는 마음으로.
가보자고~!
<img src="https://velog.velcdn.com/images/_hennessy_/post/586c4aee-3ec8-42d6-b7f1-926c042fa316/image.jpeg" alt=""></p>
<p>문제는 이러하다.</p>
<blockquote>
<p>문제 설명
ROR 게임은 두 팀으로 나누어서 진행하며, 상대 팀 진영을 먼저 파괴하면 이기는 게임입니다. 따라서, 각 팀은 상대 팀 진영에 최대한 빨리 도착하는 것이 유리합니다.
지금부터 당신은 한 팀의 팀원이 되어 게임을 진행하려고 합니다. 다음은 5 x 5 크기의 맵에, 당신의 캐릭터가 (행: 1, 열: 1) 위치에 있고, 상대 팀 진영은 (행: 5, 열: 5) 위치에 있는 경우의 예시입니다.
<img src="https://velog.velcdn.com/images/_hennessy_/post/95bb8f6e-5481-4e82-bbdf-d82fa36d4844/image.png" alt="">
위 그림에서 검은색 부분은 벽으로 막혀있어 갈 수 없는 길이며, 흰색 부분은 갈 수 있는 길입니다. 캐릭터가 움직일 때는 동, 서, 남, 북 방향으로 한 칸씩 이동하며, 게임 맵을 벗어난 길은 갈 수 없습니다.
아래 예시는 캐릭터가 상대 팀 진영으로 가는 두 가지 방법을 나타내고 있습니다.</p>
</blockquote>
<blockquote>
<ul>
<li>첫 번째 방법은 11개의 칸을 지나서 상대 팀 진영에 도착했습니다.
<img src="https://velog.velcdn.com/images/_hennessy_/post/9cba9d3a-0287-49e1-a0e4-20c061634699/image.png" alt=""></li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>두 번째 방법은 15개의 칸을 지나서 상대팀 진영에 도착했습니다.
<img src="https://velog.velcdn.com/images/_hennessy_/post/5bd118e9-8cf2-441d-a9aa-71da2a295c8b/image.png" alt=""></li>
</ul>
</blockquote>
<blockquote>
<p>위 예시에서는 첫 번째 방법보다 더 빠르게 상대팀 진영에 도착하는 방법은 없으므로, 이 방법이 상대 팀 진영으로 가는 가장 빠른 방법입니다.
만약, 상대 팀이 자신의 팀 진영 주위에 벽을 세워두었다면 상대 팀 진영에 도착하지 못할 수도 있습니다. 예를 들어, 다음과 같은 경우에 당신의 캐릭터는 상대 팀 진영에 도착할 수 없습니다.
<img src="https://velog.velcdn.com/images/_hennessy_/post/c3ffd578-d9b1-4e80-ab67-a8262c475136/image.png" alt="">
게임 맵의 상태 maps가 매개변수로 주어질 때, 캐릭터가 상대 팀 진영에 도착하기 위해서 지나가야 하는 칸의 개수의 최솟값을 return 하도록 solution 함수를 완성해주세요. 단, 상대 팀 진영에 도착할 수 없을 때는 -1을 return 해주세요.</p>
</blockquote>
<blockquote>
<p>제한사항</p>
</blockquote>
<ul>
<li>maps는 n x m 크기의 게임 맵의 상태가 들어있는 2차원 배열로, n과 m은 각각 1 이상 100 이하의 자연수입니다.</li>
<li>n과 m은 서로 같을 수도, 다를 수도 있지만, n과 m이 모두 1인 경우는 입력으로 주어지지 않습니다.</li>
<li>maps는 0과 1로만 이루어져 있으며, 0은 벽이 있는 자리, 1은 벽이 없는 자리를 나타냅니다.</li>
<li>처음에 캐릭터는 게임 맵의 좌측 상단인 (1, 1) 위치에 있으며, 상대방 진영은 게임 맵의 우측 하단인 (n, m) 위치에 있습니다.</li>
</ul>
<blockquote>
<p>입출력 예시
<img src="https://velog.velcdn.com/images/_hennessy_/post/a66e78ec-2b9d-4228-b79a-12cadecf3b74/image.png" alt=""></p>
</blockquote>
<h2 id="브레인스토밍">브레인스토밍</h2>
<p>무엇부터 해야할지 모르겠는 상황에서 스터디장님의 도움을 받아 우선 dfs를 쓸 것인가 bfs를 쓸 것인가 구분지었다.</p>
<blockquote>
<p>DFS 그게 뭔데?</p>
</blockquote>
<ul>
<li>깊이 우선 탐색법</li>
<li>모든 분기의 끝을 탐색하기 때문에</li>
<li>순열이나  어떠한 모든 경우의 수를 알아내기 위할 때 사용</li>
<li>정점 노드를 기점으로 </li>
</ul>
<blockquote>
<p>BFS 너는 뭔데?</p>
</blockquote>
<ul>
<li>너비우선 탐색법</li>
<li>트리구조로 치자면 레벨별 탐색</li>
<li>해당 목적지가 존재하는 레벨을 탐색하는 방법</li>
<li>거리 계산 프로그램에 적합</li>
</ul>
<p>그러니까, 여기서 깊이 우선으로 탐색해버리면 모든 경우의 수를 탐색하기 때문에 적절치 못하고
너비 우선 탐색을 하면 모든 분기의 엣지들을 다 훑는 것이 아니라 필요한 정보가 있는 레벨을 탐색하게 되는 것이다.
지금도 쓰면서 약간 헷갈려 하는 중이다...</p>
<p>암튼 그렇게 방향성을 잡고 코드를 짜보았다.</p>
<pre><code>package findShortestWay;

//프로그래머스 게임맵최단거리 구하기 ROR

import java.util.LinkedList;
import java.util.Queue;

class Solution {
    int[] dx = {0, 0, 1, -1};
    int[] dy = {-1, 1, 0, 0};

    public int soulution(int[][] maps){
        int answer = 0;
        int[][] visited = new int[maps.length][maps[0].length];

        visited[0][0] = 1; //시작위치 방문체크

        //bfs 탐색
        bfs(maps, visited);
        //도착지 값을 넣어주기
        answer = visited[maps.length - 1][maps[0].length - 1];

        //갈 수 없다면 -1 return
        if (answer == 0){
            answer = -1;
        }

        return answer;
    }

    public void bfs(int[][] maps, int[][] visited){
        Queue&lt;int[]&gt; q = new LinkedList&lt;&gt;();
        q.add(new int[]{0, 0});

        while (!q.isEmpty()){
            int[] now = q.poll();
            int x = now[0]; //0
            int y = now[1]; //0

            //4방 탐색
            for (int i = 0; i &lt; 4; i++) {
                //이동시 위치
                int nx = x + dx[i]; //0
                int ny = y + dy[i]; //0

                //범위 벗어나는지 확인
                //방문했는지 확인
                //갈 수 있는지 확인
                if(nx &gt;= 0 &amp;&amp; nx &lt; maps.length &amp;&amp; ny &gt;=0 &amp;&amp; ny &lt; maps[0].length &amp;&amp; visited[nx][ny] == 0 &amp;&amp; maps[nx][ny] == 1){
                    //방문했다고 체크하기
                    visited[nx][ny] = visited[x][y] + 1;
                    //큐에 넣기
                    q.add(new int[]{nx, ny});
                }
            }
        }
    }
}
</code></pre><blockquote>
<ul>
<li>처음 정수배열 dx dy는 이동하는 방향에 대해 정의하기 위해 선언해놓았다.</li>
</ul>
</blockquote>
<ul>
<li>아래 메서드 bfs에서 4방탐색 아래를 보면 포문으로 4번 돌려 갈 수 있는 방향을 알 수 있고,</li>
<li>출발점, 즉 (x, y) 에 이 dx, dy의 값을 각각 더하여 현재 위치를 다시 설정하는 것이다.</li>
<li>그런데 문제에서 이 맵밖을 나갈 수 없다는 조건이 있어서 만약 x나  y중에 음수가 있으면 이는 맵 탈출이라고 본다.
따라서 이 경우에는 q에 add되지 않고 패스된다.</li>
<li>이런 과정을 반복해서 q에 아무것도 남아있지 않게 되면,
if문의 실행결과에 따라 내가 방문했던 좌표들은 visited[][] = 0에서 이동 횟수만큼 +1을 하게 된다.</li>
<li>그리고 다시 solution메서드로 돌아와서 만약 목표로 하는 (n-1, m-1)에 방문한 적이 없었다면 
그 좌표에 대한 visited는 0이 되고 이때는 갈 수 없은 경우로 판단, -1을 return하게 되는 것이다.</li>
</ul>
<p>이 문제를 완벽하게 이해하기 위해서는 아무래도 백지에 한 다섯번 정도 더 반복해서 구현해보아야 할 것 같다.
아직 bfs나 dfs나 익숙하지가 않아서 많이 어려웠다....(주륵)
코드 자체를 분석하는 데에만 몇시간을 쏟았던 것 같다....</p>
<p>뭔가 오롯이 내 스스로의 힘으로 해결해야 할 것 같은 느낌에 검색하고 이런거에 거부감이 좀 들었는데
스터디장님 말씀이, 현업에서는 모르면 모른다고 빨리 말을 해야 한다고.
프로젝트 하루전에 &quot;모르겠어요~&quot; 이러면 더 욕나오는 일이라고 하셨다.
필요할 때에는 적절히 검색을 이용하자.
아직 나는 개발초보자이기 때문에, 자바의 기본 문법도 100프로 다 안다고 할 수 없기에 ㅋㅋㅋ.....
그리고, 스터디는 진짜 일주일 공부 일정 중 가장 유익한 것 같다.</p>
<p>화이팅~~!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[페어코딩스터디 <백준-제로>풀이]]></title>
            <link>https://velog.io/@_hennessy_/%ED%8E%98%EC%96%B4%EC%BD%94%EB%94%A9%EC%8A%A4%ED%84%B0%EB%94%94-%EB%B0%B1%EC%A4%80-%EC%A0%9C%EB%A1%9C%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@_hennessy_/%ED%8E%98%EC%96%B4%EC%BD%94%EB%94%A9%EC%8A%A4%ED%84%B0%EB%94%94-%EB%B0%B1%EC%A4%80-%EC%A0%9C%EB%A1%9C%ED%92%80%EC%9D%B4</guid>
            <pubDate>Wed, 30 Nov 2022 01:09:12 GMT</pubDate>
            <description><![CDATA[<h2 id="소식은-없었지만-여전히-스터디-중--">소식은 없었지만 여전히 스터디 중. . .</h2>
<p>요즘 코딩테스트며 CS시험이며 정신이 하나도 없어서 글 쓸 여유가 많지 않았다..
이 온점의 갯수는 나의 처참했던 코딩테스트 결과를 대신한다.........</p>
<p>글을 안올렸지만 여전히 스터디는 열심히 참여중이었다.
(근데 한번 애기 재우다가 나도 잠들어서 못들어갔다...흑흑흑)
<img src="https://velog.velcdn.com/images/_hennessy_/post/9c444680-0070-42b5-9578-a811df0cefcd/image.jpeg" alt=""></p>
<p>앞으론 애기는 남편에게 맡겨 재우는걸로....</p>
<h2 id="백준-제로">백준: 제로</h2>
<p>각설하고 내가 이번주에 맡았던 문제다! 실버4문제인데 스택을 배우고 나니 
&#39;이게 왜 실버4지...?&#39;
싶은 오만함이 내 마음을 휩쓸었다...ㅋㅋㅋ</p>
<p>문제 조건은 이러하다!</p>
<blockquote>
<p>문제
나코더 기장 재민이는 동아리 회식을 준비하기 위해서 장부를 관리하는 중이다.</p>
</blockquote>
<p>재현이는 재민이를 도와서 돈을 관리하는 중인데, 애석하게도 항상 정신없는 재현이는 돈을 실수로 잘못 부르는 사고를 치기 일쑤였다.</p>
<blockquote>
<p>재현이는 잘못된 수를 부를 때마다 0을 외쳐서, 가장 최근에 재민이가 쓴 수를 지우게 시킨다.
재민이는 이렇게 모든 수를 받아 적은 후 그 수의 합을 알고 싶어 한다. 재민이를 도와주자!</p>
</blockquote>
<blockquote>
<p>입력
첫 번째 줄에 정수 K가 주어진다. (1 ≤ K ≤ 100,000)
이후 K개의 줄에 정수가 1개씩 주어진다. 정수는 0에서 1,000,000 사이의 값을 가지며, 정수가 &quot;0&quot; 일 경우에는 가장 최근에 쓴 수를 지우고, 아닐 경우 해당 수를 쓴다.
정수가 &quot;0&quot;일 경우에 지울 수 있는 수가 있음을 보장할 수 있다.</p>
</blockquote>
<blockquote>
<p>출력
재민이가 최종적으로 적어 낸 수의 합을 출력한다. 최종적으로 적어낸 수의 합은 231-1보다 작거나 같은 정수이다.</p>
</blockquote>
<p>그러니까 0은 backspace인 것이다.
그래서 스택으로 쌓다가 0이 나오면 팝해주고,
결과값은 스택에 남은 모든 것들의 합이 되겠다.</p>
<p>처음에 너무 쉽게 풀어서 얼른 제출 돌려보자는 마음으로 신나게 돌렸는데...
계속 &quot;시간초과&quot;가 나왔다...
로직도 그렇게 복잡하지 않은데 도대체 왜...?
그런데 내가 문제 잘못보고 합을 안구했다.
앞으로의 다짐은....문제를 잘 읽자...!..
그게 제일 중요한 준비였다......
<img src="https://velog.velcdn.com/images/_hennessy_/post/bf06acfa-9a15-4d60-8453-9631c4bb9d9f/image.gif" alt=""></p>
<p>코드를 한번 보자!</p>
<pre><code>public class Main {
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int k = sc.nextInt();

        int[] numbers = new int[k];

        for (int i = 0; i &lt; numbers.length; i++) {
            numbers[i] = sc.nextInt();
        }

        Stack&lt;Integer&gt; stack = new Stack();

        for (int i = 0; i &lt; numbers.length; i++) {
            if(numbers[i] != 0){
                stack.push(numbers[i]);
            } else if (numbers[i] == 0 &amp;&amp; !stack.isEmpty()) {
                stack.pop();
            }
        }

        int result = 0;
        while (!stack.isEmpty()){
            result += stack.pop();
        }

        System.out.println(result);
    }
}</code></pre><p>매우 간단하게 풀었다. 처음으로 딱 보고 느낌 딱 와서 푼 문제....
백준 제출해서 &quot;맞았습니다!!&quot; 가 뜬 나의 첫 문제...&quot;제로&quot; 
잊지 않겠다...</p>
<p>근데 어제 스터디 하면서 들어보니 Scanner보다 BufferReader가 훨씬 메모리를 덜 먹는다는 얘길 들어서
다음엔 BufferReader를 써 볼 생각이다.</p>
<p>백준은 처음 해봐서 다 메인함수에 넣어야 하는게 적응이 안된다.
클래스 만들어서 하는게 나는 더 재밌는거 같다.ㅋㅋㅋㅋ
그래서 맨날 클래스 만들고 다시 메인에 꾸깃꾸깃 넣는 중.</p>
<p>앞으로 어려운 문제들도 딱 느낌이 팍 와서(?)ㅋㅋㅋ
슝슝 풀고 싶다...</p>
<p>얼른 공부해야지....</p>
<p>안녕<del>~</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[페어코딩 스터디 준비 (1편)]]></title>
            <link>https://velog.io/@_hennessy_/sbqoc76r</link>
            <guid>https://velog.io/@_hennessy_/sbqoc76r</guid>
            <pubDate>Tue, 15 Nov 2022 03:08:36 GMT</pubDate>
            <description><![CDATA[<h1 id="페어코딩-스터디-준비-1편">페어코딩 스터디 준비 (1편)</h1>
<p>페어코딩 스터디를 하다보니 내가 네비게이터로서 설명을 해줘야 해서 문제를 좀 설명하면서 머릿속을 정리하려고 한다! 오늘은 수업에서 예제로 나왔던 문제를 다뤄볼 것이다.
문제 자체는 되게 간단한거 같은데 나는 역시 개린이(개발 어린이)라 ㅋㅋㅋ강사님처럼 쒹쒹하는게 여전히 넘나 신기함.......대단하세요.......존경해요...
암튼 이따가 할 페어코딩 스터디에 쩔쩔 매지 않도록 만발의 준비를 해보자!!!!
<img src="https://velog.velcdn.com/images/_hennessy_/post/51c1ba12-5073-4ea8-bfcc-4dfffc41ca0b/image.gif" alt=""></p>
<h2 id="입력한-수를-거꾸로-출력하기">입력한 수를 거꾸로 출력하기</h2>
<blockquote>
<ul>
<li>12345를 입력하면 54321로 거꾸로 출력</li>
</ul>
</blockquote>
<ul>
<li>100의 경우 0이 사라지고 1만 출력</li>
<li>-12345를 입력했으면 -54321로 출력</li>
</ul>
<p>이것이 만약...배열이었다면 muy facíl하게...포문 배열로 뽑았겠지만...
이것은 정수로 출력하는 것이다....
첨에 문제 보고 &#39;헉 이거 어떻게 하라는겨!!!&#39;
했는데 강사님 설명보고 아~ 했다.
풀이 과정을 설명해 보자면.</p>
<blockquote>
<ol>
<li>12345를 10으로 나눠 나머지를 저장,</li>
<li>몫에서 또 10을 나눠 나머지 저장(안나눠질때까지..)</li>
<li>그리고 각 몫에 10을 곱하고 나머지를 더하는 과정</li>
</ol>
</blockquote>
<p>이렇게 보면 뭔말인지 싶다....한번 코드를 보자!</p>
<pre><code>
public class Practice1 {
    public static void solution(int num) {
        int numReverse = 0;
        boolean isMinus = false;

        if (num &lt; 0){
            isMinus = true;
            num *= -1;
        }

        while (num&gt;0){
            int r = num % 10;
            num /=10;
            numReverse = numReverse * 10 + r;
        }
        System.out.println(isMinus ? numReverse * -1 : numReverse);

    }

    public static void main(String[] args) {
        solution(12345);
        solution(-12345);
        solution(100);
        solution(0);
    }
}</code></pre><ul>
<li>우선 practice1이란 클래스 안에 이름은 solution, 생성자엔 int만 들어갈 수 있는 메서드를 만들었다.</li>
<li>boolean isMinus를 초기화 하고 , 음수가 들어갔을 때는 우선 -1을 곱해 양수로서 함께 while문으로 돌아갈 수 있게끔 해줬다.</li>
<li>그렇게 입력된 num이 while문으로 들어가서 num이 0보다 큰 상황에</li>
<li>Int r에 num을 10으로 나눴을 때의 나머지 값을 저장,</li>
<li>num은 몫으로 저장되고</li>
<li>앞서 선언한 numReverse라는 변수에 10을 곱하고 나머지 r을 더한 값을 반복.</li>
<li>0보다 크지 못해진(?) num은 while을 빠져나와 만약 isMinus(음수이면) ? numReverse값에 -1을 다시 곱해서 음수로 만들고</li>
<li>isMinus가 false였으면, 그냥 numReverse를 출력한다.</li>
</ul>
<p>처음에 이 numReverse가 왜 나오는지?
이걸 이렇게 곱하는게 의미가 있다고? 했는데
손코딩 해보면서 직접 대입해보고 하니까 대박임...이게 맞는거였어...
그러면서 역시 고수들은 ㅋㅋㅋㅋㅋ생각하는게 다르다고 느꼈음 ㅠㅠㅠㅠ대박적...
어떻게 이런 생각을 하지요?
뭔가 원리라도 알겠으면 이해하겠는데 아직도 원리가 이해가 안되는중..그냥 넣어보니까 되길래 대박이라....&#39;ㅅ&#39;;;;;;
해설 안봤으면 혼자 백프로 쩔쩔 맸음 ㅋㅋㅋ</p>
<p><img src="https://velog.velcdn.com/images/_hennessy_/post/e2aef900-597d-44b1-a46f-aebe7710860b/image.webp" alt="">
마무리가 어색하지만 빠이!ㅋㅋㅋㅋ오늘 스터디 잘 할 수 있기를!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[로또 프로그램 만들기]]></title>
            <link>https://velog.io/@_hennessy_/%EB%A1%9C%EB%98%90-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@_hennessy_/%EB%A1%9C%EB%98%90-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Mon, 14 Nov 2022 02:50:28 GMT</pubDate>
            <description><![CDATA[<h3 id="treeset을-이용한-로또-번호-뽑기-프로그램">TreeSet을 이용한 로또 번호 뽑기 프로그램</h3>
<p>사실 과제 때문에 만들게 된 것이지만, 다 하고 보니 과세 프로그램보다 더 어렵게 해결을 했던 것 같아서 기록으로 남겨보고자 한다.
그건 어쩌면 이 프로그램 만들기가 성장에 도움을 꽤나 주었던 것일지도...?
그래서 다음 과제가 비교적 쉬웠다고 느껴졌을 지도 모르겠다.</p>
<p>아무튼 이 로또 프로그램의 조건은 이러하다.</p>
<blockquote>
<ul>
<li>scanner를 통해 내가 입력한 수만큼 (1~10까지) 랜덤 로또번호를 생성할 것.
(6개를 입력했다면 6개의 번호가 6쌍으로..)</li>
</ul>
</blockquote>
<ul>
<li>당첨 번호 또한 생성할 것.</li>
<li>나의 번호와 당첨 번호를 비교하여 일치하는 수가 몇개인지 출력할 것.</li>
</ul>
<p>원래는 이 과제를 이차원 배열로 해결하려고 했었다.
그리고 이차원 배열로 어떻게 당첨 번호 뽑는 것 까지는 진행을 했었는데 ㅋㅋㅋ
그 번호를 뽑는 와중에 중복을 제거하고 오름차순으로 나열하려니 코드가 너무     복잡해지더라....
for문 안에 for문이 두개나 더 들어가니까 엄청 헷갈렸다.......
<img src="https://velog.velcdn.com/images/_hennessy_/post/e875eaf1-36f9-48b3-9cbe-cc9f511e8507/image.gif" alt="">
하다가 뇌정지 온건 안비밀....
과세  프로그램은 하루 정도 걸려 했는데....
이 이차원 배열로 골머리를 썩히느라...로또 프로그램은 3일걸린 듯....ㅋㅋㅋㅋㅋ</p>
<p>그래서 이차원 배열은 버리기로 했다.
그리고 그 다음으로 생각한게 HashSet이었는데 ㅋㅋㅋㅋ
중복만 제거하는거 사라지면 좀 편할 거라고 생각했다...하지만..........ㅋㅋㅋ
오름차순이가 나를 잡았다....ㅠㅠ따로 또 넣기 복잡해지고 싫어서 다른 방법 없나 궁리함...
그런데 같이 공부하시는 분이 TreeSet쓰면 자동으로 오름차순으로 정리 된다는 것을 알려주셨다...
여기까지.. TreeSet으로 오게 된 여정이다..</p>
<p>그래..그럼 TreeSet으로 한번 해보자.
그 전에 HashSet으로 한건 그나마 나았음.
왜냐면 이차원 배열로 한거는 그냥 코드 다 지워야 했지만 그래도 같은 Set 계열이라 그런가?
그냥 HashSet을 TreeSet으로 변경만 해줘도 됐기에...
<img src="https://velog.velcdn.com/images/_hennessy_/post/6ad58386-0b76-49fa-a538-b0cb8ded4dcb/image.webp" alt="">
TreeSet알려줘서 감사합니다....덕분에 고생을 덜었습니다...(feat. 줄진 재생)
근데 당첨 번호 뽑는 곳에서는 그냥 한쌍밖에 없겠다 for문으로 돌림.
결론: TreeSet도 쓰고 for문도 쓰고 했다~</p>
<p>요약해서 말을 하자면</p>
<blockquote>
<p>TreeSet의 특징</p>
</blockquote>
<ol>
<li>Random으로 돌렸을 때 중복을 제거하여 산출</li>
<li>오름차순 정리</li>
<li>여러개의 element저장 가능</li>
<li>그리고 그 여러개의 element에 배열을 저장가능! (어쨋든 자기도 ArrayList부류다 이거지....)</li>
</ol>
<p>그렇게 TreeSet으로 방향을 잡고 시작했다.</p>
<h4 id="나의-로또-번호-만들기의-로직">&lt;나의 로또 번호 만들기의 로직&gt;</h4>
<ul>
<li>여러개의 로또 쌍을 저장할 수 있도록 변수를 만들고 (bundle)</li>
<li>내가 산 로또 쌍에 이름 알파벳 출력(A, B, C, D, E ...)</li>
<li>원하는 구매 갯수 입력하도록 만들고(Scanner), 그 수를 변수 선언(many)</li>
<li>for문 만들고 그 안에 먼저 ArrayList(TreeSet) 변수를 하나 만든다. (number)</li>
<li>그리고 그 아래 while문을 넣고 number.size()&lt;6이 참일 때,</li>
<li>이 number라는 TreeSet에 46까지의 Random수를 넣는다.</li>
<li>그리고 마지막! for문 빠져나오기 전에 bundle(번호6개인 로또 하나씩 저장)에 저장하고</li>
<li>탈출~~!!</li>
</ul>
<h4 id="당첨-번호-로직6개의-번호-한쌍">&lt;당첨 번호 로직(6개의 번호 한쌍)&gt;</h4>
<ul>
<li>당첨 번호가 저장될 int[] 변수 선언(lotto)</li>
<li>for문으로 i가 lotto.legth만큼 돌면서</li>
<li>lotto[j]에 난수 저장</li>
<li>그리고 또!!!!for문을 넣어 조건문, lotto[i]와 lotto[j]가 같을 때 i에서 1씩 빼서 다시 랜덤 함수를 뽑게끔 했음.</li>
</ul>
<p>뭔가 구구절절 좔좔하게 쓴 것 같은데 그것은 이것을 보는 사람들의 뇌를 편안하게 하기 위해서다...
<img src="https://velog.velcdn.com/images/_hennessy_/post/fffe0e8e-0dd3-4349-91d9-cd0cc59d78d6/image.webp" alt="">
완전 진심임 ㅎㅎ</p>
<h4 id="이제-본격-코드를-한번-살펴보자">이제 본격 코드를 한번 살펴보자!</h4>
<ol>
<li><pre><code>import java.util.*;
public class main(String[] args){
 public static void main {
     Scanner sc = new Scanner(System.in);
     Random rdm = new Random();
     ArrayList&lt;TreeSet&gt; bundle = new ArrayList&lt;&gt;();
     char[] myLottery = {A, B, C, D, E, F, G, H, I, J} 
     }
 }
</code></pre></li>
</ol>
<p>일단 이렇게 초반부를 들어가겠다. 필요한 스캐너, 랜덤, 배열을 저장할 bundle변수,
내 로또 한장한장을 구분지어줄 A, B, C.....</p>
<ol start="2">
<li><pre><code>    System.out.println(&quot;[로또 당첨 프로그램]&quot;);
     System.out.print(&quot;구매 개수를 입력해 주세요.(1~10): &quot;);
     int many = sc.nextInt();

     while(0 &gt; many &amp;&amp; many &gt; 10){
     System.out.print(&quot;다시 입력해 주세요.&quot;)
     many = sc.nextInt();
     }

     //여기까지는 잘못된 수를 입력했을 때 다시 돌아가게끔 While을 써준 내용이다.//

</code></pre></li>
</ol>
<pre><code>    //본격 내 로또 뽑기!!
    for (int i = 0; i &lt; many; i++) {
        TreeSet&lt;Integer&gt; number = new TreeSet&lt;&gt;();
        while (number.size()&lt;6){
            number.add(rdm.nextInt(45)+1);
        }
        bundle.add(number);
    }

    for (int i = 0; i &lt; many; i++) {
        System.out.print(myLottery[i]);
        System.out.println(bundle.get(i));
        }
    System.out.println();</code></pre><p>본격 로또 뽑기 아래 내용을 보자.
for문으로 i가 돌아갈 때마다 number라는 TreeSet이 선언되고, 그 아래 while을 넣어 이 변수에 6개의 번호를 입력하는 모습이다.
여기까진 오케이,,,,그런데 첨엔 이 랜덤으로 나온 수를 어떻게 저장하는지를 몰라서 이것 또한 학우분의 도움을 받음.....ㅋ 아직 메서드를 쓰는걸 잘 몰라서 그런거 같다.
근데 왜 ArrayList는 .add고 map은 .put이고,,,StringBuffer는 .append 로 하는거냐....
add로 통일 시켜주면 안댐?
ㅋㅋㅋㅋㅋ
<img src="https://velog.velcdn.com/images/_hennessy_/post/95e5b467-94e9-475c-91d6-436c805083e3/image.gif" alt=""></p>
<p>아무튼 그렇게 for문을 완전히 빠져나오기 전에 앞서 만든 number(ArrayList)에 저장을 해줬다.
그리고 일단 출력!!<img src="https://velog.velcdn.com/images/_hennessy_/post/f03608ab-f4c9-4474-8c5a-2cbffe512e08/image.png" alt=""></p>
<p>으음 아주 좋다. 앞에 로또마다 이름 넣어주려고 다시 for문 써서 i번째 myLottery인덱스, bundle 인덱스를 뽑아주었다.</p>
<p>그리고 이제....for문을 돌려서 당첨 번호를 뽑아보자!</p>
<ol start="3">
<li><pre><code>     System.out.println(&quot;[로또 발표]&quot;);

             int[] lotto = new int[6];
     for (int i = 0; i &lt; 6; i++) {
         lotto[i] = rdm.nextInt(45) + 1;
         for (int j = 0; j &lt; i; j++) {
             if (lotto[i] == lotto[j]) {
                 i--;
                 break;
             }
         }
     }
     Arrays.sort(lotto);
     System.out.println(Arrays.toString(lotto));

</code></pre></li>
</ol>
<p>for문은 이렇게 사용했다. 
이 중복 제거하는 j에 관한 for문이 처음에는 이해가 잘 안됐다 ,,
근데 곰곰히 생각해보니...
&quot;만약에 lotto[j]의 요소가 그 이전[i]요소에 있다면 i를 빼서 다시 돌아가게끔 한 후, 멈춘다.&quot;
뭔가 말로 하니 설명이 안되는데 이런 느낌이겠거니 하는 중이다.
이차원 배열로 했을 땐 랜덤 없앤다고 for문이 세개나 됐음 ^^^^
그러니까 코드가 완전 복잡했고 결론은 삽질이 됐지 ^^^ㅋㅋㅋ<img src="https://velog.velcdn.com/images/_hennessy_/post/dd490def-1762-4231-862f-8dc4484afaab/image.gif" alt=""></p>
<p>그리고 마지막 단계...
당첨 번호를 출력하고 내 번호와 비교하여, 일치하는 수의 갯수를 찾기!!
근데 나는 왕초보라 사실 Arrays.toString도 몰랐따. 들어보니 그냥 Array로 출력하면 그 배열이 저장된 메모리가 출력된다구? 새로운 지식을 이렇게 또 얻어간다 ㅋㅋ</p>
<p>내가 맞춘 숫자는 0으로 초기화된 변수 하나를 만들고,
for문으로 bundle의 i번째 배열의 인덱스와 Winning의 인덱스를 하나하나 비교해서 
일치하는게 있으면 count++; 이렇게 만들어보았다.</p>
<pre><code>        System.out.println();

        System.out.println(&quot;[내 로또 결과]&quot;);

        int count = 0;

        for (int i = 0; i &lt; many; i++) {
            count = 0;
            for (int j = 0; j &lt; 6; j++) {
                if (bundle.get(i).contains(Winning[j])){
                    count++;
                }
            }
            System.out.println(&quot;맞춘 개수: &quot; + myLottery[i] + &quot;  &quot; +count + &quot;개&quot;);
        }

    }
}</code></pre><p>여기서도 .get이라든가, contains라든가 전혀 메서드를 사용할 생각을 못했음.
ㅠㅠㅠ
메서드를 활용할 생각을 해야하는데 나는 뭐 메서드도 하나만 쓸 수 있는 줄 알았다...
잊지않고 쓸 수 있도록 오늘은 메소드맨 노래를 열심히 들어야겠다.....</p>
<p>아래는 이제 전체 코드다!.</p>
<pre><code>import java.util.*;

public class Main2 {
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        Random rdm = new Random();

        System.out.println(&quot;[로또 당첨 프로그램]&quot;);

        ArrayList&lt;TreeSet&gt; bundle = new ArrayList&lt;&gt;();
        System.out.print(&quot;구매 개수를 입력해 주세요.(1~10): &quot;);
        int many = sc.nextInt();


        char[] myLottery = {&#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;, &#39;E&#39;, &#39;F&#39;, &#39;G&#39;, &#39;H&#39;, &#39;I&#39;, &#39;J&#39;};


        for (int i = 0; i &lt; many; i++) {
            TreeSet&lt;Integer&gt; number = new TreeSet&lt;&gt;();
            while (number.size()&lt;6){
                number.add(rdm.nextInt(45)+1);
            }
            bundle.add(number);
        }

        for (int i = 0; i &lt; many; i++) {
            System.out.print(myLottery[i]);
            System.out.println(bundle.get(i));
            }
        System.out.println();

        System.out.println(&quot;[로또 발표]&quot;);
        int[] lotto = new int[6];
        for (int i = 0; i &lt; 6; i++) {
            lotto[i] = rdm.nextInt(45) + 1;
            for (int j = 0; j &lt; i; j++) {
                if (lotto[i] == lotto[j]) {
                    i--;
                    break;
                }
            }
        }
        Arrays.sort(lotto);
        System.out.println(Arrays.toString(lotto));


        System.out.println();

        System.out.println(&quot;[내 로또 결과]&quot;);

        int count = 0;

        for (int i = 0; i &lt; many; i++) {
            count = 0;
            for (int j = 0; j &lt; 6; j++) {
                if (bundle.get(i).contains(lotto[j])){
                    count++;
                }
            }
            System.out.println(&quot;맞춘 개수: &quot; + myLottery[i] + &quot;  &quot; +count + &quot;개&quot;);
        }

    }
}</code></pre><h3 id="다른-방식으로-해결한-것클래스-만들어-넣기">다른 방식으로 해결한 것(클래스 만들어 넣기)</h3>
<pre><code>import java.util.*;

class lottery {
    public static void cal() {
        ArrayList&lt;TreeSet&gt; myLottery = new ArrayList&lt;&gt;();
        int[] winNumber = new int[6];
        Scanner sc = new Scanner(System.in);
        Random rdm = new Random();
        int count = 0;
        char[] name = {&#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;, &#39;E&#39;, &#39;F&#39;, &#39;G&#39;, &#39;H&#39;, &#39;I&#39;, &#39;J&#39;};

        System.out.println(&quot;[로또 당첨 프로그램]&quot;);
        System.out.print(&quot;구매개수를 입력해 주세요.(1~10) : &quot;);
        int number = sc.nextInt();

        if (0 &gt; number &amp;&amp; number &gt; 10) {
            System.out.print(&quot;다시 입력해 주세요. : &quot;);
            sc.nextInt();
        }

        for (int i = 0; i &lt; number; i++) {
            TreeSet&lt;Integer&gt; myNumbers = new TreeSet&lt;&gt;();
            while (myNumbers.size() &lt; 6) {
                myNumbers.add(rdm.nextInt(45) + 1);
            }
            myLottery.add(myNumbers);
        }

        for (int i = 0; i &lt; number; i++) {
            System.out.print(name[i]);
            System.out.println(myLottery.get(i));
        }

        System.out.println();

        System.out.println(&quot;로또 발표&quot;);
        for (int i = 0; i &lt; winNumber.length; i++) {
            winNumber[i] = rdm.nextInt(45) + 1;
            for (int j = 0; j &lt; i; j++) {
                if (winNumber[i] == winNumber[j]) {
                    i--;
                    break;
                }
            }
        }
        Arrays.sort(winNumber);
        System.out.println(Arrays.toString(winNumber));


        System.out.println();

        for (int i = 0; i &lt; number; i++) {
            count = 0;
            for (int j = 0; j &lt; 6; j++) {
                if (myLottery.get(i).contains(winNumber[j])) {
                    count++;
                }
            }
            System.out.println(&quot;맞춘 개수 &quot; + name[i] + &quot;  &quot; + count + &quot;개&quot;);
        }

    }
}


public class Main {
    public static void main(String[] args) {
        lottery.cal();
    }
}</code></pre><p>모쪼록 이 험난한 여정에서....
나의 어려움...궁금증을 해결해주시는데 도움을 주는 모든 분들에게 샤라웃 하고싶다........</p>
<p>¡Muchas Gracias, mis compañeros!🖤</p>
<p><img src="https://velog.velcdn.com/images/_hennessy_/post/724b3936-2dfa-496f-a306-d8b73e400718/image.webp" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA 페어코딩 1일차]]></title>
            <link>https://velog.io/@_hennessy_/JAVA-%ED%8E%98%EC%96%B4%EC%BD%94%EB%94%A9-1%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@_hennessy_/JAVA-%ED%8E%98%EC%96%B4%EC%BD%94%EB%94%A9-1%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Sat, 12 Nov 2022 00:37:52 GMT</pubDate>
            <description><![CDATA[<h2 id="java-스터디-시작">Java 스터디 시작!</h2>
<p>혼자서 코딩연습하는 것도 의미가 있지만, 여럿이서 하는 것도 문제에 대한 접근 방식을 폭넓힐 수 있을 것 같아서 스터디에 참여하게 되었다.</p>
<p>기초적인 문제들도 버벅대는 나인지라...
잘 할 수 있을까...가 제일 걱정이었다. 그래도 혼자서 낑낑대면서 하는 것 보단 좀 덜 답답(?)할 것 같아서
어쨌든 한번 해보자고~! 하면서 시작했다.</p>
<p><img src="https://velog.velcdn.com/images/_hennessy_/post/beedece0-cbd3-4c0d-bbb8-6fbfea6e30f1/image.gif" alt=""></p>
<h2 id="페어코딩-그게-뭔데">페어코딩? 그게 뭔데</h2>
<p>뭐 맨처음엔 그냥 쌍으로 이뤄서 의견 나눠서 코딩하는건 줄 알았는데
한명이 코드 작성을 드라이브 하고 한명이 그 코드를 작성하면서 하는 방식이었다.</p>
<p>우리는 처음 스터디 시작한거라 페어로 한게 아니라 그냥 단체로 했다...
한명씩 돌아가면서 네비게이터를 하고, 스터디장님께서 드라이브를 하셨다.
그 다음에는 스터디장님께서 네비게이터를 하고 돌아가면서 코드를 작성하는 방식으로 했다.</p>
<p>그 때까진 이 베타 테스트가 예정 30분이었던 스터디시간을 훌쩍 넘어...
2시간 30분동안 모두를 헤매게 할지 몰랐다...
<img src="https://velog.velcdn.com/images/_hennessy_/post/f976fb15-60e0-49ba-b29c-d07c4b41431a/image.gif" alt="">
살려줘.........</p>
<h2 id="1일차-문제">1일차 문제</h2>
<h3 id=""></h3>
<ul>
<li>n명의 참가자가 있다.</li>
<li>m개의 팀으로 나눌 수 있다.</li>
<li>n,m 참가자의 이름을 입력받을 수 있다.(n과 참가자의 수는 동일해야 한다.)</li>
<li>팀의 수를 고르게 분배하고, 참가 인원은 입력받은 팀의 수로 나눌 수 있어야 한다.
(이것도 하다가 팀원들끼리 타협한 조건이었다.ㅋㅋ원래는 안나눠져도 되는데 앞의 팀부터 1씩 더한다는 조건이 있었다....저기요....스터디장님...?오늘 처음이자나요 ㅠㅠㅠㅠ)
<img src="https://velog.velcdn.com/images/_hennessy_/post/fa1b65d6-cdbf-4216-a3d0-264f9a3497fc/image.gif" alt=""></li>
</ul>
<p>그렇게 처음으로 내가 네비게이터를 하면서 진행됐다.
다같이 머리를 싸매고 결국 해결한 방법은 두가지!</p>
<p>HashMap과 이차원배열이었다..
근데 결국 나만 못풀었다. 워낙 늦은시간(11시)이기도 했고 너무 졸렸고.....하루종일 코딩만 붙잡고 있으니 머리가 잘 안굴러갔따 ㅋㅋㅋㅋ변명아님 ㅠ 암튼 아래는 해시맵 접근 방법에 대해서 한번 리뷰해보려고 한다.</p>
<h4 id="해시맵을-이용한-접근">해시맵을 이용한 접근</h4>
<pre><code>import java.util.*;</code></pre><ul>
<li>내가 먼저 네비게이터해서 젤 쉬운거 한 것 같다 ㅋㅋㅋㅋ잘 할 수 있는게 입력부분밖에 없다고요...
그런데 여기서 나는 당연히 뭐 이거저거 쓸 거 같으면 util.*;로
전체를 긁어와서 쓰는게 편하다고 생각했는데...
그렇게 쓰면 안쓰는 유틸까지 다 끌어와서 결론적으로 프로그램, 메모리가 무거워질 수 있다고....
새로운 사실을 알았다....</li>
</ul>
<pre><code>package main.java;
import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int member;
        int team;

        // 입력받고 조건에 맞지 않으면 다시 입력받기
        do {
            System.out.print(&quot;참가인원 수를 입력해 주세요.(0 이상의 정수): &quot;);
            member = scanner.nextInt();
            System.out.print(&quot;팀의 갯수를 입력해 주세요.(0 이상의 정수, 참가인원이 나누어 떨어지는 수): &quot;);
            team = scanner.nextInt();
            if (member == 0 || team == 0 || member % team != 0) {
                System.out.println(&quot;0을 입력하셨거나, 나누어 떨어지지 않는 수를 입력하셨습니다&quot;);
            }
        } while (member == 0 || team == 0 || member % team != 0);
</code></pre><ul>
<li>이렇게 일단 우리가 입력해야할 변수들을 선언하고 do While문으로 들어갔다.
나는 사실 처음에 do While이 아니라</li>
</ul>
<pre><code>while(team % member !=){
System.out.println(&quot;0을 입력하셨거나, 나누어 떨어지지 않는 수를 입력하셨습니다&quot;&quot;)

System.out.print(&quot;참가인원 수를 입력해 주세요.(0 이상의 정수): &quot;);
member = scanner.nextInt();

System.out.print(&quot;팀의 갯수를 입력해 주세요.(0 이상의 정수, 참가인원이 나누어 떨어지는 수): &quot;);
team = scanner.nextInt();}</code></pre><p>뭐이런식으로 생각을 했다. 아직 내가 초심자라 그런가 ㅋㅋㅋ내가 짠 게 더 예뻐보인다....(줄 정리의 위력)
암튼 이렇게 뭐 도입부는 어떻게 했다. 그런데 그 이후부터가 우리를 구렁텅이로 밀어넣었음.ㅋㅋㅋ
<img src="https://velog.velcdn.com/images/_hennessy_/post/29ae9f72-8524-4c84-8bdd-7e18a84c555e/image.gif" alt=""></p>
<h4 id="팀에-멤버를-분배하여-각-멤버의-이름과-팀을-어떻게-출력할-것인가">팀에 멤버를 분배하여 각 멤버의 이름과 팀을 어떻게 출력할 것인가?</h4>
<p>그래서 우리는 해시맵으로 접근을 했다.</p>
<pre><code>        HashMap&lt;Integer, String&gt; memberList = new HashMap&lt;&gt;();

        String memberName;
        for (int i = 0; i &lt; member; i++) {
            memberName = scanner.next();
            for (int j = 0; j &lt; team; j++) {
                memberList.put(j, memberName);
            }
        }
        System.out.print(memberList);</code></pre><p>이렇게 해서 해시맵으로 짝을 지어서 출력하려고 했다.
그래서 해시맵 변수도 만들고 돌렸으나....
member의 변수만큼 (각 이름 입력) + 팀의 갯수만큼 j가 돌아가는데 
이렇게 하면 j가 만약 2였다고 치면,  [0, 1, 2] 이렇게 돌아가면서
memberName에는 마지막정보가 계속 덮어 씌워지게 되는 것이었다.
뭐 예를들면 1번팀에 [김철수, 김영희]가 있다면 i첫번째에서 김철수가 입력됐으니
1번팀에도 김철수..
2번팀에도 김철수...
3번팀에도 김철수...... 이렇게 되면서 계속 덮어써진다고 해야하나?
이거때문에 결국 2시간 반 걸린거다.ㅋㅋㅋ
<img src="https://velog.velcdn.com/images/_hennessy_/post/997ecd11-2ff8-46d4-9ac9-52cc0c44682c/image.gif" alt=""></p>
<p>약간 여기서 해결해야 한다는? 그런 생각에 씌여서 뭔가 다른 방식으로 해결할 생각을 못한 것 같다.
참 이런부분 내가 느낀점은 가능성에 대해서 곰곰히 생각해보아야 한다는 것 .
내가 처음 생각한 아이디어가 틀리다? 그럼 그걸 과감히 버리고 갈 필요도 있는 것이다.</p>
<p>수정해서 좋은거 얻을 가능성을 생각하는 것도 중요하지만..
내가 이 틀에 나의 생각, 방향이 갇혀있는 것이 아닌지를 고민해봐야겠다는 생각이 들었다.</p>
<p>결국 코딩도 창의적 행위가 아닐까 ㅋㅋㅋ 발상? 생각의 폭이 중요하다는 것을 새삼 깨달음...
<img src="https://velog.velcdn.com/images/_hennessy_/post/72a507ea-86fb-4131-87e4-f94b0209eeae/image.gif" alt=""></p>
<p>아무튼 이부분은 먼저 member의 갯수만큼의 길이의 배열을 만들고 팀이름을 붙이는 방식으로 하고 ==&gt; 랜덤으로 만들기 위해 팀번호를 뒤섞는다...==&gt;이후 랜덤으로 섞인 팀 번호에 순서대로 참가자를 입력해서 출력 (사실 내가 한건 아니라서 했다고 하긴 뭐하지만...)
코드로 보면</p>
<pre><code>        // 랜덤한 팀 설정을 위하여, 입력받은 참가인원 수 길이의 배열 생성후 각각 팀번호 입력
        ArrayList&lt;Integer&gt; nums = new ArrayList&lt;&gt;();
        for (int i = 1; i &lt;= team; i++) {
            for (int j = 0; j &lt; member / team; j++) {
                nums.add(i);
            }
        }</code></pre><ul>
<li>여기서는 num이라는 배열 변수 만들고,</li>
<li>team의 수만큼 돌리는데 </li>
<li>이때 j는 각 팀의 멤버수만큼 돌아가고, 그동안 num배열에 i를 입력하겠단거</li>
<li>그럼 뭐 멤버수가 2명씩이면
[1, 1, 2, 2] 이렇게 배열생기는거네....</li>
</ul>
<p>(지금 이거 쓰면서 이해함 .......)</p>
<pre><code>        // 팀 번호 셔플
        Collections.shuffle(nums);

        // 셔플한 팀번호 배열에 순서대로 참가자 입력받아서 입력
        HashMap&lt;String, Integer&gt; memberList = new HashMap&lt;&gt;();
        for (int i = 0; i &lt; nums.size(); i++) {
            System.out.print((i + 1) + &quot; 번째 참가자의 이름을 입력해 주세요: &quot;);
            String memberName = scanner.next();
            memberList.put(memberName, nums.get(i));
        }</code></pre><p>그다음에 이거 함 섞어주고(랜덤으로 하려고)
memberList(해시맵) 선언 후..
1번째 참가자부터니까 i+1부터 입력부분을 포문 돌린다.
그리고 나서 입력한 내용을 nums배열의 i번째 인덱스로 넣는다.
(이 nums배열은 랜덤을 돌렸으니 팀이 랜덤으로 되는 것과 같은 효과인 것이다....)</p>
<pre><code>// 해시맵에 value 기준으로 정렬해서 프린트 찍어보기
        System.out.println();
        List&lt;Map.Entry&lt;String, Integer&gt;&gt; entries = memberList.entrySet().stream()
                .sorted(Map.Entry.comparingByValue())
                .collect(Collectors.toList());
        for (Map.Entry&lt;String, Integer&gt; entry : entries) {
            System.out.printf(&quot;%s 님은 %d 번팀 %n&quot;, entry.getKey(), entry.getValue());
        }

    }
}</code></pre><p>출력 짜잔...근데 이 출력 부분은 내가 모르는게 많아서 좀 더 공부해야할 것 같음....entry는 뭔데? stream은 또 뭐야,,,,저 맨아래 포문은 &quot;향상된 포문&quot; 이란 것인가...?</p>
<p>암튼 오늘 과제 하고 시간되면 쉐도우 코딩 한번 해야겠다...나는  어제 이걸 수행하지 못했기 때문에,,,, 이렇게도 해보고 어제 이차원 배열로 하신 분도 계신데 그렇게도 한번 해봐야겠다..</p>
<h2 id="스터디-베타테스트-후기-끗">스터디 베타테스트 후기 끗~!</h2>
]]></description>
        </item>
    </channel>
</rss>