<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Kitsun3.log</title>
        <link>https://velog.io/</link>
        <description>HELLO</description>
        <lastBuildDate>Mon, 27 Jan 2025 16:43:42 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Kitsun3.log</title>
            <url>https://velog.velcdn.com/images/winy3ori_/profile/11c7f2b9-1a6d-4c64-b96e-c1255fe3dbf7/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Kitsun3.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/winy3ori_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Java] #백준 1157 단어공부]]></title>
            <link>https://velog.io/@winy3ori_/java-%EB%B0%B1%EC%A4%80-1157%EB%B2%88-%EB%8B%A8%EC%96%B4%EA%B3%B5%EB%B6%80</link>
            <guid>https://velog.io/@winy3ori_/java-%EB%B0%B1%EC%A4%80-1157%EB%B2%88-%EB%8B%A8%EC%96%B4%EA%B3%B5%EB%B6%80</guid>
            <pubDate>Mon, 27 Jan 2025 16:43:42 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/winy3ori_/post/fea4e1df-5e5c-4172-a0ac-dceb39a5f259/image.png" alt=""></p>
<hr>
<h3 id="📌-고려사항">📌 고려사항</h3>
<p>기본적으로 백준 문제를 풀 때 간결화 된 코드보다 가독성 좋은 코드를 1순위로 생각하고 작성한다.</p>
<p><code>HashMap</code> 을 사용해 실제 포함된 알파벳만 추려서 구하는게 가독성 측면에서 좋을 것 같았다.
(사실 그것보다 아직까지는 시간까지 고려할 수준이 안된다...)</p>
<hr>
<h3 id="작성코드">작성코드</h3>
<pre><code class="language-java">import java.io.*;
import java.util.*;

public class Main {

    public static void solution() throws IOException {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
            String word = br.readLine().toUpperCase();
            Map&lt;Character, Integer&gt; count = new HashMap&lt;&gt;();

            for (char c : word.toCharArray()) {
                count.put(c, count.getOrDefault(c, 0) + 1);
            }

            int maxCount = 0;
            char res = &#39;?&#39;;

            for (Map.Entry&lt;Character, Integer&gt; entry : count.entrySet()) {
                if (entry.getValue() &gt; maxCount) {
                    res = entry.getKey();
                    maxCount = entry.getValue();
                } else if (entry.getValue() == maxCount) {
                    res = &#39;?&#39;;
                }
            }
            System.out.println(res);
        }
    }

    public static void main(String[] args) throws IOException {
        solution();
    }
}</code></pre>
<hr>
<p>먼저  결과값이 대문자로 반환되어야 하므로 <code>toUpperCase</code> 로 대문자 변환을 진행했다.</p>
<p><code>getOrDefault</code> 를 사용해 <code>HashMap</code> 에 key의 존재 여부에 따라 value에 변화를 주도록 했다.</p>
<p>각 key, value의 쌍인 <code>Entry</code> 를 가져와 순회 후 가장 높은 빈도의 key를 구한다.</p>
<hr>
<h3 id="개선방향">개선방향</h3>
<p>대부분의 사람들은 ASCII 코드를 사용해서 사이클을 돌려 알파벳 빈도를 구하는 방식을 사용했는데 이유를 알아보니 처리 시간과 메모리 사용량에서 장점을 보인다.</p>
<p>난 ASCII 코드를 사용할 생각 조차 못했는데 이 부분은 그냥 문제를 많이 풀어봐야 알 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 백준 #25206 너의 평점은]]></title>
            <link>https://velog.io/@winy3ori_/Java-%EB%B0%B1%EC%A4%80-25206-%EB%84%88%EC%9D%98-%ED%8F%89%EC%A0%90%EC%9D%80</link>
            <guid>https://velog.io/@winy3ori_/Java-%EB%B0%B1%EC%A4%80-25206-%EB%84%88%EC%9D%98-%ED%8F%89%EC%A0%90%EC%9D%80</guid>
            <pubDate>Mon, 20 Jan 2025 13:58:36 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/winy3ori_/post/2b28f8ca-5d52-4b1c-871f-139106754bb4/image.png" alt=""></p>
<hr>
<h3 id="처음풀이">처음풀이</h3>
<pre><code class="language-java">import java.io.*;
import java.util.StringTokenizer;

public class Main {

    public static void solution() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String str[] = new String[20];
        String gradeList[] = {&quot;A+&quot;, &quot;A0&quot;, &quot;B+&quot;, &quot;B0&quot;, &quot;C+&quot;, &quot;C0&quot;, &quot;D+&quot;, &quot;D0&quot;, &quot;F&quot;, &quot;P&quot;};
        double gradeScore[] = {4.5, 4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.0, 0.0, 0.0};

        double totalSum = 0;
        double scoreSum = 0;

        for (int i = 0; i &lt; 20; i++) {
            str[i] = br.readLine(); // 한 줄 입력 받고
            StringTokenizer st = new StringTokenizer(str[i], &quot; &quot;);  
            String subject = st.nextToken(); // 과목명
            double score = Double.parseDouble(st.nextToken()); // 학점
            String grade = st.nextToken(); // 점수

            for (int j = 0; j &lt; 10; j++) {
                if (grade.equals(gradeList[j])) {
                    totalSum += score * gradeScore[j];
                    if (j != 9) {   // Pass 과목 총 학점에서 제외
                        scoreSum += score;
                    }
                }
            }
        }

        double average = totalSum/scoreSum;
        System.out.printf(&quot;%.6f\n&quot;, average);
        br.close();

    }

    public static void main(String[] args) throws IOException {
        solution();
    }
}
</code></pre>
<p>학점과 성적을 담을 리스트를 만들고 20줄의 입력을 받기위한 반복문을 작성했다.
<code>StringTokenizer</code> 을 이용해 공백을 기준으로 구분 후 과목명, 학점, 점수를 분리해 계산했다.</p>
<hr>
<h3 id="💡-문제점">💡 문제점</h3>
<p>학점과 성적을 매핑하는데 리스트를 사용해서 코드가 복잡해보였다.</p>
<p>또한 반복문이 두 번 들어가서 불필요하게 보였다.</p>
<hr>
<h3 id="최종풀이">최종풀이</h3>
<pre><code class="language-java">import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

public class Main {

    private static final int SUBJECT_COUNT = 20;

    public static void solution() throws IOException {
        Map&lt;String, Double&gt; gradeMap = new HashMap&lt;&gt;();
        gradeMap.put(&quot;A+&quot;, 4.5);
        gradeMap.put(&quot;A0&quot;, 4.0);
        gradeMap.put(&quot;B+&quot;, 3.5);
        gradeMap.put(&quot;B0&quot;, 3.0);
        gradeMap.put(&quot;C+&quot;, 2.5);
        gradeMap.put(&quot;C0&quot;, 2.0);
        gradeMap.put(&quot;D+&quot;, 1.5);
        gradeMap.put(&quot;D0&quot;, 1.0);
        gradeMap.put(&quot;F&quot;, 0.0);
        gradeMap.put(&quot;P&quot;, 0.0);

        double totalSum = 0.0; // 총 점수 (학점 * 성적)
        double scoreSum = 0.0; // 총 학점

        try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
            for (int i = 0; i &lt; SUBJECT_COUNT; i++) {
                String line = br.readLine();
                StringTokenizer st = new StringTokenizer(line, &quot; &quot;);

                String subject = st.nextToken(); // 과목명
                double score = Double.parseDouble(st.nextToken()); // 학점
                String grade = st.nextToken(); // 성적

                double gradeValue = gradeMap.get(grade);
                totalSum += score * gradeValue;

                if (!grade.equals(&quot;P&quot;)) {
                    scoreSum += score;
                }
            }
        }

        double average = totalSum / scoreSum;
        System.out.printf(&quot;%.6f\n&quot;, average);
    }

    public static void main(String[] args) throws IOException {
        solution();
    }
}
</code></pre>
<hr>
<h3 id="개선방향">개선방향</h3>
<p>HashMap을 사용해 성적과 점수를 매핑하여 가독성과 효율성을 높였다.</p>
<p><code>BufferdReader</code> 사용시 명시적으로 <code>close()</code> 사용하는 대신 try-with-resources를 사용해 자원 관리를 간소화했다.
(이 부분은 나중에 따로 다뤄 보도록 하겠다.)</p>
<p>또한 상수를 사용해 가독성과 유지보수성을 향상했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 백준 #10950 A+B - 3]]></title>
            <link>https://velog.io/@winy3ori_/%EB%B0%B1%EC%A4%80-10950-AB-3-java</link>
            <guid>https://velog.io/@winy3ori_/%EB%B0%B1%EC%A4%80-10950-AB-3-java</guid>
            <pubDate>Fri, 17 Jan 2025 15:52:47 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/winy3ori_/post/331d919f-8478-410b-8998-aca04b327805/image.png" alt=""></p>
<p>A와 B를 입력받아 그 합을 출력하는 간단한 문제입니다.
효율적인 입출력을 위해 기존의 <code>Scanner</code>와 <code>split()</code> 대신, <code>BufferedReader</code> 와 <code>StringTokenizer</code> 를 활용한 새로운 접근을 시도해 보았습니다.</p>
<hr>
<h3 id="왜-bufferedreader를-선택했는가">왜 BufferedReader를 선택했는가?</h3>
<p>자주 사용하던 <code>Scanner</code> 클래스는 편리한 입력 처리 기능을 제공하지만, 상대적으로 느린 속도를 가지고 있습니다.
이는 <strong>입출력 처리 과정에서 동기화(synchronization)</strong>가 발생하기 때문인데요, 데이터가 많은 경우 실행 속도에 영향을 줄 수 있습니다.</p>
<p>반면, <code>BufferedReader</code> 는 버퍼(buffer)를 사용하여 데이터를 읽기 때문에 훨씬 빠른 속도를 제공합니다.
특히, 반복적으로 많은 데이터를 입력받고 처리해야 하는 문제에서는 그 차이가 더욱 두드러집니다.</p>
<hr>
<h3 id="왜-stringtokenizer를-선택했는가">왜 StringTokenizer를 선택했는가?</h3>
<p>문자열을 특정 구분자(예: 공백, 콤마 등)로 나누는 작업에서 흔히 사용되는 <code>split()</code> 메서드는 내부적으로 <strong>정규표현식(Regular Expression)</strong>을 사용합니다. 이로 인해 코드가 간단해지는 장점이 있지만, 처리 속도가 느릴 수 있습니다.</p>
<p>반면, <code>StringTokenizer</code>는 단순한 구분자 처리에 특화되어 있어 더 빠르고 메모리 효율적입니다. 
따라서, 문자열 분리가 단순한 문제에서는 <code>split()</code>보다 <code>StringTokenizer</code>를 사용하는 것이 유리합니다.</p>
<hr>
<h3 id="풀이">풀이</h3>
<pre><code class="language-java">import java.io.*;
import java.util.StringTokenizer;

public class Main {

    public static void solution() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int count = Integer.parseInt(br.readLine());

        StringTokenizer st;
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i &lt; count; i++) {
            st = new StringTokenizer(br.readLine(), &quot; &quot;);   // 각 줄을 공백으로 분리
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            sb.append(a + b).append(&quot;\n&quot;);
        }

        br.close();
        System.out.println(sb);

    }

    public static void main(String[] args) throws IOException {
        solution();
    }
}
</code></pre>
<hr>
<h3 id="느낀-점-및-개선-가능성">느낀 점 및 개선 가능성</h3>
<ul>
<li>이번 문제에서는 효율적인 입출력 처리가 중요하지 않을 수도 있지만, 대규모 데이터 처리가 필요한 경우 이러한 최적화는 매우 유의미한 차이를 만들어낼 수 있습니다.</li>
<li>또한, <code>split()</code>과 <code>Scanner</code>가 편리하다는 이유로 습관적으로 사용했지만, 효율성을 고려한 선택이 더 나은 코드로 이어진다는 점을 다시 한번 깨닫게 되었습니다.</li>
<li>다만, 입력 데이터가 복잡한 구분자를 포함하거나 정규표현식을 사용하는 경우에는 여전히 <code>split()</code>이 더 적합할 수 있으므로 상황에 맞는 도구를 선택하는 것이 중요합니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[macOS에서 Oracle DB 사용 방법]]></title>
            <link>https://velog.io/@winy3ori_/Mac-OS%EC%97%90%EC%84%9C-Oracle-DB-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@winy3ori_/Mac-OS%EC%97%90%EC%84%9C-Oracle-DB-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Fri, 12 Jan 2024 03:23:28 GMT</pubDate>
            <description><![CDATA[<p>Mac OS에서 Oracle DB 사용을 위해 필요한 절차</p>
<h3 id="colima-설치">Colima 설치</h3>
<blockquote>
<p>💡 Colima는 무거운 Docker Desktop을 대신해 간단한 CLI 환경에서 도커 컨테이너들을 실행할 수 있는 오픈 소스 S/W</p>
</blockquote>
<pre><code>brew install colima</code></pre><p><br><br></p>
<h3 id="docker-설치">Docker 설치</h3>
<p>Docker 홈페이지에서 Docker Desktop 설치
만약 Docker Engine만 설치하고 싶은 경우 brew로 도커 엔진만 설치 가능</p>
<pre><code>brew install docker</code></pre><p><br><br></p>
<h3 id="colima-실행">Colima 실행</h3>
<p>colima를 x86_64 환경으로 띄워준다.</p>
<pre><code>colima start --memory 4 --arch x86_64
</code></pre><p><code>docker ps</code> 명령어를 사용해 작동 확인
<br><br></p>
<h3 id="docker-컨테이너-실행">Docker 컨테이너 실행</h3>
<pre><code>docker run --restart unless-stopped --name oracle -e ORACLE_PASSWORD=pass -p 1521:1521 -d gvenzl/oracle-xe</code></pre><ul>
<li>--restart 옵션에서 <code>unless-stopped</code> 설정시 재부팅시 자동으로 Oracle DB 실행</li>
<li>-- name 옵션에서 이름 설정시 컨테이너 ID 대신 편한 이름 사용 가능<br>

</li>
</ul>
<p><code>docker ps</code> 로 Oracle 컨테이너가 떠있는 상태 확인</p>
<pre><code>docker logs -f oracle (컨테이너명)</code></pre><p><code>docker logs</code> 로 로그 확인시 &quot;DATABASES IS READY TO USE!&quot; 가 뜨면 성공</p>
<p><code>control(^) + c</code> 로 종료
<br><br></p>
<h3 id="sql-plus-실행">SQL Plus 실행</h3>
<pre><code>docker exec -it 컨테이너 이름 sqlplus</code></pre><p>user-name : system 
password : 설정값</p>
]]></description>
        </item>
    </channel>
</rss>