<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Channi Studies</title>
    <link>https://code-studies.tistory.com/</link>
    <description>공학 공부 블로그 입니다
Partially worked with English and Korean.</description>
    <language>ko</language>
    <pubDate>Sun, 5 Apr 2026 23:22:03 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Chan Lee</managingEditor>
    <image>
      <title>Channi Studies</title>
      <url>https://tistory1.daumcdn.net/tistory/6636578/attach/7a710509f31f44ef94d0484858f4c209</url>
      <link>https://code-studies.tistory.com</link>
    </image>
    <item>
      <title>Ordinary Least Squares (OLS)</title>
      <link>https://code-studies.tistory.com/192</link>
      <description>&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/kZGaN/dJMb9i2NnDp/4sek5OK9j1g89L8lW01Q2k/Week%207.pdf?attach=1&amp;amp;knm=tfile.pdf&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;Week 7.pdf&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;2.89MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Since I've started to use Obsidian for summarizing my leranings, I will upload the PDF of the note in this blog from now on.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;https://drive.google.com/file/d/1drGN-n_DeaUXCXe4e2y05UUWRgRVBL7n/preview&quot; width=&quot;750&quot; height=&quot;530&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://drive.google.com/open?id=1drGN-n_DeaUXCXe4e2y05UUWRgRVBL7n&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Open in new tab&lt;/a&gt;&lt;/p&gt;</description>
      <category>Data Science</category>
      <author>Chan Lee</author>
      <guid isPermaLink="true">https://code-studies.tistory.com/192</guid>
      <comments>https://code-studies.tistory.com/192#entry192comment</comments>
      <pubDate>Sat, 18 Oct 2025 06:18:18 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Stack with IntNode, two-stack reverse trick</title>
      <link>https://code-studies.tistory.com/191</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Let's try implementing a Stack in Java using IntNode.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The structure of IntNode looks like this:&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757278845175&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private static class IntNode() {
    int val;
    IntNode next;
    
    IntNode(int val, IntNode next) {
    	this.val = val;
        this.next = next;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;We're going to put this&amp;nbsp;&lt;i&gt;private static&amp;nbsp;&lt;/i&gt;IntNode class into the Stack class.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;We call it nested classes, and there are times when we should declare it as a&amp;nbsp;&lt;i&gt;static&amp;nbsp;&lt;/i&gt;or&amp;nbsp;&lt;i&gt;non-static&lt;/i&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Static vs. Non-Static&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Static variables in Java is a variable that is shared across all objects of a same class.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Similarly, static method is a method shared among all objects, and are expected to approach via the Class name. (e.g. Car.getFaster(car1, car2) rather than Ford.getFaster(Tesla, Toyota))&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;However,&amp;nbsp;&lt;i&gt;static class&amp;nbsp;&lt;/i&gt;is a little different.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;We declare an inner class&amp;nbsp;&lt;i&gt;static&amp;nbsp;&lt;/i&gt;when the inner class has an independent meaning, and&amp;nbsp;&lt;i&gt;non-static&amp;nbsp;&lt;/i&gt;otherwise.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If the nexted inner class NEVER uses any instance variables or methods of the outer class, declare it&amp;nbsp;&lt;i&gt;static&lt;/i&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;One analogy is a Car class.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There are distinct car parts for each car objects, such as wheel, window, engine, etc.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Those are parts of a car, unliked&amp;nbsp;&lt;i&gt;IntNodes&amp;nbsp;&lt;/i&gt;in a&amp;nbsp;&lt;i&gt;Stack&lt;/i&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;IntNode&lt;/i&gt;, which carry its integer value and pointer to next&amp;nbsp;&lt;i&gt;IntNode&lt;/i&gt;, has an independent meaning regardless of&amp;nbsp;&lt;i&gt;Stack&lt;/i&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IntNode is just a data container, it has no reason to be a part of a specific Stack instance (it's just one element.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In contrast, whell, window, etc are a PART of a car.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Understanding this, we can continue implementing Stack class with &lt;i&gt;static &lt;/i&gt;inner IntNode class.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1757279384625&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Stack {
    // Stack is Last In First Out
    private static class IntNode {
        int val;
        IntNode next;

        IntNode(int val, IntNode next) {
            this.val = val;
            this.next = next;
        }
    }

    private int size;
    // sentinel.next will work as the 'real' head node
    private IntNode sentinel;

    // Constructor with no value
    public Stack() {
        sentinel = new IntNode(0, null);
        size = 0;
    }

    // Constructor with 1 value
    public Stack(int val) {
        sentinel = new IntNode(0, null);
        sentinel.next = new IntNode(val, null);
        size = 1;
    }

    /**
     * Puts x on top of the stack.
     * Constant runtime.
     */
    public void push(int x) {
        sentinel.next = new IntNode(x, sentinel.next);
        size += 1;
    }

    /**
     * Removes and returns the top item of the stack.
     * Constant runtime.
     */
    public int pop() {
        int returnVal = sentinel.next.val;
        sentinel.next = sentinel.next.next;
        size -= 1;

        return returnVal;
    }

    /**
     * Returns the number of items on the stack.
     * Constant runtime.
     */
    public int size() {
        return size;
    }

    /**
     * Compute the sum of the numbers of the stack.
     * No runtime restrictions.
     */
    public int sum() {
        IntNode currentNode = sentinel.next;
        int result = 0;

        while (currentNode != null) {
            result += currentNode.val;
            currentNode = currentNode.next;
        }

        return result;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;We're using&amp;nbsp;&lt;i&gt;sentinel&amp;nbsp;&lt;/i&gt;private class variable as the head node.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;So the 'real' head node is at&amp;nbsp;&lt;i&gt;sentinel.next&lt;/i&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Now, say we want to implement a function that takes a single Stack, returning a reversed Stack, but in a different package. Since we declared all of the instance variables as private, we must use public methods to implement it.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757279564363&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class StackClient {
    /**
     * Approach:
     * Repeatedly .pop values from s, put into new Stack and return it until size is 0.
     */
    public static Stack flipped(Stack s) {
        Stack newStack = new Stack();

        while (s.size() != 0) {
            int val = s.pop();
            newStack.push(val);
        }

        return newStack;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;It works as intended, but it destroys the original stack by repeatedly calling &lt;i&gt;s.pop()&lt;/i&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If we could approach&amp;nbsp;&lt;i&gt;IntNode.next,&amp;nbsp;&lt;/i&gt;we could make it non-destructive..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;But we could fix the code slightly in order to keep the original Stack AND return the new one.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757279842350&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class StackClient {
    /**
     * Approach:
     * Repeatedly pop values from s, put into new Stack and return it until size is 0.
     */
    public static Stack flipped(Stack s) {
        Stack newStack = new Stack();
        Stack temp = new Stack();

        // 1. Make two reversed Stack, newStack and temp
        // s becomes empty stack after this
        while (s.size() != 0) {
            int val = s.pop();
            newStack.push(val);
            temp.push(val);
        }

        // 2. Reverse the temp Stack, and save to s
        while (temp.size() != 0) {
            int val = temp.pop();
            s.push(val);
        }
        
        return newStack;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;With this implementation, we could maintain the structure of the original Stack AND return the new reversed Stack.&amp;nbsp;&lt;/p&gt;</description>
      <category>Data Science/Data Structure &amp;amp; Algorithm</category>
      <author>Chan Lee</author>
      <guid isPermaLink="true">https://code-studies.tistory.com/191</guid>
      <comments>https://code-studies.tistory.com/191#entry191comment</comments>
      <pubDate>Mon, 8 Sep 2025 06:18:07 +0900</pubDate>
    </item>
    <item>
      <title>[Numpy] Numpy Basics (.ipynb)</title>
      <link>https://code-studies.tistory.com/190</link>
      <description>&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/sTUxb/dJMb9P7htcx/KjpkvzTlz6A9AKkjJ0dxP1/numpy.ipynb?attach=1&amp;amp;knm=tfile.ipynb&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;numpy.ipynb&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.06MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This Jupyter Notebook file tells you about the numpy array (&lt;i&gt;numpy.ndarray&lt;/i&gt;) basics.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Creating different shaped array, reshaping, random array, array indexing, etc.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2358&quot; data-origin-height=&quot;1294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dFKdT9/btsQeqHQMlX/WcKC3sye9VChd2AI4KMWI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dFKdT9/btsQeqHQMlX/WcKC3sye9VChd2AI4KMWI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dFKdT9/btsQeqHQMlX/WcKC3sye9VChd2AI4KMWI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdFKdT9%2FbtsQeqHQMlX%2FWcKC3sye9VChd2AI4KMWI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2358&quot; height=&quot;1294&quot; data-origin-width=&quot;2358&quot; data-origin-height=&quot;1294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Data Science/Python</category>
      <author>Chan Lee</author>
      <guid isPermaLink="true">https://code-studies.tistory.com/190</guid>
      <comments>https://code-studies.tistory.com/190#entry190comment</comments>
      <pubDate>Mon, 1 Sep 2025 04:49:54 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Generic Types of List</title>
      <link>https://code-studies.tistory.com/189</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;To create an ArrayList (or LinkedList) in Java, you can do as following:&lt;/p&gt;
&lt;pre id=&quot;code_1756581473170&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List myList = new ArrayList();

        myList.add(10);
        myList.add(&quot;Go&quot;);
        myList.add(false);

        System.out.println(myList); // [10, Go, false]
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If we do not specify the type of the elements in the List, we can put different types in the List like we did in Python.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Since we can put whatever we want, possible runtime errors can occur dealing with types.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;However, there are multiple reasons why we use generics specified within angle brackets (or diamond operator, &amp;lt;&amp;gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;One problem that might arise in such situation is incompatible type error when assigning an element to&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1756581986006&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List myList = new ArrayList();

        myList.add(10);
        myList.add(&quot;Go&quot;);
        myList.add(false);

        int firstNum = myList.get(0); // Compile Error
        // java: incompatible types: java.lang.Object cannot be converted to int
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This error occurs same for &lt;i&gt;&quot;Go&quot;&lt;/i&gt; and &lt;i&gt;false.&amp;nbsp;&lt;/i&gt;Why does this happen?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;It happens because we didn't specified generic type of the List, resulting EVERY elements getting returned to have&amp;nbsp;&lt;i&gt;Object (java.util.Object) &lt;/i&gt;type, which is the superclass of every class in Java.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In other words, ANY classes that you define automatically inherits from&amp;nbsp;&lt;i&gt;java.util.Object&amp;nbsp;&lt;/i&gt;class.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Since the generic type hasn't provided, Java returns every object in&amp;nbsp;&lt;i&gt;Object&amp;nbsp;&lt;/i&gt;type.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Although specifying type is safer, we can still use the code if we add type casting.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;Object&amp;nbsp;&lt;/i&gt;type will be converted to our desired types with appropriate type casting.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;For example:&lt;/p&gt;
&lt;pre id=&quot;code_1756582469081&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List myList = new ArrayList();

        myList.add(10);
        myList.add(&quot;Go&quot;);
        myList.add(false);

        int firstNum = (Integer) myList.get(0);
        String secondStr = (String) myList.get(1);
        boolean thirdBool = (boolean) myList.get(2);

        System.out.println(firstNum + &quot;, &quot; + secondStr + &quot;, &quot; + thirdBool);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Now, there is another weird problem when you try to make a List of integers. (with generics)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRGvTe/btsQdVamoVI/uqujvBKc2eKxZPRvVE17LK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRGvTe/btsQdVamoVI/uqujvBKc2eKxZPRvVE17LK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRGvTe/btsQdVamoVI/uqujvBKc2eKxZPRvVE17LK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRGvTe%2FbtsQdVamoVI%2FuqujvBKc2eKxZPRvVE17LK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1274&quot; height=&quot;514&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;514&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;My compiler shows&amp;nbsp;&lt;i&gt;&quot;Type argument cannot be of a &lt;b&gt;primitive type&lt;/b&gt;&quot;&amp;nbsp;&lt;/i&gt;on integer.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Like other programming languages, Java have some primitive types&amp;ndash;byte, short, int, long, float, double, boolean, and char.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Those primitive types are NOT objects, while &lt;b&gt;generic system requires objects&lt;/b&gt;. So you must only put objects inside the diamond operator (&amp;lt;&amp;gt;).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Then, what should we do in such situation?&amp;nbsp;There are something called &lt;b&gt;wrapper class &lt;/b&gt;corresponding to each data type.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ex)&lt;i&gt; int &amp;rarr; Integer, double &lt;i&gt;&amp;rarr; Double, boolean &lt;i&gt;&amp;rarr; Boolean, etc&lt;/i&gt;&lt;/i&gt;&lt;/i&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756583082514&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List&amp;lt;Integer&amp;gt; myList = new ArrayList&amp;lt;&amp;gt;();
        List&amp;lt;Double&amp;gt; secondList = new LinkedList&amp;lt;&amp;gt;();

        myList.add(1);
        myList.add(2);
        myList.add(3);
        System.out.println(myList);

        secondList.add(2.0);
        secondList.add(2.5);
        secondList.add(-3.141592);
        System.out.println(secondList);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1518&quot; data-origin-height=&quot;356&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSPM0l/btsQcpJIsZU/VUp2i1yCTJGM43tV7qFhW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSPM0l/btsQcpJIsZU/VUp2i1yCTJGM43tV7qFhW1/img.png&quot; data-alt=&quot;Result&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSPM0l/btsQcpJIsZU/VUp2i1yCTJGM43tV7qFhW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSPM0l%2FbtsQcpJIsZU%2FVUp2i1yCTJGM43tV7qFhW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;745&quot; height=&quot;175&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1518&quot; data-origin-height=&quot;356&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Result&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Data Science/Data Structure &amp;amp; Algorithm</category>
      <author>Chan Lee</author>
      <guid isPermaLink="true">https://code-studies.tistory.com/189</guid>
      <comments>https://code-studies.tistory.com/189#entry189comment</comments>
      <pubDate>Sun, 31 Aug 2025 04:46:09 +0900</pubDate>
    </item>
    <item>
      <title>Data Science case study - Systematic Racial Discrimination in Tax Audit</title>
      <link>https://code-studies.tistory.com/188</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Let's go through a case study of data science to understand what is it about.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1756503916097&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Black Americans Are Much More Likely to Face Tax Audits, Study Finds (Published 2023)&quot; data-og-description=&quot;A new report documents systemic discrimination in how the I.R.S. selects taxpayers to be audited, with implications for a debate on the agency&amp;rsquo;s funding.&quot; data-og-host=&quot;www.nytimes.com&quot; data-og-source-url=&quot;https://www.nytimes.com/2023/01/31/us/politics/black-americans-irs-tax-audits.html&quot; data-og-url=&quot;https://www.nytimes.com/2023/01/31/us/politics/black-americans-irs-tax-audits.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bmAWeo/hyZC4bjUAg/jyxBDErI35Fy5uKKkOyD0k/img.jpg?width=1050&amp;amp;height=550&amp;amp;face=0_0_1050_550,https://scrap.kakaocdn.net/dn/HMvAH/hyZGhUouKa/s3OtYqtcuvxQzWxa9sTze1/img.jpg?width=3000&amp;amp;height=1688&amp;amp;face=0_0_3000_1688,https://scrap.kakaocdn.net/dn/O1zLu/hyZGnNQr2X/0hd0PRssDj2HoaX3vDyWN0/img.jpg?width=600&amp;amp;height=400&amp;amp;face=0_0_600_400&quot;&gt;&lt;a href=&quot;https://www.nytimes.com/2023/01/31/us/politics/black-americans-irs-tax-audits.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.nytimes.com/2023/01/31/us/politics/black-americans-irs-tax-audits.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bmAWeo/hyZC4bjUAg/jyxBDErI35Fy5uKKkOyD0k/img.jpg?width=1050&amp;amp;height=550&amp;amp;face=0_0_1050_550,https://scrap.kakaocdn.net/dn/HMvAH/hyZGhUouKa/s3OtYqtcuvxQzWxa9sTze1/img.jpg?width=3000&amp;amp;height=1688&amp;amp;face=0_0_3000_1688,https://scrap.kakaocdn.net/dn/O1zLu/hyZGnNQr2X/0hd0PRssDj2HoaX3vDyWN0/img.jpg?width=600&amp;amp;height=400&amp;amp;face=0_0_600_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Black Americans Are Much More Likely to Face Tax Audits, Study Finds (Published 2023)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A new report documents systemic discrimination in how the I.R.S. selects taxpayers to be audited, with implications for a debate on the agency&amp;rsquo;s funding.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.nytimes.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;New York times reported said that the IRS seems to be exhibiting systemic discrimination regarding tax audit (세무 조사) somehow. (Jan, 2023)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;However, the mystery is that tax payers never report their race to IRS in any way. Race is not reported anywhere in tax return.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Then how can this happen?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Initial Research Question&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;What are audit rates of Black and non-Black taxpayers?&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;X%&lt;/b&gt; of tax returns of &lt;b&gt;Black&lt;/b&gt; taxpayers were audited.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Y%&lt;/b&gt; of tax returns of &lt;b&gt;non-Black&lt;/b&gt; taxpayers were audited.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q. Human Context: What does this comparison matter? What is implied by X &amp;ne; Y?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q. Core Component of DS: Calculations across groups. (simple for this example, but require multiple analyses for larger data)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q. How do we know who was audited?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A. Data obtained from IRS. Obtained from partnership between researchers and the IRS.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;How do we determine the race of each taxpayer? &lt;b&gt;We can't.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Could we make an informed&amp;nbsp;&lt;b&gt;prediction &lt;/b&gt;of taxpayer's race?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3330&quot; data-origin-height=&quot;1116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7OC64/btsQeoQot6I/jDYNGi5Jk55jJRkrsE31hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7OC64/btsQeoQot6I/jDYNGi5Jk55jJRkrsE31hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7OC64/btsQeoQot6I/jDYNGi5Jk55jJRkrsE31hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7OC64%2FbtsQeoQot6I%2FjDYNGi5Jk55jJRkrsE31hk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3330&quot; height=&quot;1116&quot; data-origin-width=&quot;3330&quot; data-origin-height=&quot;1116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There is a difference in preference in their baby names in each race. Also, there is a difference in demographics for differenct cities. (more than 30% in SF, less than 20% in NY)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Drawing on external datasets, researchers estimated the probability that a taxpayer with a particular location + name identifies as Black.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciXGQD/btsQfC8eDyL/4dtkXX3amkkbcCHCnfKkK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciXGQD/btsQfC8eDyL/4dtkXX3amkkbcCHCnfKkK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciXGQD/btsQfC8eDyL/4dtkXX3amkkbcCHCnfKkK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciXGQD%2FbtsQfC8eDyL%2F4dtkXX3amkkbcCHCnfKkK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;570&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;570&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Then the result graph showing the audit rate against estimated probability of identifying as Black shows a strong pattern.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Taxpayers with a higher estimated probability of identifying as Black were more likely to be audited.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2042&quot; data-origin-height=&quot;1658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S05JY/btsQccjh6IK/fUlaMg1587LIYd9bY0X8C1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S05JY/btsQccjh6IK/fUlaMg1587LIYd9bY0X8C1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S05JY/btsQccjh6IK/fUlaMg1587LIYd9bY0X8C1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS05JY%2FbtsQccjh6IK%2FfUlaMg1587LIYd9bY0X8C1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;494&quot; height=&quot;401&quot; data-origin-width=&quot;2042&quot; data-origin-height=&quot;1658&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Now, plotting it against reported income and divide into two groups&amp;ndash;identifying as Black and Non-Black&amp;ndash;shows stark difference.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2046&quot; data-origin-height=&quot;1640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cV8Ych/btsQcYkBTkT/WIT7nXJ72I33C50YYyeAZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cV8Ych/btsQcYkBTkT/WIT7nXJ72I33C50YYyeAZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cV8Ych/btsQcYkBTkT/WIT7nXJ72I33C50YYyeAZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcV8Ych%2FbtsQcYkBTkT%2FWIT7nXJ72I33C50YYyeAZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;550&quot; height=&quot;441&quot; data-origin-width=&quot;2046&quot; data-origin-height=&quot;1640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Remembering IRS doesn't collect racial data, what are some possible reasons for this disparity?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Neighborhood? Address? Geography?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Identifying a Potential Root Cause&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2392&quot; data-origin-height=&quot;1202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v4g4r/btsQfDTAHro/EoyXVi3RZbCihJZEQ6Baik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v4g4r/btsQfDTAHro/EoyXVi3RZbCihJZEQ6Baik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v4g4r/btsQfDTAHro/EoyXVi3RZbCihJZEQ6Baik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv4g4r%2FbtsQfDTAHro%2FEoyXVi3RZbCihJZEQ6Baik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;601&quot; height=&quot;302&quot; data-origin-width=&quot;2392&quot; data-origin-height=&quot;1202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Taxpayers goes through a &quot;black-box&quot; algorithm that predicts the likelyhood that somebody has an error in their tax returns.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This algorithm seems to have prioritized catching &lt;b&gt;errors in claimed tax credits&lt;/b&gt; over catching errors that, if addressed, would recover the &lt;b&gt;most money&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Black taxpayers were&amp;nbsp;&lt;b&gt;more likely&lt;/b&gt; to file the kinds of returns targeted by the algorithm. Thus, audit rates of Black taxpayers were higher.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9 months after the original report was released, I.R.S. started to work on this to minimize the racial discrimination in tax audits.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 시스템적 인종 차별은 회계 감사의 대상 중 많은 양을 차지하는 것이 Earned Income Tax Credit (EITC) 신청이고, EITC는 중저소득층 계열에서 가장 큰 혜택을 볼 수 있기 때문이다. 중저소득층 (~$20,000)에 타 구간과 비교하여 확연히 많은 EITC 신청이 존재하며, 심지어 최대 혜택을 받을 수 있는 구간이기에 더욱 감사 비율이 높은 것으로 추정된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것이 흑인 대상 감사 비율이 높은 이유를 설명하는 이유는, 미국 사회의 인종별 소득 수준에는 인종간 차이가 존재하기 때문이다. 흑인의 평균 소득 수준이 전체 인종 그룹 중에서도 가장 낮기 때문에, EITC 신청의 비율 또한 가장 많고, 이것이 시스템적 인종 차별로 이어졌다는 추정이다.&amp;nbsp;&lt;/p&gt;</description>
      <category>Data Science/개념과 용어</category>
      <author>Chan Lee</author>
      <guid isPermaLink="true">https://code-studies.tistory.com/188</guid>
      <comments>https://code-studies.tistory.com/188#entry188comment</comments>
      <pubDate>Sat, 30 Aug 2025 07:52:47 +0900</pubDate>
    </item>
    <item>
      <title>nonlocal 변수</title>
      <link>https://code-studies.tistory.com/187</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Python 함수를 다룰 때에, nested function definition에서 inner function의 함수 프레임에서, 상위 프레임의 변수를 수정하려고 하면 오류가 발생합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n을 함수 인자로 받아, n번 특정 문자를 출력해주는 또 다른 함수를 반환하는&lt;i&gt;&amp;nbsp;print_n_times&lt;/i&gt; 함수에 대해서 알아보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1751512655474&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def print_n_times(n):
    def a(word):
        times = n
        while times:
            print(word)
            times -= 1

    return a
    
print_n_times(2)(&quot;hey&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최초 인자로 전달된 n (2)를 &lt;i&gt;times&lt;/i&gt; 라는 &lt;i&gt;a &lt;/i&gt;함수 내의 로컬 변수로 복사한 뒤, 해당 변수를 통해 while loop을 컨트롤 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같은 경우 의도된 대로 함수가 작동합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qZuOE/btsO2GECtiw/JqpyXQudiw4HVjz4mHhXw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qZuOE/btsO2GECtiw/JqpyXQudiw4HVjz4mHhXw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qZuOE/btsO2GECtiw/JqpyXQudiw4HVjz4mHhXw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqZuOE%2FbtsO2GECtiw%2FJqpyXQudiw4HVjz4mHhXw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;519&quot; height=&quot;105&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 만약&amp;nbsp;&lt;i&gt;a&amp;nbsp;&lt;/i&gt;함수 내에서 &lt;i&gt;times&lt;/i&gt; 로 복사하지 않고 &lt;i&gt;n&amp;nbsp;&lt;/i&gt;을 직접 변경하고자 하면 어떤 일이 발생할까요?&lt;/p&gt;
&lt;pre id=&quot;code_1751512780154&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def print_n_times(n):
    def a(word):
        while n:	# n 직접 접근
            print(word)
            n -= 1	# n 변경

    return a
    
print_n_times(2)(&quot;hey&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1660&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K32rz/btsO2ARQkWR/1j5zt7AlK91BkB4fIJW5Fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K32rz/btsO2ARQkWR/1j5zt7AlK91BkB4fIJW5Fk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K32rz/btsO2ARQkWR/1j5zt7AlK91BkB4fIJW5Fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK32rz%2FbtsO2ARQkWR%2F1j5zt7AlK91BkB4fIJW5Fk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1660&quot; height=&quot;254&quot; data-origin-width=&quot;1660&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인자 n에 대한 접근 권한은 최소 print_n_times 함수 또는 그 이상, 우리의 경우 글로벌 프레임에서만 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 점은 파이썬이 그렇게 디자인 되었기 때문이고 다른 언어에서는 또 다르게 작동할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 만약 의도적으로 상위 프레임의 인자를 변경하고자 한다면 어떻게 해야 할까요?&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1751512870688&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def print_n_times(n):
    def a(word):
        nonlocal n	# 추가
        while n:
            print(word)
            n -= 1

    return a


print_n_times(2)(&quot;hey&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzdCkP/btsO2W8g4A4/V8NWGqs3GXhtwu07YX1TB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzdCkP/btsO2W8g4A4/V8NWGqs3GXhtwu07YX1TB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzdCkP/btsO2W8g4A4/V8NWGqs3GXhtwu07YX1TB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzdCkP%2FbtsO2W8g4A4%2FV8NWGqs3GXhtwu07YX1TB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;622&quot; height=&quot;142&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용하고자 하는 하위 프레임 내에서 상위 프레임의 변수를 nonlocal로 지정하면 기존처럼 활용할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 안전하고 유지보수가 쉬운 코드를 디자인하기 위해서는 되도록이면 전달된 인자를 직접 사용하는 것 보다는 추가적 변수로 복사를 하고 해당 변수를 활용하는 것이 권장됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 경우에서는 직접적으로 변경하는 것이 요구될 수 있기 때문에, 숙지해 두면 좋겠습니다.&amp;nbsp;&lt;/p&gt;</description>
      <category>python</category>
      <author>Chan Lee</author>
      <guid isPermaLink="true">https://code-studies.tistory.com/187</guid>
      <comments>https://code-studies.tistory.com/187#entry187comment</comments>
      <pubDate>Thu, 3 Jul 2025 12:22:47 +0900</pubDate>
    </item>
    <item>
      <title>[Data Structure] Graph: Topological Sort</title>
      <link>https://code-studies.tistory.com/186</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;A&amp;nbsp;&lt;b&gt;topological sort&amp;nbsp;&lt;/b&gt;of a &lt;u&gt;directed, acyclic graph&lt;/u&gt; produces a list of graph's vertices such that for every edge from a vertex X to a vertex Y, X comes before Y in the list.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There can be more than one valid topoligcal sort. Again, the graph must be acyclic and riected in order to apply topological sorting.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;950&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yzgra/btsOeF8kJmg/xIR3Tb9fo3iQmU7Xx1qfbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yzgra/btsOeF8kJmg/xIR3Tb9fo3iQmU7Xx1qfbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yzgra/btsOeF8kJmg/xIR3Tb9fo3iQmU7Xx1qfbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyzgra%2FbtsOeF8kJmg%2FxIR3Tb9fo3iQmU7Xx1qfbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;543&quot; height=&quot;524&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;950&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The time complexity and space complexity of topological sorting is&amp;nbsp;&lt;b&gt;O(|V| + |E|).&amp;nbsp;&lt;/b&gt;&lt;/p&gt;</description>
      <category>Data Science/Data Structure &amp;amp; Algorithm</category>
      <author>Chan Lee</author>
      <guid isPermaLink="true">https://code-studies.tistory.com/186</guid>
      <comments>https://code-studies.tistory.com/186#entry186comment</comments>
      <pubDate>Wed, 28 May 2025 05:02:20 +0900</pubDate>
    </item>
    <item>
      <title>[Python] Bellman-Ford's Shortest Path</title>
      <link>https://code-studies.tistory.com/185</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;The&amp;nbsp;&lt;b&gt;Bellman-Ford shortest path algorithm&lt;/b&gt;, created by&amp;nbsp;&lt;i&gt;Richard Bellman&lt;/i&gt; and&amp;nbsp;&lt;i&gt;Lester Ford, Jr&lt;/i&gt;,. determines the shortest path from a start vertex to each vertex in a graph.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;For each vertex, the Bellman-Ford algorithm determines the vertex's distance and predecessor pointer. A vertex's&amp;nbsp;&lt;b&gt;distance&amp;nbsp;&lt;/b&gt;is the shortest path distance from the start vertex. A vertex's&amp;nbsp;&lt;b&gt;predecessor pointer&amp;nbsp;&lt;/b&gt;points to the previous vertex along the shortest path from the start vertex.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The Bellman-Ford algorithm initializes all vertices' current distances to &lt;i&gt;infinity (&amp;infin;)&lt;/i&gt; and predecessors to &lt;i&gt;null&lt;/i&gt;, and assigns the start vertex with a distance of 0. The algorithm performs V-1 main iterations, visiting all vertices in the graph during each iteration. Each time a vertex is visited, the algorithm follows all edges to adjacent vertices. For each adjacent vertex, the algorithm computes the distance of the path from the start vertex to the current vertex and continuing on to the adjacent vertex. If that path's distance is shorter than the adjacent vertex's current distance, a shorter path has been found. The adjacent vertex's current distance is updated to the newly found shorter path's distance, and the vertex's predecessor pointer is pointed to the current vertex.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;The Bellman-Ford algorithm does not require a specific order for visiting vertices during each main iteration. So after each iteration, a vertex's current distance and predecessor may not yet be the shortest path from the start vertex. The shortest path may propagate to only one vertex each iteration, requiring V-1 iterations to propagate from the start vertex to all other vertices&lt;/p&gt;
&lt;pre id=&quot;code_1748369744707&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Pseudocode
BellmanFord(startV) {
   for each vertex currentV in graph {
      currentV⇢distance = Infinity
      currentV⇢predV = null
   }

   // startV has a distance of 0 from itself
   startV⇢distance = 0                

   for i = 1 to number of vertices - 1 { // Main iterations
      for each vertex currentV in graph {
         for each vertex adjV adjacent to currentV {
            edgeWeight = weight of edge from currentV to adjV
            alternativePathDistance = currentV⇢distance + edgeWeight
                  
            // If shorter path from startV to adjV is found,
            // update adjV's distance and predecessor
            if (alternativePathDistance &amp;lt; adjV⇢distance) {
               adjV⇢distance = alternativePathDistance
               adjV⇢predV = currentV
            }
         }
      }
   }

   // Check for a negative edge weight cycle
   for each vertex currentV in graph {
      for each vertex adjV adjacent to currentV {
         edgeWeight = weight of edge from currentV to adjV
         alternativePathDistance = currentV⇢distance + edgeWeight

         // If shorter path from startV to adjV is still found,
         // a negative edge weight cycle exists
         if (alternativePathDistance &amp;lt; adjV⇢distance) {
            return false
         }
      }
   }

   return true
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The Bellman-Ford algorithm supports graphs with negative edge weights. However, if a negative edge weight exists, there is no shortest path.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;한글로 정리하자면&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 모든 Vertex (Node) 들의 distance를 &amp;infin;, predecessor node를 null로 초기화한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 시작 vertex (&lt;i&gt;startV&lt;/i&gt;)의 distance를 0으로 설정한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. V 개의 Vertex를 가진 Graph는 (V - 1) 번의 Main iteration (foor loop)이 존재한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 각 Main iteration에서&amp;nbsp;&lt;u&gt;모든 vertex&lt;/u&gt;를 방문하고 (현재 방문한 vertex를 &lt;i&gt;currentV&lt;/i&gt; 라고 할때) 다음과 같은 절차를 따른다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;distance 계산&lt;br /&gt;distance = (현재 방문한 currentV의 distance) + (계산하고자 하는 adjacnet vertex 까지의 path weight)&amp;nbsp;&lt;br /&gt;Ex. A (distance 10) &amp;rarr;(weight 3)&amp;rarr; B 이면, B의 distance는 10 + 3 = 13&lt;/li&gt;
&lt;li&gt;계산된 distance가 adjacent vertex의 distance 값보다 높다면 이를 업데이트한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 위 알고리즘을 V - 1회 반복 시 각 node의 distance가 starting vertex 부터의 거리, predecessor pointer가 최단거리 path를 나타낸다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1748371525561&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;## Python Implementation

def bellman_ford(graph, start_vertex):
    # Initialize all vertex distances to infinity and
    # and predecessor vertices to None.
    for current_vertex in graph.adjacency_list:
      current_vertex.distance = float('inf') # Infinity
      current_vertex.pred_vertex = None

    # start_vertex has a distance of 0 from itself
    start_vertex.distance = 0                

    # Main loop is executed |V|-1 times to guarantee minimum distances.
    for i in range(len(graph.adjacency_list)-1):
        # The main loop.
        for current_vertex in graph.adjacency_list:
            for adj_vertex in graph.adjacency_list[current_vertex]:
                edge_weight = graph.edge_weights[(current_vertex, adj_vertex)]
                alternative_path_distance = current_vertex.distance + edge_weight
                      
                # If shorter path from start_vertex to adj_vertex is found,
                # update adj_vertex's distance and predecessor
                if alternative_path_distance &amp;lt; adj_vertex.distance:
                   adj_vertex.distance = alternative_path_distance
                   adj_vertex.pred_vertex = current_vertex

    # Check for a negative edge weight cycle
    for current_vertex in graph.adjacency_list:
        for adj_vertex in graph.adjacency_list[current_vertex]:
             edge_weight = graph.edge_weights[(current_vertex, adj_vertex)]
             alternative_path_distance = current_vertex.distance + edge_weight

             # If shorter path from start_vertex to adj_vertex is still found,
             # a negative edge weight cycle exists
             if alternative_path_distance &amp;lt; adj_vertex.distance:
                return False

    return True&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Data Science/Data Structure &amp;amp; Algorithm</category>
      <author>Chan Lee</author>
      <guid isPermaLink="true">https://code-studies.tistory.com/185</guid>
      <comments>https://code-studies.tistory.com/185#entry185comment</comments>
      <pubDate>Wed, 28 May 2025 03:45:33 +0900</pubDate>
    </item>
    <item>
      <title>[Python] Dijkstra's Shortest Path | 다익스트라 최단거리</title>
      <link>https://code-studies.tistory.com/184</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Finding the shortest path between vertices in a graph has many applications.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Dijkstra's shortest path algorithm&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;, created by &lt;i&gt;Edsger Dijkstra&lt;/i&gt;, determines the shortest path from a start vertex to each vertex in a graph. For each vertex, Dijkstra's algorithm determines the vertex's distance and predecessor pointer.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;A vertex's&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;distance&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;is the shortest path distance from the start vertex. &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;A vertex's&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;predecessor pointer&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;points to the previous vertex along the shortest path from the start vertex.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Dijkstra's algorithm initializes all vertices' distances to infinity (&amp;infin;), initializes all vertices' predecessors to null, and enqueues all vertices into a queue of unvisited vertices. The algorithm then assigns the start vertex's distance with 0. While the queue is not empty, the algorithm dequeues the vertex with the shortest distance. For each adjacent vertex, the algorithm computes the distance of the path from the start vertex to the current vertex and continuing on to the adjacent vertex. If that path's distance is shorter than the adjacent vertex's current distance, a shorter path has been found. The adjacent vertex's current distance is updated to the distance of the newly found shorter path's distance, and vertex's predecessor pointer is pointed to the current vertex.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;To perfrom Dijkstra's algorithm, the&amp;nbsp;&lt;i&gt;Graph&amp;nbsp;&lt;/i&gt;and&amp;nbsp;&lt;i&gt;Vertex&amp;nbsp;&lt;/i&gt;classes are used. The&amp;nbsp;&lt;i&gt;Vertex&amp;nbsp;&lt;/i&gt;class is extended to include two additional data members:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;nbsp;&lt;i&gt;distance&lt;/i&gt;: The total sum of the edge weights on a path from some start vertex to the vertex.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;nbsp;&lt;i&gt;pred_vertex&lt;/i&gt;: A reference to the vertex that occurs immediately before the vertex, on a path from some start vertex to the vertex.&lt;/p&gt;
&lt;pre id=&quot;code_1748301762120&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def dijkstra_shortest_path(g, start_vertex):
    # Put all vertices in an unvisited queue.
    unvisited_queue = []
    for current_vertex in g.adjacency_list:
        unvisited_queue.append(current_vertex)

    # start_vertex has a distance of 0 from itself
    start_vertex.distance = 0

    # One vertex is removed with each iteration; repeat until the list is
    # empty.
    while len(unvisited_queue) &amp;gt; 0:
        
        # Visit vertex with minimum distance from start_vertex
        smallest_index = 0
        for i in range(1, len(unvisited_queue)):
            if unvisited_queue[i].distance &amp;lt; unvisited_queue[smallest_index].distance:
                smallest_index = i
        current_vertex = unvisited_queue.pop(smallest_index)

        # Check potential path lengths from the current vertex to all neighbors.
        for adj_vertex in g.adjacency_list[current_vertex]:
            edge_weight = g.edge_weights[(current_vertex, adj_vertex)]
            alternative_path_distance = current_vertex.distance + edge_weight
                  
            # If shorter path from start_vertex to adj_vertex is found,
            # update adj_vertex's distance and predecessor
            if alternative_path_distance &amp;lt; adj_vertex.distance:
                adj_vertex.distance = alternative_path_distance
                adj_vertex.pred_vertex = current_vertex


def get_shortest_path(start_vertex, end_vertex):
    # Start from end_vertex and build the path backwards.
    path = ''
    current_vertex = end_vertex
    while current_vertex is not start_vertex:
        path = ' -&amp;gt; ' + str(current_vertex.label) + path
        current_vertex = current_vertex.pred_vertex
    path = start_vertex.label + path
    return path&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Data Science/Data Structure &amp;amp; Algorithm</category>
      <author>Chan Lee</author>
      <guid isPermaLink="true">https://code-studies.tistory.com/184</guid>
      <comments>https://code-studies.tistory.com/184#entry184comment</comments>
      <pubDate>Tue, 27 May 2025 08:33:15 +0900</pubDate>
    </item>
    <item>
      <title>[Data Structure] Python: Graphs</title>
      <link>https://code-studies.tistory.com/183</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Vertex and Graph Class&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The &lt;i&gt;Graph&lt;/i&gt; class holds a vertex adjacency list using a dictionary that maps a &lt;i&gt;Vertex&lt;/i&gt; object to a list of aadjacent&amp;nbsp;&lt;i&gt;Vertex&amp;nbsp;&lt;/i&gt;objects.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The Vertex class contains a label, but can be augmented by graph algorithms to contain additional data if required.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A&amp;nbsp;&lt;i&gt;Graph&amp;nbsp;&lt;/i&gt;object is initialized with an empty adjacency list.&amp;nbsp;&lt;i&gt;Vertex&amp;nbsp;&lt;/i&gt;objects are created and added to the&amp;nbsp;&lt;i&gt;Graph&amp;nbsp;&lt;/i&gt;using the&amp;nbsp;&lt;i&gt;add_vertex()&amp;nbsp;&lt;/i&gt;method.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1748299458449&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Vertex:
    def __init__(self, label):
        self.label = label
        
class Graph:
    def __init__(self):
        self.adjacency_list = {}
  
    def add_vertex(self, new_vertex):
        self.adjacency_list[new_vertex] = []
        
# Program to create and populate a Graph object.
g = Graph()
vertex_a = Vertex(&quot;New York&quot;)
vertex_b = Vertex(&quot;Tokyo&quot;)
vertex_c = Vertex(&quot;London&quot;)

g.add_vertex(vertex_a)
g.add_vertex(vertex_b)
g.add_vertex(vertex_c)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Graph Edges and Edge Weights&lt;/b&gt;&lt;/h3&gt;
&lt;div id=&quot;ember2383&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Edges are represented as vertex&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;pairs&lt;/i&gt;, using a 2-item tuple. &lt;br /&gt;Ex: (vertex_a, vertex_b) is an edge that goes from vertex_a to vertex_b.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Undirected edges are two symmetric vertex pairs: (vertex_a, vertex_b) and (vertex_b, vertex_a).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Edges also have numeric&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;weights&lt;/i&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;By default, an edge is assigned with weight 1.0. Edge weights are stored in the dictionary edge_weights where the vertex pair is the key and the edge weight is the value.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1748299661965&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Graph:
    def __init__(self):
        self.adjacency_list = {}
        self.edge_weights = {}
        
    def add_vertex(self, new_vertex):
        self.adjacency_list[new_vertex] = []
        
    def add_directed_edge(self, from_vertex, to_vertex, weight = 1.0):
        self.edge_weights[(from_vertex, to_vertex)] = weight
        self.adjacency_list[from_vertex].append(to_vertex)
        
    def add_undirected_edge(self, vertex_a, vertex_b, weight = 1.0):
        self.add_directed_edge(vertex_a, vertex_b, weight)
        self.add_directed_edge(vertex_b, vertex_a, weight)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;1252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czdw2T/btsOd9ATD3B/LkqMrRfrB2LLgnipTH8x2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czdw2T/btsOd9ATD3B/LkqMrRfrB2LLgnipTH8x2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czdw2T/btsOd9ATD3B/LkqMrRfrB2LLgnipTH8x2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fczdw2T%2FbtsOd9ATD3B%2FLkqMrRfrB2LLgnipTH8x2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;399&quot; height=&quot;596&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;1252&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Python: Breadth-First Search&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Breadth-first search traverses a graph by starting at a specific vertex and visiting the vertex's adjacent vertices before visiting the next closest vertices. No vertex is re-visited.&lt;/p&gt;
&lt;pre id=&quot;code_1748300399043&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Breadth-first search function
def breadth_first_search(graph, start_vertex, distances=dict()):
    discovered_set = set()
    frontier_queue = Queue()
    visited_list = []
    
    # start_vertex has a distance of 0 from itself
    distances[start_vertex] = 0

    frontier_queue.enqueue(start_vertex) # Enqueue start_vertex in frontier_queue
    discovered_set.add(start_vertex)     # Add start_vertex to discovered_set

    while (frontier_queue.list.head != None):
        current_vertex = frontier_queue.dequeue()
        visited_list.append(current_vertex)
        for adjacent_vertex in graph.adjacency_list[current_vertex]:
            if adjacent_vertex not in discovered_set:
                frontier_queue.enqueue(adjacent_vertex)
                discovered_set.add(adjacent_vertex)
                
                # Distance of adjacent_vertex is 1 more than current_vertex
                distances[adjacent_vertex] = distances[current_vertex] + 1
    return visited_list&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Python: Depth-First Search&lt;/b&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Depth-first search traverses a graph by first visiting a specific starting vertex, and then visiting every vertex along each path originating from the starting vertex. Each path is traversed to the path's end before backtracking.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1748300506041&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Depth-first search function
def depth_first_search(graph, start_vertex, visit_function):
    vertex_stack = [start_vertex]
    visited_set = set()

    while len(vertex_stack) &amp;gt; 0:
        current_vertex = vertex_stack.pop()
        if current_vertex not in visited_set:
            visit_function(current_vertex)
            visited_set.add(current_vertex)
            for adjacent_vertex in graph.adjacency_list[current_vertex]:
                vertex_stack.append(adjacent_vertex)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Data Science/Data Structure &amp;amp; Algorithm</category>
      <author>Chan Lee</author>
      <guid isPermaLink="true">https://code-studies.tistory.com/183</guid>
      <comments>https://code-studies.tistory.com/183#entry183comment</comments>
      <pubDate>Tue, 27 May 2025 08:13:47 +0900</pubDate>
    </item>
  </channel>
</rss>