<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[不工程的攻城獅]]></title><description><![CDATA[很油又不工程的攻城獅，喜歡不務正業、各式新奇的東西。看看網路行銷、政治議題、二次元世界 Peko。不負責任的想到就寫，懶得排版的傢伙]]></description><link>https://blog.taiwolskit.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 03:34:07 GMT</lastBuildDate><atom:link href="https://blog.taiwolskit.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[如何開始入門軟體工程領域 - 名詞解釋（長期更新）]]></title><description><![CDATA[現在應該開始有很多人想要踏入軟體工程的領域，但在進入這個領域之前，覺得先了解一些名詞，可以在入門時更有方向也更知道要用什麼關鍵字去找尋有用的資訊。這篇文章就是想要幫助想要入門的人理解一些軟體工程裡的專有名詞。
作業系統
這一區塊主要解釋跟作業系統層面相關的名詞




英文中文解釋



Operation system  


簡稱 OS | 作業系統 | 就是電腦的作業系統，是三大作業系統分別是：Linux、Windows、macOS |
| Linux |  | 自由和開放原始碼的 UNI...]]></description><link>https://blog.taiwolskit.com/how-to-begin-learning-in-the-field-of-software-engineering-explanation-of-terms</link><guid isPermaLink="true">https://blog.taiwolskit.com/how-to-begin-learning-in-the-field-of-software-engineering-explanation-of-terms</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Wed, 10 May 2023 14:42:25 GMT</pubDate><content:encoded><![CDATA[<p>現在應該開始有很多人想要踏入軟體工程的領域，但在進入這個領域之前，覺得先了解一些名詞，可以在入門時更有方向也更知道要用什麼關鍵字去找尋有用的資訊。這篇文章就是想要幫助想要入門的人理解一些軟體工程裡的專有名詞。</p>
<h2 id="heading-5l2c5qwt57o757wx">作業系統</h2>
<p>這一區塊主要解釋跟作業系統層面相關的名詞</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>英文</td><td>中文</td><td>解釋</td></tr>
</thead>
<tbody>
<tr>
<td>Operation system  </td></tr>
</tbody>
</table>
</div><p>簡稱 OS | 作業系統 | 就是電腦的作業系統，是三大作業系統分別是：Linux、Windows、macOS |
| Linux |  | 自由和開放原始碼的 UNIX-like 作業系統，是目前全世界佔比最高的作業系統，主要是使用於電腦伺服器和軟體開發上。對於一般消費大眾較不常見，但其實平常使用的線上等服務都是使用此作業系統。 |
| Kernel | 核心 | 可以想像是作業系統的大腦，是處理所有事物中的核心程式 |
| Shell |  | OS 的操作介面，為作業系統解譯程式傳入需要處理的指令，來管理您與作業系統之間的互動。 |
| Terminal | 終端機 | 是一台<a target="_blank" href="https://www.wikiwand.com/zh-tw/%E9%9B%BB%E8%85%A6">電腦</a>或者計算機系統，用來讓用戶輸入數據，及顯示其計算結果的機器，簡而言之就是人類使用者與計算機互動的裝置 |
| Open source | 開放原始碼 | 一種開放分享程式碼的文化，需要注意的是開放分享不意味著免費喔。依照不同的開放授權，有些也只允許使用在非營利的情況。 |</p>
<h2 id="heading-56il5byp6kqe6kia">程式語言</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>英文</td><td>中文</td><td>解釋</td></tr>
</thead>
<tbody>
<tr>
<td>Programming Language</td><td>程式語言</td><td>透過一系列的語法轉換成可以與作業系統溝通的語言</td></tr>
<tr>
<td>Library</td><td>函式庫</td><td></td></tr>
<tr>
<td>Framework</td><td>框架</td><td></td></tr>
<tr>
<td>Software Development Kit  </td></tr>
</tbody>
</table>
</div><p>SDK | 軟體開發套件 | 可以想像就是英雄套裝，當你需要變成鋼鐵人，你就下載這個 SDK 來使用你就使用鋼鐵裝。你想變成雷神索爾，你下載相對應的 SDK 就可以索爾。 |
| Application programming interface<br />API | 應用程式介面 | 可以想像就是皮卡丘，你叫皮卡丘使用十萬伏特，他就會使用十萬伏特。 |
| Integrated Development Environment<br />IDE | 整合開發環境 | 一種輔助程式開發人員開發軟體的應用軟體 |
| Version control | 版本控制 | 目前主流常見的版本控制工具是 Git，所謂的版本控制就是控制每次的程式語言版本。因為每次不可能記住每次夕改程式語言時改了什麼，所以就利用版本控制工具來紀錄每次的修改。 |
| Frontend | 前端 | 通常指的是使用者可以看到的範圍，例如網站介面、行動裝置介面（但行動裝置通常會稱作 Mobile 端） |
| Backend | 後端 | 使用者看不到的範圍，例如伺服器、資料庫等 |</p>
<p>Library 和 Framework 的概念比較需要拉出來解釋，很常會搞混。Library 是類似 SDK 的東西，通常是包裝了許多常用的功能。但是使用後並不影響既有的程式架構。Framework 也是包裝了許多的功能，但是如果要使用的話，就必須按照它規定的規則來使用。</p>
<p>有點像是 Library 是自由重量的啞鈴，你可以用啞鈴做到很多種不同的運動來訓練不同的身體部位。但是 Framework 就像是機械式器材，你就是只能照他的使用方式來訓練特定的部位。</p>
<h2 id="heading-55sf5owl5zyi">生態圈</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>英文</td><td>中文</td><td>解釋</td></tr>
</thead>
<tbody>
<tr>
<td>Cloud service 或 Public Cloud</td><td>公有雲</td><td>就是一堆開放給大眾付錢使用的伺服器，目前最大宗的三家就是：AWS(Amazon 爸爸)、Azure(微軟爸爸)、GCP(Google 爸爸)</td></tr>
<tr>
<td>GitHub</td><td></td><td>目前最大眾使用來分享程式碼的網站，目前已被微軟收購</td></tr>
<tr>
<td>VSCode</td><td></td><td>目前被主流使用的程式編輯軟體</td></tr>
<tr>
<td>Stack Overflow</td><td></td><td>最主流的軟體問答網站</td></tr>
<tr>
<td>LeetCode</td><td></td><td>最主流知名的程式練習網站，擁有豐富的題庫來訓練程式語言的邏輯思維和演算法</td></tr>
</tbody>
</table>
</div>]]></content:encoded></item><item><title><![CDATA[我的 MacBook Pro (Apple Silicon) 設定]]></title><description><![CDATA[現在開始因為 ChatGPT 的出現，各種 AI 助手的功能都跑出來了。想想自己用了許久的環境設定也應該要來重新審視和建立新的開發環境了，僅此紀錄我個人的環境配置步驟和設定。
環境前置步驟

還原 MacBook Pro 至全新環境 macOS（全部資料刪除）

設定好初始設定後，登入 Apple ID 進入 App Store 確定 macOS 版本和預設 APP 都更新到最新 macOS 版本

到系統設定調整所有設定至個人習慣的設定

三指拖移

觸控板手勢開啟

防火牆開啟

輸入法設定...]]></description><link>https://blog.taiwolskit.com/my-macbook-pro-setup</link><guid isPermaLink="true">https://blog.taiwolskit.com/my-macbook-pro-setup</guid><category><![CDATA[software development]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Tue, 25 Apr 2023 14:10:13 GMT</pubDate><content:encoded><![CDATA[<p>現在開始因為 ChatGPT 的出現，各種 AI 助手的功能都跑出來了。想想自己用了許久的環境設定也應該要來重新審視和建立新的開發環境了，僅此紀錄我個人的環境配置步驟和設定。</p>
<h1 id="heading-55kw5akd5ymn572u5q2l6amf">環境前置步驟</h1>
<ol>
<li><p>還原 MacBook Pro 至全新環境 macOS（全部資料刪除）</p>
</li>
<li><p>設定好初始設定後，登入 Apple ID 進入 App Store 確定 macOS 版本和預設 APP 都更新到最新 macOS 版本</p>
</li>
<li><p>到系統設定調整所有設定至個人習慣的設定</p>
<ul>
<li><p>三指拖移</p>
</li>
<li><p>觸控板手勢開啟</p>
</li>
<li><p>防火牆開啟</p>
</li>
<li><p>輸入法設定</p>
</li>
</ul>
</li>
<li><p>安裝 Safari Extension 和設定開啟開發者清單</p>
</li>
<li><p>到 App Store 安裝 XCode，安裝完後開啟 XCode 安裝 Command Line Tool</p>
</li>
</ol>
<h2 id="heading-6luf6auu5a6j6kod">軟體安裝</h2>
<p>分不同的類別，順序不影響</p>
<h3 id="heading-font">字體 Font</h3>
<ul>
<li><p>英文</p>
<ul>
<li><p><a target="_blank" href="https://www.nerdfonts.com/">Meslo Nerd Font</a> for p10k</p>
</li>
<li><p><a target="_blank" href="https://github.com/tonsky/FiraCode">Fira Code</a> for VSCode</p>
</li>
<li><p><a target="_blank" href="https://www.jetbrains.com/lp/mono/">JetBrains Mono</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/microsoft/cascadia-code">Cascadia Code</a></p>
</li>
<li><p><a target="_blank" href="https://fontsarena.com/sans-forgetica-by-rmit-university/">Sana Forgetica</a></p>
</li>
</ul>
</li>
<li><p>中文</p>
<ul>
<li><a target="_blank" href="https://justfont.com/huninn/">justfont 粉圓體</a></li>
</ul>
</li>
</ul>
<h3 id="heading-5lia6iis55so6ycu">一般用途</h3>
<ul>
<li><p>App Store：Magnet - 視窗管理</p>
</li>
<li><p>App Store：The Unarchiver - 解壓縮工具</p>
</li>
<li><p>1Password - 密碼管理工具</p>
</li>
<li><p>Bitdefender - 防毒軟體</p>
</li>
<li><p>CleanMyMacX - 空間清理</p>
</li>
<li><p>Bartender - Menu bar 管理工具</p>
</li>
<li><p>CheatSheet - 快捷鍵查詢</p>
</li>
<li><p>Raycast - 免費的 Spotlight 加強版</p>
</li>
<li><p>MacGPT - 串接 ChatGPT</p>
</li>
<li><p>Rewind - 個人操作記錄</p>
</li>
<li><p>Chrome</p>
</li>
<li><p>Edge</p>
</li>
<li><p>TradingView</p>
</li>
<li><p>ClickUp</p>
</li>
<li><p>Rize - 個人時間追蹤軟體</p>
</li>
</ul>
<h3 id="heading-5pah5pu4">文書</h3>
<ul>
<li><p>Notion</p>
</li>
<li><p>Miro</p>
</li>
<li><p>Grammarly</p>
</li>
<li><p>Dash</p>
</li>
<li><p>Anki</p>
</li>
<li><p>Airtable</p>
</li>
<li><p>App Store：Day One</p>
</li>
<li><p>App Store：Feedly</p>
</li>
<li><p>App Store：OneNote</p>
</li>
<li><p>App Store：Habitify</p>
</li>
<li><p>App Store：GoodNotes</p>
</li>
</ul>
<h3 id="heading-6yca6kik">通訊</h3>
<ul>
<li><p>App Store：Line</p>
</li>
<li><p>App Store：Slack</p>
</li>
<li><p>App Store：Twitter</p>
</li>
<li><p>Discord</p>
</li>
<li><p>Zoom</p>
</li>
</ul>
<h3 id="heading-5b2x6zz">影音</h3>
<ul>
<li><p>App Store：Shazam</p>
</li>
<li><p>App Store：Noizio - 白噪音</p>
</li>
<li><p>App Store：Motion</p>
</li>
<li><p>App Store：Final Cut Pro</p>
</li>
<li><p>App Store：Logic Pro</p>
</li>
<li><p>App Store：MainStage</p>
</li>
<li><p>App Store：Compressor</p>
</li>
<li><p>Steam</p>
</li>
<li><p>OBS</p>
</li>
<li><p>Spotify</p>
</li>
<li><p>VLC</p>
</li>
</ul>
<h3 id="heading-6zal55m85bel5yw3">開發工具</h3>
<ul>
<li><p>iTerm2</p>
</li>
<li><p>Wrap</p>
</li>
<li><p>Termius</p>
</li>
<li><p>Docker</p>
</li>
<li><p>GPG Keychain</p>
</li>
<li><p>Fig</p>
</li>
<li><p>Visual Studio Code</p>
</li>
<li><p>Cursor</p>
</li>
<li><p>Lens</p>
</li>
<li><p>Android Studio</p>
</li>
<li><p>RapidAPI / Postman</p>
</li>
<li><p>GitKraken</p>
</li>
<li><p>Responsively</p>
</li>
<li><p>Wireshark</p>
</li>
<li><p>Figma</p>
</li>
<li><p>TablePlus</p>
</li>
<li><p>pgAdmin</p>
</li>
<li><p>Querious</p>
</li>
<li><p>RedisInsight</p>
</li>
</ul>
<h2 id="heading-55kw5akd6kit5a6a">環境設定</h2>
<h3 id="heading-iterm2">iTerm2 設定</h3>
<ol>
<li><p>到 iterm2 color theme 設定：Tomorrow Night Eighties</p>
</li>
<li><p>匯入 Profile 設定檔</p>
</li>
</ol>
<h3 id="heading-zsh-shell">Zsh Shell 設定</h3>
<ol>
<li><p>安裝 Homebrew</p>
</li>
<li><p>安裝 rvm 並更新 ruby 到最新版本</p>
</li>
<li><p>開啟 Fig，登入帳號後同步環境設定和 Plugins</p>
<ol>
<li><p>oh-my-zsh</p>
</li>
<li><p>zsh-syntax-highlight</p>
</li>
<li><p>zsh-autosuggestions</p>
</li>
<li><p>Powerlevel10k</p>
</li>
<li><p>Git Flow Completion</p>
</li>
<li><p>Kube Color</p>
</li>
<li><p>Zsh Completions</p>
</li>
<li><p>Git Flow</p>
</li>
</ol>
</li>
<li><p>設定 Fig Aliases <code>systemupdate = sudo gem update --system &amp;&amp; sudo gem update &amp;&amp; brew update &amp;&amp; brew upgrade &amp;&amp; omz update &amp;&amp; rustup update &amp;&amp; kubectl krew update &amp;&amp; kubectl krew upgrade &amp;&amp; gcloud components update &amp;&amp; brew doctor</code></p>
</li>
<li><p>開啟 iTerm2 執行 <code>p10k configure</code> 設定或是設定檔放置 <code>~/.p10k.zsh</code></p>
</li>
<li><p>設定 gpg 和 git 全域設定</p>
<pre><code class="lang-bash"> gpg --full-generate-key
 gpg --list-secret-keys --keyid-format LONG
 gpg --armor --<span class="hljs-built_in">export</span> &lt;ID&gt;
 git config --global user.name &lt;Name&gt;
 git config --global user.email &lt;Email&gt;
 git config --global commit.gpgsign <span class="hljs-literal">true</span>
 git config --global gpg.program /usr/<span class="hljs-built_in">local</span>/bin/gpg
 git config --global user.signingkey &lt;ID&gt;
</code></pre>
</li>
</ol>
<h3 id="heading-command-line">安裝 Command Line</h3>
<h4 id="heading-general">General</h4>
<pre><code class="lang-bash"><span class="hljs-comment"># General</span>
fig install --dotfiles
brew install --cask 1password/tap/1password-cli
brew install mycli pgcli jq yq tmux tldr shellcheck glances sonarqube hadolint \
  k6 slack-cli streamlink tree ffmpeg postgresql

<span class="hljs-comment"># GitHub</span>
brew install gh
gh auth login

<span class="hljs-comment"># GitLab</span>
brew install glab
glab auth login

<span class="hljs-comment"># CloudFlare</span>
brew install cloudflared

<span class="hljs-comment"># Ngrok</span>
brew install ngrok
ngrok config add-authtoken &lt;Token&gt;

<span class="hljs-comment"># Shopify</span>
brew tap shopify/shopify
brew install 
shopify login

<span class="hljs-comment"># Ytarhcive</span>
brew install danirukun/ytarchive/ytarchive
ytarchive --write-thumbnail -t --merge --add-metadata &lt;URL&gt; best

brew install go
brew install terraform terragrunt terraform-docs
brew install swift-format
</code></pre>
<h4 id="heading-cloud-service">Cloud Service</h4>
<pre><code class="lang-bash"><span class="hljs-comment"># gcloud</span>
curl https://sdk.cloud.google.com | zsh
gcloud init

<span class="hljs-comment"># firebase</span>
curl -sL https://firebase.tools | upgrade=<span class="hljs-literal">true</span> zsh
firebase login:ci

<span class="hljs-comment"># awscli</span>
brew install awscli session-manager-plugin cdk8s cdktf
brew tap weaveworks/tap
brew install weaveworks/tap/eksctl
brew install aws/tap/copilot-cli
aws configure
aws configure <span class="hljs-built_in">set</span> region ap-northeast-1
npm install -g aws-cdk

<span class="hljs-comment"># azure cli</span>
brew install azure-cli
az login
</code></pre>
<h4 id="heading-kubernetes">Kubernetes</h4>
<pre><code class="lang-bash"><span class="hljs-comment"># 快速切換 K8S Cluster 和 Namespace 的工具</span>
brew install kubectx kustomize k9s skaffold helm helmfile 

<span class="hljs-comment"># Kubernetes Operations</span>
brew install kops
<span class="hljs-comment"># SDK for building Kubernetes applications</span>
brew install operator-sdk
<span class="hljs-comment"># A tool for exploring each layer in a docker image</span>
brew install dive
<span class="hljs-comment"># The lazier way to manage everything docker</span>
brew install lazydocker
<span class="hljs-comment"># Container Image Linter for Security</span>
brew install goodwithtech/r/dockle

brew tap kubeshark/kubeshark
brew install kubeshark

<span class="hljs-comment"># Helm plugin</span>
helm plugin install https://github.com/jkroepke/helm-secrets
helm plugin install https://github.com/databus23/helm-diff
</code></pre>
<h5 id="heading-krew">krew</h5>
<ol>
<li><p>Install Krew</p>
</li>
<li><p>在 Fig 設定 PATH 中加上 <code>${KREW_ROOT:-$HOME/.krew}/bin</code></p>
</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-comment"># Show an RBAC access matrix for server resources</span>
kubectl krew install access-matrix

<span class="hljs-comment"># Manage cert-manager resources inside your cluster</span>
kubectl krew install cert-manager

<span class="hljs-comment"># Provides an overview of resource requests, limits, and utilization</span>
kubectl krew install resource-capacity

<span class="hljs-comment"># Kubernetes static code analysis</span>
kubectl krew install score

<span class="hljs-comment"># Show a tree of object hierarchies through ownerReferences</span>
kubectl krew install tree

<span class="hljs-comment"># Trace Kubernetes pods and nodes with system tools</span>
kubectl krew install trace
</code></pre>
<h4 id="heading-python">Python</h4>
<pre><code class="lang-bash">brew install python@3.11
ln -s -f /usr/<span class="hljs-built_in">local</span>/bin/python3 /usr/<span class="hljs-built_in">local</span>/bin/python
brew install pipenv poetry
</code></pre>
<h4 id="heading-nodejs">Node.js</h4>
<ol>
<li>安裝 <code>nvm</code></li>
</ol>
<pre><code class="lang-bash">nvm install-latest-npm

<span class="hljs-comment"># General Tool</span>
brew install watchman
npm i -g @vue/cli @angular/cli npm-check-updates vercel

<span class="hljs-comment"># GitHub copilot</span>
npm install -g @githubnext/github-copilot-cli
github-copilot-cli auth
<span class="hljs-comment"># 在 Fig scripts 加上 eval "$(github-copilot-cli alias -- "$0")"</span>
</code></pre>
<h4 id="heading-rust">Rust</h4>
<pre><code class="lang-bash"><span class="hljs-comment"># rustup, rust version manager</span>
brew install rustup
<span class="hljs-comment"># curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh</span>
<span class="hljs-comment"># source $HOME/.cargo/env</span>
<span class="hljs-comment"># WASM</span>
cargo install wasm-pack
</code></pre>
<h4 id="heading-java">Java</h4>
<pre><code class="lang-bash">brew install openjdk
sudo ln -sfn /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk
</code></pre>
<p>Fig PATH 加上 <code>/opt/homebrew/opt/openjdk/bin</code></p>
<hr />
<h2 id="heading-5zix6kmm5zkm5ps56ycy">嘗試和改進</h2>
<p>幾個嘗試改變的調整</p>
<ol>
<li><p>導入 1Password 來做 SSH agent 的管理</p>
<ul>
<li>缺陷：目前遇到開啟 VSCode 有些套件要存取 KeyChain 或是 SSH 都需要做授權的問題</li>
</ul>
</li>
<li><p>使用 Fig 來做環境設定和同步</p>
<ul>
<li>缺陷：沒有辦法很好的管理已經現有的環境，然後一些安裝的 Script 會直接幫忙寫入 ENV 或 Script 到 <code>.zshrc</code> 中，但現在變成都還要自己手動加入到 Fig 中</li>
</ul>
</li>
<li><p>使用 Raycast 來加強和自動化個人的工作流程</p>
<ul>
<li>改進：功能很強大，但還在熟悉中</li>
</ul>
</li>
<li><p>嘗試使用 Cursor 來做開發工具</p>
<ul>
<li>基底看起來是包了 VSCode，但是 Extension 不多。看起來不會掃描既有專案的 Code Base，要使用在現有專案有點難。</li>
</ul>
</li>
<li><p>嘗試 Wrap &amp; Termius &amp; GitHub Copilot CLI</p>
<ul>
<li><p>Wrap 提供的 Wrap AI 滿不錯的搭配 GitHub Copilot CLI 相當好用</p>
</li>
<li><p>Termius 可以用於平板做 AWS SSH 的登入操作也相當不錯用，對於突然要進機器處理問題，但又沒有帶筆電時相當好用的工具</p>
</li>
</ul>
</li>
<li><p>使用 Rewind &amp; ClickUp &amp; Rize &amp; MacGPT</p>
<ul>
<li><p>Rewind 可以搜尋和記錄自己過去筆電的所有操作，還能對於關鍵字做搜尋相當不錯，但是小心自己看什麼色色的東西也被記錄喔。</p>
</li>
<li><p>ClickUp 使用這個平台做自己的個人進度追蹤軟體，算是免費版裡面覺得功能最多，且跨平台。Jira 速度太慢了，受不了所以找了這個。</p>
</li>
<li><p>Rize 可以做個人的時間追蹤，想使用這個軟體來分析自己的生產力。缺點是目前只支援 Mac，還沒辦法跨平台到 iPad 或 iPhone。</p>
</li>
<li><p>MacGPT 直接在 Mac 上不用開網頁就能跟 ChatGPT 做對話的工具</p>
</li>
</ul>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[ChatGPT 下的發展預想]]></title><description><![CDATA[從 ChatGPT 問世到現在，有許許多多的文章和討論出來。先從最早的 Google 要完蛋了，到後來的工作要被取代了，工程師失業了。
我就比較沒有想要馬上出來評論一下，我喜歡讓子彈飛一會兒。跟討論一下我自己比較在意的討論點。
Google 為什麼慢了?
結論：因為他需要更小心
很多人說 Google 怎麼被微軟搶先了一步。剛開始 Bing 說要加上 AI 的時候大家都在說 Google 怎麼慢了。我就馬上跑去看 OpenAI 的網站，靠北呀啊就 Azure 贊助的。那當然在正式上線 ChatG...]]></description><link>https://blog.taiwolskit.com/my-preview-about-chatgpt</link><guid isPermaLink="true">https://blog.taiwolskit.com/my-preview-about-chatgpt</guid><category><![CDATA[AI]]></category><category><![CDATA[chatgpt]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Thu, 23 Mar 2023 07:17:56 GMT</pubDate><content:encoded><![CDATA[<p>從 ChatGPT 問世到現在，有許許多多的文章和討論出來。先從最早的 Google 要完蛋了，到後來的工作要被取代了，工程師失業了。</p>
<p>我就比較沒有想要馬上出來評論一下，我喜歡讓子彈飛一會兒。跟討論一下我自己比較在意的討論點。</p>
<h2 id="heading-google">Google 為什麼慢了?</h2>
<p>結論：因為他需要更小心</p>
<p>很多人說 Google 怎麼被微軟搶先了一步。剛開始 Bing 說要加上 AI 的時候大家都在說 Google 怎麼慢了。我就馬上跑去看 OpenAI 的網站，靠北呀啊就 Azure 贊助的。那當然在正式上線 ChatGPT 前，微軟早就在準備了。只能說就是一個準備好的連續技給 Google 一拳。不過 Google 也不愧是技術能量很強，也是趕出了一個 Brand（雖然跟 ChatGPT 還是有段距離）。但我相信以 Google 的資料量要趕上應該是不難，所以才可以看出微軟是準備了好幾層的連續技，想要一次拉開差距先來個 BingAI 再來個 Microsoft 365 再來 GitHub Copilot X。</p>
<p>所以為什麼覺得 Google 慢了，因為微軟是準備了一連串的連續攻勢。再來是因為 Google 重心我相信比較煩惱的是之後的 Cookieless 和隱私問題。（想想美國大選就知道 Facebok和 Google 被釘得多慘，沒有做社群的微軟算賺到？）。而且真的說要慢，那位 Apple 老大哥才慢呢。</p>
<h2 id="heading-google-1">Google 會被取代嗎？</h2>
<p>結論：想太多了，打打嘴炮而已。</p>
<p>一個大型企業的收入不會是一個而已，雖然廣告是 Google 最大宗的收入，但是平台是難以取代的。Tiktok 出來了，一堆人說 Facebook 要完蛋了，喊了多久。結果？別忘了 YouTube、Google Maps、Google Cloud Platform、Chromebook 等。小公司就算了，當年一堆人說 IBM 要倒了，還不是到現在都活著。</p>
<h2 id="heading-6kix5asa5lq655qe5bel5l2c6kab6kkr5yw5luj77yf">許多人的工作要被取代？</h2>
<p>結論：對也不對</p>
<p>我相信一些工作將要漸漸被取代，但絕對不會快。而且相對的會產生一些新的工作。舉個例子就是當年的國道收費員退休。收費員的工作被機器取代，相對的會產生需要維修機器和安裝的工作產生。只是當初被取代工作的人並不一定是同一批人能直接承擔新產生的工作。</p>
<p>而且你要說取代，也真的沒那麼快。不然洗碗工早就都被洗碗機取代了。早上街道的打掃人員怎麼沒有被一堆掃地機器人取代。喊這種話的就是騙騙你而已，製造你的資訊落差的恐懼感。</p>
<h2 id="heading-chatgpt-ai">ChatGPT 是 AI 的奇點？</h2>
<p>結論：不是</p>
<p>我覺得 ChatGPT 不是奇點，比較像是一個敲門磚。他終於突破了機器要理解人語言的意思。我覺得要可以達到奇點是需要他可以延伸到期啊的地方。怎麼說呢就是他現在還是文字上的回饋，如果今天叫他去幫我訂披薩。他可以直接用 API 或轉換成語音打電話過去應對。這一連串可以都自動地接起來，做到這種地步。我個人認為才是一個奇點。但我相信 ChatGPT 的成功會加速這個的發生</p>
<h2 id="heading-5b6m57qm55m85bgv55qe6acq5ooz">後續發展的預想</h2>
<p>很多人說工作會被 AI 提升效率，會讓做事情變得更輕鬆。從一開始接觸 GitHub Copilot 到 ChatGPT。我會說其實真的沒有變得更輕鬆，人們會容易變成神化這個些 AI，尤其當人們沒有基礎知識的時候。</p>
<p>我已經開始可以預想以後會有小孩或老人拿著 AI 產生的內容去質問醫生說「AI 說這個藥可以吃，為什麼你不開給我藥」</p>
<p>人需要轉換成一個「領導者」而不是「依靠者」，而作為一個領導者將會要求更多的更廣泛的知識量。就像是我在使用 GitHub Copliot 的時候，他會產生一些樣板，但如果沒有一定的程式基礎你就看不出來需要再優化的問題。</p>
<p>資訊將會變得更多樣且極為擬真，將更要求人們的辨別能力，而要有更強的辨別能力將需要更多的知識。所以你說會變更輕鬆嗎？我覺得不會。</p>
]]></content:encoded></item><item><title><![CDATA[一些覺得有用的工具蒐藏]]></title><description><![CDATA[Development

mkcert：開發工具，產生一個本地使用的 HTTPS 憑證
sqlcommenter：用於檢測 ORM 成效的工具
wallace-cli：用於分析 CSS 的工具
Recoil：Recoil 是一個用於 React 應用程序的實驗性狀態管理庫。它提供了一些單獨使用 React 難以實現的功能，同時兼容 React 的最新功能。
mariana trench：針對 Android 和 Java 應用程序的安全性靜態分析工具。
Browser fingerprintin...]]></description><link>https://blog.taiwolskit.com/5lia5lqb6ka65b6x5pyj55so55qe5bel5yw36jkq6jep</link><guid isPermaLink="true">https://blog.taiwolskit.com/5lia5lqb6ka65b6x5pyj55so55qe5bel5yw36jkq6jep</guid><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Thu, 23 Mar 2023 06:34:14 GMT</pubDate><content:encoded><![CDATA[<h3 id="heading-development">Development</h3>
<ul>
<li><a target="_blank" href="https://github.com/FiloSottile/mkcert">mkcert</a>：開發工具，產生一個本地使用的 HTTPS 憑證</li>
<li><a target="_blank" href="https://github.com/google/sqlcommenter">sqlcommenter</a>：用於檢測 ORM 成效的工具</li>
<li><a target="_blank" href="https://github.com/projectwallace/wallace-cli">wallace-cli</a>：用於分析 CSS 的工具</li>
<li><a target="_blank" href="https://github.com/facebookexperimental/Recoil">Recoil</a>：Recoil 是一個用於 React 應用程序的實驗性狀態管理庫。它提供了一些單獨使用 React 難以實現的功能，同時兼容 React 的最新功能。</li>
<li><a target="_blank" href="https://github.com/facebook/mariana-trench">mariana trench</a>：針對 Android 和 Java 應用程序的安全性靜態分析工具。</li>
<li><a target="_blank" href="https://github.com/niespodd/browser-fingerprinting">Browser fingerprinting</a>：用可用的對策分析機器人保護系統🚿。抓取網頁時如何擊敗反殭屍系統👻並繞過瀏覽器指紋腳本🕵️‍♂️？</li>
<li><a target="_blank" href="https://docs.quantifiedcode.com/python-anti-patterns/index.html">Python anti pattern</a>：Python 開發的反指標</li>
<li><a target="_blank" href="https://bentojs.dev/">BentoJS</a>：AMP 團隊所開發的</li>
<li><a target="_blank" href="https://github.com/GoogleContainerTools/kpt">kpt</a>：一個 Git 原生、模式感知、可擴展的客戶端工具，用於打包、定制、驗證和應用 Kubernetes 資源。</li>
</ul>
<h3 id="heading-terminal">Terminal</h3>
<ul>
<li><a target="_blank" href="https://github.com/sqshq/sampler">sampler</a>：用於 shell 命令執行、可視化和警報的工具</li>
<li><a target="_blank" href="https://github.com/c-bata/kube-prompt">kube-prompt</a>：提供自動補齊 kubernetes 指令的工具</li>
<li><a target="_blank" href="https://github.com/gcla/termshark">termshark</a>：在 Terminal 使用類似 Wireshark 的工具</li>
</ul>
<h3 id="heading-privacy-policy">Privacy Policy</h3>
<ul>
<li><a target="_blank" href="https://github.com/lyrasoft/chinese-privacy-policy-template">中文隱私權政策樣板</a></li>
</ul>
<h3 id="heading-security">Security</h3>
<ul>
<li><a target="_blank" href="https://github.com/authcov/authcov">authov</a>：掃描網站權限覆蓋</li>
<li><a target="_blank" href="https://github.com/labuladong/fucking-algorithm">Fucking algorithm</a></li>
<li><a target="_blank" href="https://moz.com/blog/the-ultimate-guide-to-the-google-search-parameters">The Ultimate Guide to the Google Search Parameters</a></li>
<li><a target="_blank" href="https://github.com/google/disapproved-ads-auditor">Disapproved Ads Auditor</a></li>
<li><a target="_blank" href="https://github.com/tbillington/kondo">Kondo</a>：用於清除電腦非必要的空間</li>
<li><a target="_blank" href="https://github.com/voidcosmos/npkill">npkill</a>：列出所有系統內的 node_module 並可以清除</li>
<li><a target="_blank" href="https://github.com/pyroscope-io/pyroscope">pyroscope</a>：About
Continuous Profiling Platform! Debug performance issues down to a single line of code</li>
<li><a target="_blank" href="https://github.com/statelyai/xstate">xstate</a></li>
</ul>
<h3 id="heading-interview">Interview</h3>
<ul>
<li><a target="_blank" href="https://github.com/jwasham/coding-interview-university">Coding interview university</a>：成為一個軟體工程師的面試準備</li>
<li><a target="_blank" href="https://github.com/AkashSingh3031/The-Complete-FAANG-Preparation">The Complete FAANG Preparation</a>：用於搜集所有準備 FAANG 工作的面試問題</li>
<li><a target="_blank" href="https://github.com/kkbruce/reverse-interview-zh-Hant">面試背後的面試</a></li>
<li><a target="_blank" href="https://github.com/donnemartin/system-design-primer">System design primer</a>：了解如何設計大型系統。準備系統設計面試。包括 Anki 抽認卡。</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Medium, 607. Sales Person]]></title><description><![CDATA[607. Sales Person
題目敘述
SQL Schema >
    Create table If Not Exists SalesPerson (sales_id int, name varchar(255), salary int, commission_rate int, hire_date date)
    Create table If Not Exists Company (com_id int, name varchar(255), city varchar(255)...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-medium-607-sales-person</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-medium-607-sales-person</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Sun, 12 Mar 2023 23:30:48 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-607-sales-personhttpsleetcodecomproblemssales-persondescription"><a target="_blank" href="https://leetcode.com/problems/sales-person/description/">607. Sales Person</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema &gt;</p>
<p>    Create table If Not Exists SalesPerson (sales_id int, name varchar(255), salary int, commission_rate int, hire_date date)
    Create table If Not Exists Company (com_id int, name varchar(255), city varchar(255))
    Create table If Not Exists Orders (order_id int, order_date date, com_id int, sales_id int, amount int)
    Truncate table SalesPerson
    insert into SalesPerson (sales_id, name, salary, commission_rate, hire_date) values ('1', 'John', '100000', '6', '4/1/2006')
    insert into SalesPerson (sales_id, name, salary, commission_rate, hire_date) values ('2', 'Amy', '12000', '5', '5/1/2010')
    insert into SalesPerson (sales_id, name, salary, commission_rate, hire_date) values ('3', 'Mark', '65000', '12', '12/25/2008')
    insert into SalesPerson (sales_id, name, salary, commission_rate, hire_date) values ('4', 'Pam', '25000', '25', '1/1/2005')
    insert into SalesPerson (sales_id, name, salary, commission_rate, hire_date) values ('5', 'Alex', '5000', '10', '2/3/2007')
    Truncate table Company
    insert into Company (com_id, name, city) values ('1', 'RED', 'Boston')
    insert into Company (com_id, name, city) values ('2', 'ORANGE', 'New York')
    insert into Company (com_id, name, city) values ('3', 'YELLOW', 'Boston')
    insert into Company (com_id, name, city) values ('4', 'GREEN', 'Austin')
    Truncate table Orders
    insert into Orders (order_id, order_date, com_id, sales_id, amount) values ('1', '1/1/2014', '3', '4', '10000')
    insert into Orders (order_id, order_date, com_id, sales_id, amount) values ('2', '2/1/2014', '4', '5', '5000')
    insert into Orders (order_id, order_date, com_id, sales_id, amount) values ('3', '3/1/2014', '1', '1', '50000')
    insert into Orders (order_id, order_date, com_id, sales_id, amount) values ('4', '4/1/2014', '1', '4', '25000')</p>
<p>Table: <code>SalesPerson</code></p>
<p>    +-----------------+---------+
    | Column Name     | Type    |
    +-----------------+---------+
    | sales_id        | int     |
    | name            | varchar |
    | salary          | int     |
    | commission_rate | int     |
    | hire_date       | date    |
    +-----------------+---------+
    sales_id is the primary key column for this table.
    Each row of this table indicates the name and the ID of a salesperson alongside their salary, commission rate, and hire date.</p>
<p>Table: <code>Company</code></p>
<p>    +-------------+---------+
    | Column Name | Type    |
    +-------------+---------+
    | com_id      | int     |
    | name        | varchar |
    | city        | varchar |
    +-------------+---------+
    com_id is the primary key column for this table.
    Each row of this table indicates the name and the ID of a company and the city in which the company is located.</p>
<p>Table: <code>Orders</code></p>
<p>    +-------------+------+
    | Column Name | Type |
    +-------------+------+
    | order_id    | int  |
    | order_date  | date |
    | com_id      | int  |
    | sales_id    | int  |
    | amount      | int  |
    +-------------+------+
    order_id is the primary key column for this table.
    com_id is a foreign key to com_id from the Company table.
    sales_id is a foreign key to sales_id from the SalesPerson table.
    Each row of this table contains information about one order. This includes the ID of the company, the ID of the salesperson, the date of the order, and the amount paid.</p>
<p>Write an SQL query to report the names of all the salespersons who did not have any orders related to the company with the name <strong>"RED"</strong>.</p>
<p>Return the result table in <strong>any order</strong>.</p>
<p>The query result format is in the following example.</p>
<p>Example 1:</p>
<p>    Input:
    SalesPerson table:
    +----------+------+--------+-----------------+------------+
    | sales_id | name | salary | commission_rate | hire_date  |
    +----------+------+--------+-----------------+------------+
    | 1        | John | 100000 | 6               | 4/1/2006   |
    | 2        | Amy  | 12000  | 5               | 5/1/2010   |
    | 3        | Mark | 65000  | 12              | 12/25/2008 |
    | 4        | Pam  | 25000  | 25              | 1/1/2005   |
    | 5        | Alex | 5000   | 10              | 2/3/2007   |
    +----------+------+--------+-----------------+------------+
    Company table:
    +--------+--------+----------+
    | com_id | name   | city     |
    +--------+--------+----------+
    | 1      | RED    | Boston   |
    | 2      | ORANGE | New York |
    | 3      | YELLOW | Boston   |
    | 4      | GREEN  | Austin   |
    +--------+--------+----------+
    Orders table:
    +----------+------------+--------+----------+--------+
    | order_id | order_date | com_id | sales_id | amount |
    +----------+------------+--------+----------+--------+
    | 1        | 1/1/2014   | 3      | 4        | 10000  |
    | 2        | 2/1/2014   | 4      | 5        | 5000   |
    | 3        | 3/1/2014   | 1      | 1        | 50000  |
    | 4        | 4/1/2014   | 1      | 4        | 25000  |
    +----------+------------+--------+----------+--------+
    Output:
    +------+
    | name |
    +------+
    | Amy  |
    | Mark |
    | Alex |
    +------+
    Explanation:
    According to orders 3 and 4 in the Orders table, it is easy to tell that only salesperson John and Pam have sales to company RED, so we report all the other names in the table salesperson.</p>
<h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<p>這邊使用了 SubQuery 來篩選條件，我們可以先思考子條件</p>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-mysql">MySQL</h4>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> s.name
<span class="hljs-keyword">FROM</span> salesperson s
<span class="hljs-keyword">WHERE</span> s.sales_id <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">IN</span> (
        <span class="hljs-keyword">SELECT</span> o.sales_id
        <span class="hljs-keyword">FROM</span> orders o
            <span class="hljs-keyword">LEFT</span> <span class="hljs-keyword">JOIN</span> company c <span class="hljs-keyword">ON</span> o.com_id = c.com_id
        <span class="hljs-keyword">WHERE</span> c.name = <span class="hljs-string">'RED'</span>
    );
</code></pre>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 1158. Market Analysis I]]></title><description><![CDATA[1158. Market Analysis I
題目敘述
SQL Schema >
    Create table If Not Exists Users (user_id int, join_date date, favorite_brand varchar(10))
    Create table If Not Exists Orders (order_id int, order_date date, item_id int, buyer_id int, seller_id int)
 ...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-1158-market-analysis-i</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-1158-market-analysis-i</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Sun, 12 Mar 2023 23:28:17 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-1158-market-analysis-ihttpsleetcodecomproblemsmarket-analysis-i"><a target="_blank" href="https://leetcode.com/problems/market-analysis-i/">1158. Market Analysis I</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema &gt;</p>
<p>    Create table If Not Exists Users (user_id int, join_date date, favorite_brand varchar(10))
    Create table If Not Exists Orders (order_id int, order_date date, item_id int, buyer_id int, seller_id int)
    Create table If Not Exists Items (item_id int, item_brand varchar(10))
    Truncate table Users
    insert into Users (user_id, join_date, favorite_brand) values ('1', '2018-01-01', 'Lenovo')
    insert into Users (user_id, join_date, favorite_brand) values ('2', '2018-02-09', 'Samsung')
    insert into Users (user_id, join_date, favorite_brand) values ('3', '2018-01-19', 'LG')
    insert into Users (user_id, join_date, favorite_brand) values ('4', '2018-05-21', 'HP')
    Truncate table Orders
    insert into Orders (order_id, order_date, item_id, buyer_id, seller_id) values ('1', '2019-08-01', '4', '1', '2')
    insert into Orders (order_id, order_date, item_id, buyer_id, seller_id) values ('2', '2018-08-02', '2', '1', '3')
    insert into Orders (order_id, order_date, item_id, buyer_id, seller_id) values ('3', '2019-08-03', '3', '2', '3')
    insert into Orders (order_id, order_date, item_id, buyer_id, seller_id) values ('4', '2018-08-04', '1', '4', '2')
    insert into Orders (order_id, order_date, item_id, buyer_id, seller_id) values ('5', '2018-08-04', '1', '3', '4')
    insert into Orders (order_id, order_date, item_id, buyer_id, seller_id) values ('6', '2019-08-05', '2', '2', '4')
    Truncate table Items
    insert into Items (item_id, item_brand) values ('1', 'Samsung')
    insert into Items (item_id, item_brand) values ('2', 'Lenovo')
    insert into Items (item_id, item_brand) values ('3', 'LG')
    insert into Items (item_id, item_brand) values ('4', 'HP')</p>
<p>Table: <code>Users</code></p>
<p>    +----------------+---------+
    | Column Name    | Type    |
    +----------------+---------+
    | user_id        | int     |
    | join_date      | date    |
    | favorite_brand | varchar |
    +----------------+---------+
    user_id is the primary key of this table.
    This table has the info of the users of an online shopping website where users can sell and buy items.</p>
<p>Table: <code>Orders</code></p>
<p>    +---------------+---------+
    | Column Name   | Type    |
    +---------------+---------+
    | order_id      | int     |
    | order_date    | date    |
    | item_id       | int     |
    | buyer_id      | int     |
    | seller_id     | int     |
    +---------------+---------+
    order_id is the primary key of this table.
    item_id is a foreign key to the Items table.
    buyer_id and seller_id are foreign keys to the Users table.</p>
<p>Table: <code>Items</code></p>
<p>    +---------------+---------+
    | Column Name   | Type    |
    +---------------+---------+
    | item_id       | int     |
    | item_brand    | varchar |
    +---------------+---------+
    item_id is the primary key of this table.</p>
<p>Write an SQL query to find for each user, the join date and the number of orders they made as a buyer in <code>2019</code>.</p>
<p>Return the result table in <strong>any order</strong>.</p>
<p>The query result format is in the following example.</p>
<p>Example 1:</p>
<p>    Input:
    Users table:
    +---------+------------+----------------+
    | user_id | join_date  | favorite_brand |
    +---------+------------+----------------+
    | 1       | 2018-01-01 | Lenovo         |
    | 2       | 2018-02-09 | Samsung        |
    | 3       | 2018-01-19 | LG             |
    | 4       | 2018-05-21 | HP             |
    +---------+------------+----------------+
    Orders table:
    +----------+------------+---------+----------+-----------+
    | order_id | order_date | item_id | buyer_id | seller_id |
    +----------+------------+---------+----------+-----------+
    | 1        | 2019-08-01 | 4       | 1        | 2         |
    | 2        | 2018-08-02 | 2       | 1        | 3         |
    | 3        | 2019-08-03 | 3       | 2        | 3         |
    | 4        | 2018-08-04 | 1       | 4        | 2         |
    | 5        | 2018-08-04 | 1       | 3        | 4         |
    | 6        | 2019-08-05 | 2       | 2        | 4         |
    +----------+------------+---------+----------+-----------+
    Items table:
    +---------+------------+
    | item_id | item_brand |
    +---------+------------+
    | 1       | Samsung    |
    | 2       | Lenovo     |
    | 3       | LG         |
    | 4       | HP         |
    +---------+------------+
    Output:
    +-----------+------------+----------------+
    | buyer_id  | join_date  | orders_in_2019 |
    +-----------+------------+----------------+
    | 1         | 2018-01-01 | 1              |
    | 2         | 2018-02-09 | 2              |
    | 3         | 2018-01-19 | 0              |
    | 4         | 2018-05-21 | 0              |
    +-----------+------------+----------------+</p>
<h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<p>這邊有三張表  Users, Orders, Items，找出每個使用者加入的時間和在 2019 年購買了多少訂單，不要求排序。</p>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<p>這邊有提到幾點說明為什麼不使用 WHERE 為什麼不使用 <code>ISNULL</code>，因為按照 SQL 執行的順序會是：</p>
<ol>
<li>FROM</li>
<li>WHERE</li>
<li>GROUP BY</li>
<li>HAVING</li>
<li>SELECT</li>
<li>ORDER BY</li>
</ol>
<p>如果我們在 WHERE 子句中使用 Year is 2019，它將在執行 GROUP BY 或 SELECT(COUNT)之前，先移除那些沒有在 2019 年下單的用戶，這意味著我們會錯過那些在 2019 年沒有下單但仍需要在最終結果集中包含的用戶，並為他們的 orders_in_2019 設置為 0。相反，我們使用 LEFT JOIN 來將 Users 表格與 Orders 表格連接起來，透過這個方式篩選出只有當 buyer_id 和 user_id 相符且 order_date 的年份為 2019 的行，這樣就能確保所有的用戶都包含在最終結果集中，即使他們在 2019 年沒有下單。</p>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-mysql">MySQL</h4>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> u.user_id <span class="hljs-keyword">AS</span> buyer_id,
    join_date,
    <span class="hljs-keyword">COUNT</span>(order_date) <span class="hljs-keyword">AS</span> orders_in_2019
<span class="hljs-keyword">FROM</span> <span class="hljs-keyword">Users</span> <span class="hljs-keyword">as</span> u
    <span class="hljs-keyword">LEFT</span> <span class="hljs-keyword">JOIN</span> Orders <span class="hljs-keyword">as</span> o <span class="hljs-keyword">ON</span> u.user_id = o.buyer_id
    <span class="hljs-keyword">AND</span> <span class="hljs-keyword">YEAR</span>(order_date) = <span class="hljs-string">'2019'</span>
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> u.user_id
</code></pre>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 1050. Actors and Directors Who Cooperated At Least Three Times]]></title><description><![CDATA[1050. Actors and Directors Who Cooperated At Least Three Times
題目敘述
SQL Schema >
    Create table If Not Exists ActorDirector (actor_id int, director_id int, timestamp int)
    Truncate table ActorDirector
    insert into ActorDirector (actor_id, dir...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-1050-actors-and-directors-who-cooperated-at-least-three-times</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-1050-actors-and-directors-who-cooperated-at-least-three-times</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Thu, 02 Feb 2023 11:38:31 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-1050-actors-and-directors-who-cooperated-at-least-three-timeshttpsleetcodecomproblemsactors-and-directors-who-cooperated-at-least-three-times"><a target="_blank" href="https://leetcode.com/problems/actors-and-directors-who-cooperated-at-least-three-times/">1050. Actors and Directors Who Cooperated At Least Three Times</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema &gt;</p>
<p>    Create table If Not Exists ActorDirector (actor_id int, director_id int, timestamp int)
    Truncate table ActorDirector
    insert into ActorDirector (actor_id, director_id, timestamp) values ('1', '1', '0')
    insert into ActorDirector (actor_id, director_id, timestamp) values ('1', '1', '1')
    insert into ActorDirector (actor_id, director_id, timestamp) values ('1', '1', '2')
    insert into ActorDirector (actor_id, director_id, timestamp) values ('1', '2', '3')
    insert into ActorDirector (actor_id, director_id, timestamp) values ('1', '2', '4')
    insert into ActorDirector (actor_id, director_id, timestamp) values ('2', '1', '5')
    insert into ActorDirector (actor_id, director_id, timestamp) values ('2', '1', '6')</p>
<p>Table: <code>ActorDirector</code></p>
<p>    +-------------+---------+
    | Column Name | Type    |
    +-------------+---------+
    | actor_id    | int     |
    | director_id | int     |
    | timestamp   | int     |
    +-------------+---------+
    timestamp is the primary key column for this table.</p>
<p>Write a SQL query for a report that provides the pairs <code>(actor_id, director_id)</code> where the actor has cooperated with the director at least three times.</p>
<p>Return the result table in <strong>any order</strong>.</p>
<p>The query result format is in the following example.</p>
<p><strong>Example 1:</strong></p>
<p>    Input:
    ActorDirector table:
    +-------------+-------------+-------------+
    | actor_id    | director_id | timestamp   |
    +-------------+-------------+-------------+
    | 1           | 1           | 0           |
    | 1           | 1           | 1           |
    | 1           | 1           | 2           |
    | 1           | 2           | 3           |
    | 1           | 2           | 4           |
    | 2           | 1           | 5           |
    | 2           | 1           | 6           |
    +-------------+-------------+-------------+
    Output:
    +-------------+-------------+
    | actor_id    | director_id |
    +-------------+-------------+
    | 1           | 1           |
    +-------------+-------------+
    Explanation: The only pair is (1, 1) where they cooperated exactly 3 times.</p>
<h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-mysql">MySQL</h4>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> actor_id,
    director_id
<span class="hljs-keyword">FROM</span> ActorDirector
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> actor_id,
    director_id
<span class="hljs-keyword">HAVING</span> <span class="hljs-keyword">count</span>(*) &gt;= <span class="hljs-number">3</span>;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 182. Duplicate Emails]]></title><description><![CDATA[182. Duplicate Emails
題目敘述
SQL Schema >
    Create table If Not Exists Person (id int, email varchar(255))
    Truncate table Person
    insert into Person (id, email) values ('1', 'a@b.com')
    insert into Person (id, email) values ('2', 'c@d.com')...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-182-duplicate-emails</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-182-duplicate-emails</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Thu, 02 Feb 2023 11:32:03 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-182-duplicate-emailshttpsleetcodecomproblemsduplicate-emails"><a target="_blank" href="https://leetcode.com/problems/duplicate-emails/">182. Duplicate Emails</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema &gt;</p>
<p>    Create table If Not Exists Person (id int, email varchar(255))
    Truncate table Person
    insert into Person (id, email) values ('1', 'a@b.com')
    insert into Person (id, email) values ('2', 'c@d.com')
    insert into Person (id, email) values ('3', 'a@b.com')</p>
<p>Table: <code>Person</code></p>
<p>    +-------------+---------+
    | Column Name | Type    |
    +-------------+---------+
    | id          | int     |
    | email       | varchar |
    +-------------+---------+
    id is the primary key column for this table.
    Each row of this table contains an email. The emails will not contain uppercase letters.</p>
<p>Write an SQL query to report all the duplicate emails.</p>
<p>Return the result table in <strong>any order</strong>.</p>
<p>The query result format is in the following example.</p>
<p><strong>Example 1:</strong></p>
<p>    Input:
    Person table:
    +----+---------+
    | id | email   |
    +----+---------+
    | 1  | a@b.com |
    | 2  | c@d.com |
    | 3  | a@b.com |
    +----+---------+
    Output:
    +---------+
    | Email   |
    +---------+
    | a@b.com |
    +---------+
    Explanation: a@b.com is repeated two times.</p>
<h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-mysql">MySQL</h4>
<pre><code class="lang-sql">
</code></pre>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 511. Game Play Analysis I]]></title><description><![CDATA[511. Game Play Analysis I
題目敘述
SQL Schema:
Create table If Not Exists Activity (player_id int, device_id int, event_date date, games_played int)
Truncate table Activity
insert into Activity (player_id, device_id, event_date, games_played) values ('1'...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-511-game-play-analysis-i</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-511-game-play-analysis-i</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Thu, 02 Feb 2023 11:26:47 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-511-game-play-analysis-ihttpsleetcodecomproblemsgame-play-analysis-i"><a target="_blank" href="https://leetcode.com/problems/game-play-analysis-i/">511. Game Play Analysis I</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema:</p>
<pre><code class="lang-SQL"><span class="hljs-keyword">Create</span> <span class="hljs-keyword">table</span> <span class="hljs-keyword">If</span> <span class="hljs-keyword">Not</span> <span class="hljs-keyword">Exists</span> Activity (player_id <span class="hljs-built_in">int</span>, device_id <span class="hljs-built_in">int</span>, event_date <span class="hljs-built_in">date</span>, games_played <span class="hljs-built_in">int</span>)
<span class="hljs-keyword">Truncate</span> <span class="hljs-keyword">table</span> Activity
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> Activity (player_id, device_id, event_date, games_played) <span class="hljs-keyword">values</span> (<span class="hljs-string">'1'</span>, <span class="hljs-string">'2'</span>, <span class="hljs-string">'2016-03-01'</span>, <span class="hljs-string">'5'</span>)
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> Activity (player_id, device_id, event_date, games_played) <span class="hljs-keyword">values</span> (<span class="hljs-string">'1'</span>, <span class="hljs-string">'2'</span>, <span class="hljs-string">'2016-05-02'</span>, <span class="hljs-string">'6'</span>)
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> Activity (player_id, device_id, event_date, games_played) <span class="hljs-keyword">values</span> (<span class="hljs-string">'2'</span>, <span class="hljs-string">'3'</span>, <span class="hljs-string">'2017-06-25'</span>, <span class="hljs-string">'1'</span>)
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> Activity (player_id, device_id, event_date, games_played) <span class="hljs-keyword">values</span> (<span class="hljs-string">'3'</span>, <span class="hljs-string">'1'</span>, <span class="hljs-string">'2016-03-02'</span>, <span class="hljs-string">'0'</span>)
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> Activity (player_id, device_id, event_date, games_played) <span class="hljs-keyword">values</span> (<span class="hljs-string">'3'</span>, <span class="hljs-string">'4'</span>, <span class="hljs-string">'2018-07-03'</span>, <span class="hljs-string">'5'</span>)
</code></pre>
<p>Table: <code>Activity</code></p>
<pre><code class="lang-text">+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| player_id    | int     |
| device_id    | int     |
| event_date   | date    |
| games_played | int     |
+--------------+---------+
(player_id, event_date) is the primary key of this table.
This table shows the activity of players of some games.
Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on someday using some device.
</code></pre>
<p>Write an SQL query to report the <strong>first login date</strong> for each player.</p>
<p>Return the result table in <strong>any order</strong>.</p>
<p>The query result format is in the following example.</p>
<p><strong>Example 1:</strong></p>
<pre><code class="lang-text">Input:
Activity table:
+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 1         | 2         | 2016-03-01 | 5            |
| 1         | 2         | 2016-05-02 | 6            |
| 2         | 3         | 2017-06-25 | 1            |
| 3         | 1         | 2016-03-02 | 0            |
| 3         | 4         | 2018-07-03 | 5            |
+-----------+-----------+------------+--------------+
Output:
+-----------+-------------+
| player_id | first_login |
+-----------+-------------+
| 1         | 2016-03-01  |
| 2         | 2017-06-25  |
| 3         | 2016-03-02  |
+-----------+-------------+
</code></pre>
<h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-mysql">MySQL</h4>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span>
    player_id,
    <span class="hljs-keyword">MIN</span>(event_date) <span class="hljs-keyword">AS</span> first_login
<span class="hljs-keyword">FROM</span>
    activity
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span>
    player_id
</code></pre>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 1729. Find Followers Count]]></title><description><![CDATA[1729. Find Followers Count
題目敘述
SQL Schema >
Create table If Not Exists Followers(user_id int, follower_id int)
Truncate table Followers
insert into Followers (user_id, follower_id) values ('0', '1')
insert into Followers (user_id, follower_id) value...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-1729-find-followers-count</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-1729-find-followers-count</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Mon, 30 Jan 2023 12:42:21 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-1729-find-followers-counthttpsleetcodecomproblemsfind-followers-count"><a target="_blank" href="https://leetcode.com/problems/find-followers-count/">1729. Find Followers Count</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema &gt;</p>
<pre><code>Create table If Not Exists Followers(user_id int, follower_id int)
Truncate table Followers
insert into Followers (user_id, follower_id) values (<span class="hljs-string">'0'</span>, <span class="hljs-string">'1'</span>)
insert into Followers (user_id, follower_id) values (<span class="hljs-string">'1'</span>, <span class="hljs-string">'0'</span>)
insert into Followers (user_id, follower_id) values (<span class="hljs-string">'2'</span>, <span class="hljs-string">'0'</span>)
insert into Followers (user_id, follower_id) values (<span class="hljs-string">'2'</span>, <span class="hljs-string">'1'</span>)
</code></pre><p>Table: <code>Followers</code></p>
<pre><code>+-------------+------+
| Column Name | Type |
+-------------+------+
| user_id     | int  |
| follower_id | int  |
+-------------+------+
(user_id, follower_id) is the primary key <span class="hljs-keyword">for</span> <span class="hljs-built_in">this</span> table.
This table contains the IDs <span class="hljs-keyword">of</span> a user and a follower <span class="hljs-keyword">in</span> a social media app where the follower follows the user.
</code></pre><p>Write an SQL query that will, for each user, return the number of followers.</p>
<p>Return the result table ordered by <code>user_id</code> in ascending order.</p>
<p>The query result format is in the following example.</p>
<p><strong>Example 1:</strong></p>
<pre><code>Input:
Followers table:
+---------+-------------+
| user_id | follower_id |
+---------+-------------+
| <span class="hljs-number">0</span>       | <span class="hljs-number">1</span>           |
| <span class="hljs-number">1</span>       | <span class="hljs-number">0</span>           |
| <span class="hljs-number">2</span>       | <span class="hljs-number">0</span>           |
| <span class="hljs-number">2</span>       | <span class="hljs-number">1</span>           |
+---------+-------------+
Output:
+---------+----------------+
| user_id | followers_count|
+---------+----------------+
| <span class="hljs-number">0</span>       | <span class="hljs-number">1</span>              |
| <span class="hljs-number">1</span>       | <span class="hljs-number">1</span>              |
| <span class="hljs-number">2</span>       | <span class="hljs-number">2</span>              |
+---------+----------------+
Explanation:
The followers <span class="hljs-keyword">of</span> <span class="hljs-number">0</span> are {<span class="hljs-number">1</span>}
The followers <span class="hljs-keyword">of</span> <span class="hljs-number">1</span> are {<span class="hljs-number">0</span>}
The followers <span class="hljs-keyword">of</span> <span class="hljs-number">2</span> are {<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}
</code></pre><h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<p>找出每個 <code>user_id</code> 有多少不重複的 <code>follower_id</code>，並且最後按照 <code>user_id</code> 做升冪排序</p>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<p>不重複 =&gt; DISTINCT, GROUP BY
升冪排序 =&gt; ORDER BY ASC</p>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-mysql">MySQL</h4>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> user_id,
    <span class="hljs-keyword">COUNT</span>(<span class="hljs-keyword">DISTINCT</span> follower_id) <span class="hljs-keyword">AS</span> followers_count
<span class="hljs-keyword">FROM</span> Followers
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> user_id
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> user_id <span class="hljs-keyword">ASC</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 1693. Daily Leads and Partners]]></title><description><![CDATA[1693. Daily Leads and Partners
題目敘述
SQL Schema >
Create table If Not Exists DailySales(date_id date, make_name varchar(20), lead_id int, partner_id int)
Truncate table DailySales
insert into DailySales (date_id, make_name, lead_id, partner_id) values...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-1693-daily-leads-and-partners</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-1693-daily-leads-and-partners</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Mon, 30 Jan 2023 12:31:30 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-1693-daily-leads-and-partnershttpsleetcodecomproblemsdaily-leads-and-partners"><a target="_blank" href="https://leetcode.com/problems/daily-leads-and-partners/">1693. Daily Leads and Partners</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema &gt;</p>
<pre><code>Create table If Not Exists DailySales(date_id date, make_name varchar(<span class="hljs-number">20</span>), lead_id int, partner_id int)
Truncate table DailySales
insert into DailySales (date_id, make_name, lead_id, partner_id) values (<span class="hljs-string">'2020-12-8'</span>, <span class="hljs-string">'toyota'</span>, <span class="hljs-string">'0'</span>, <span class="hljs-string">'1'</span>)
insert into DailySales (date_id, make_name, lead_id, partner_id) values (<span class="hljs-string">'2020-12-8'</span>, <span class="hljs-string">'toyota'</span>, <span class="hljs-string">'1'</span>, <span class="hljs-string">'0'</span>)
insert into DailySales (date_id, make_name, lead_id, partner_id) values (<span class="hljs-string">'2020-12-8'</span>, <span class="hljs-string">'toyota'</span>, <span class="hljs-string">'1'</span>, <span class="hljs-string">'2'</span>)
insert into DailySales (date_id, make_name, lead_id, partner_id) values (<span class="hljs-string">'2020-12-7'</span>, <span class="hljs-string">'toyota'</span>, <span class="hljs-string">'0'</span>, <span class="hljs-string">'2'</span>)
insert into DailySales (date_id, make_name, lead_id, partner_id) values (<span class="hljs-string">'2020-12-7'</span>, <span class="hljs-string">'toyota'</span>, <span class="hljs-string">'0'</span>, <span class="hljs-string">'1'</span>)
insert into DailySales (date_id, make_name, lead_id, partner_id) values (<span class="hljs-string">'2020-12-8'</span>, <span class="hljs-string">'honda'</span>, <span class="hljs-string">'1'</span>, <span class="hljs-string">'2'</span>)
insert into DailySales (date_id, make_name, lead_id, partner_id) values (<span class="hljs-string">'2020-12-8'</span>, <span class="hljs-string">'honda'</span>, <span class="hljs-string">'2'</span>, <span class="hljs-string">'1'</span>)
insert into DailySales (date_id, make_name, lead_id, partner_id) values (<span class="hljs-string">'2020-12-7'</span>, <span class="hljs-string">'honda'</span>, <span class="hljs-string">'0'</span>, <span class="hljs-string">'1'</span>)
insert into DailySales (date_id, make_name, lead_id, partner_id) values (<span class="hljs-string">'2020-12-7'</span>, <span class="hljs-string">'honda'</span>, <span class="hljs-string">'1'</span>, <span class="hljs-string">'2'</span>)
insert into DailySales (date_id, make_name, lead_id, partner_id) values (<span class="hljs-string">'2020-12-7'</span>, <span class="hljs-string">'honda'</span>, <span class="hljs-string">'2'</span>, <span class="hljs-string">'1'</span>)
</code></pre><p>Table: <code>DailySales</code></p>
<pre><code>+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| date_id     | date    |
| make_name   | varchar |
| lead_id     | int     |
| partner_id  | int     |
+-------------+---------+
This table does not have a primary key.
This table contains the date and the name <span class="hljs-keyword">of</span> the product sold and the IDs <span class="hljs-keyword">of</span> the lead and partner it was sold to.
The name consists <span class="hljs-keyword">of</span> only lowercase English letters.
</code></pre><p>Write an SQL query that will, for each <code>date_id</code> and <code>make_name</code>, return the number of distinct <code>lead_id</code>'s and distinct <code>partner_id</code>'s.</p>
<p>Return the result table in any order.</p>
<p>The query result format is in the following example.</p>
<p><strong>Example 1:</strong></p>
<pre><code>Input:
DailySales table:
+-----------+-----------+---------+------------+
| date_id   | make_name | lead_id | partner_id |
+-----------+-----------+---------+------------+
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-8</span> | toyota    | <span class="hljs-number">0</span>       | <span class="hljs-number">1</span>          |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-8</span> | toyota    | <span class="hljs-number">1</span>       | <span class="hljs-number">0</span>          |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-8</span> | toyota    | <span class="hljs-number">1</span>       | <span class="hljs-number">2</span>          |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-7</span> | toyota    | <span class="hljs-number">0</span>       | <span class="hljs-number">2</span>          |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-7</span> | toyota    | <span class="hljs-number">0</span>       | <span class="hljs-number">1</span>          |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-8</span> | honda     | <span class="hljs-number">1</span>       | <span class="hljs-number">2</span>          |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-8</span> | honda     | <span class="hljs-number">2</span>       | <span class="hljs-number">1</span>          |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-7</span> | honda     | <span class="hljs-number">0</span>       | <span class="hljs-number">1</span>          |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-7</span> | honda     | <span class="hljs-number">1</span>       | <span class="hljs-number">2</span>          |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-7</span> | honda     | <span class="hljs-number">2</span>       | <span class="hljs-number">1</span>          |
+-----------+-----------+---------+------------+
Output:
+-----------+-----------+--------------+-----------------+
| date_id   | make_name | unique_leads | unique_partners |
+-----------+-----------+--------------+-----------------+
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-8</span> | toyota    | <span class="hljs-number">2</span>            | <span class="hljs-number">3</span>               |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-7</span> | toyota    | <span class="hljs-number">1</span>            | <span class="hljs-number">2</span>               |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-8</span> | honda     | <span class="hljs-number">2</span>            | <span class="hljs-number">2</span>               |
| <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-7</span> | honda     | <span class="hljs-number">3</span>            | <span class="hljs-number">2</span>               |
+-----------+-----------+--------------+-----------------+
Explanation:
For <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-8</span>, toyota gets leads = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>] and partners = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>] <span class="hljs-keyword">while</span> honda gets leads = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>] and partners = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>].
For <span class="hljs-number">2020</span><span class="hljs-number">-12</span><span class="hljs-number">-7</span>, toyota gets leads = [<span class="hljs-number">0</span>] and partners = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>] <span class="hljs-keyword">while</span> honda gets leads = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>] and partners = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>].
</code></pre><h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<p>要從資料表 <code>DailySales</code> 中取出每個 <code>date_id</code> 和 <code>make_name</code> 的組合中，不重複的 <code>lead_id</code> 和 <code>partner_id</code> 總數。</p>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<p>光看到不重複的第一直覺就是要使用到 <code>DISTINCT</code>，然後再來是有組合的，就會需要搭配使用 <code>GROUP BY</code> 了。最後因為要算個數所以再搭配使用 <code>COUNT</code> 來做計算</p>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-mysql">MySQL</h4>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> date_id,
    make_name,
    <span class="hljs-keyword">COUNT</span>(<span class="hljs-keyword">DISTINCT</span> lead_id) <span class="hljs-keyword">AS</span> unique_leads,
    <span class="hljs-keyword">COUNT</span>(<span class="hljs-keyword">DISTINCT</span> partner_id) <span class="hljs-keyword">AS</span> unique_partners
<span class="hljs-keyword">FROM</span> DailySales
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> date_id,
    make_name
</code></pre>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 1873. Calculate Special Bonus]]></title><description><![CDATA[1873. Calculate Special Bonus
題目敘述
SQL Schema >
Create table If Not Exists Employees (employee_id int, name varchar(30), salary int)
Truncate table Employees
insert into Employees (employee_id, name, salary) values ('2', 'Meir', '3000')
insert into E...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-1873-calculate-special-bonus</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-1873-calculate-special-bonus</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Wed, 04 Jan 2023 01:00:44 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-1873-calculate-special-bonushttpsleetcodecomproblemscalculate-special-bonus"><a target="_blank" href="https://leetcode.com/problems/calculate-special-bonus/">1873. Calculate Special Bonus</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema &gt;</p>
<pre><code>Create table If Not Exists Employees (employee_id int, name varchar(<span class="hljs-number">30</span>), salary int)
Truncate table Employees
insert into Employees (employee_id, name, salary) values (<span class="hljs-string">'2'</span>, <span class="hljs-string">'Meir'</span>, <span class="hljs-string">'3000'</span>)
insert into Employees (employee_id, name, salary) values (<span class="hljs-string">'3'</span>, <span class="hljs-string">'Michael'</span>, <span class="hljs-string">'3800'</span>)
insert into Employees (employee_id, name, salary) values (<span class="hljs-string">'7'</span>, <span class="hljs-string">'Addilyn'</span>, <span class="hljs-string">'7400'</span>)
insert into Employees (employee_id, name, salary) values (<span class="hljs-string">'8'</span>, <span class="hljs-string">'Juan'</span>, <span class="hljs-string">'6100'</span>)
insert into Employees (employee_id, name, salary) values (<span class="hljs-string">'9'</span>, <span class="hljs-string">'Kannon'</span>, <span class="hljs-string">'7700'</span>)
</code></pre><p>Table: <code>Employees</code></p>
<pre><code>+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| employee_id | int     |
| name        | varchar |
| salary      | int     |
+-------------+---------+
employee_id is the primary key <span class="hljs-keyword">for</span> <span class="hljs-built_in">this</span> table.
Each row <span class="hljs-keyword">of</span> <span class="hljs-built_in">this</span> table indicates the employee ID, employee name, and salary.
</code></pre><p>Write an SQL query to calculate the bonus of each employee. The bonus of an employee is <code>100%</code> of their salary if the ID of the employee is <strong>an odd number</strong> and <strong>the employee's name does not start with the character</strong> <code>'M'</code>. The bonus of an employee is <code>0</code> otherwise.</p>
<p>Return the result table ordered by <code>employee_id</code>.</p>
<p>The query result format is in the following example.</p>
<p>Example 1:</p>
<pre><code>Input:
Employees table:
+-------------+---------+--------+
| employee_id | name    | salary |
+-------------+---------+--------+
| <span class="hljs-number">2</span>           | Meir    | <span class="hljs-number">3000</span>   |
| <span class="hljs-number">3</span>           | Michael | <span class="hljs-number">3800</span>   |
| <span class="hljs-number">7</span>           | Addilyn | <span class="hljs-number">7400</span>   |
| <span class="hljs-number">8</span>           | Juan    | <span class="hljs-number">6100</span>   |
| <span class="hljs-number">9</span>           | Kannon  | <span class="hljs-number">7700</span>   |
+-------------+---------+--------+
Output:
+-------------+-------+
| employee_id | bonus |
+-------------+-------+
| <span class="hljs-number">2</span>           | <span class="hljs-number">0</span>     |
| <span class="hljs-number">3</span>           | <span class="hljs-number">0</span>     |
| <span class="hljs-number">7</span>           | <span class="hljs-number">7400</span>  |
| <span class="hljs-number">8</span>           | <span class="hljs-number">0</span>     |
| <span class="hljs-number">9</span>           | <span class="hljs-number">7700</span>  |
+-------------+-------+
Explanation:
The employees <span class="hljs-keyword">with</span> IDs <span class="hljs-number">2</span> and <span class="hljs-number">8</span> get <span class="hljs-number">0</span> bonus because they have an even employee_id.
The employee <span class="hljs-keyword">with</span> ID <span class="hljs-number">3</span> gets <span class="hljs-number">0</span> bonus because their name starts <span class="hljs-keyword">with</span> <span class="hljs-string">'M'</span>.
The rest <span class="hljs-keyword">of</span> the employees get a <span class="hljs-number">100</span>% bonus.
</code></pre><h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<p>從資料表 <code>Employees</code> 計算出每個員工的獎金，其中如果員工的 ID 是奇數且員工名稱字首不是 <code>M</code> 開頭，則獎金會為 0。最後回傳員工 ID 和獎金。</p>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<p>這題需要使用條件式的判斷來選擇最後要回傳的獎金是不是 0，這裡範例使用了 <code>IF</code> 函數和 <code>CASE</code> 來處理。</p>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-sql">SQL</h4>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> employee_id,
    <span class="hljs-keyword">IF</span>(
        employee_id % <span class="hljs-number">2</span> = <span class="hljs-number">1</span>
        <span class="hljs-keyword">AND</span> <span class="hljs-keyword">name</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'M%'</span>,
        salary,
        <span class="hljs-number">0</span>
    ) <span class="hljs-keyword">AS</span> bonus
<span class="hljs-keyword">FROM</span> <span class="hljs-string">`Employees`</span>
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> employee_id;
</code></pre>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> employee_id,
    <span class="hljs-keyword">CASE</span>
        <span class="hljs-keyword">WHERE</span> employee_id %<span class="hljs-number">2</span> &lt;&gt; <span class="hljs-number">0</span>
            <span class="hljs-keyword">AND</span> <span class="hljs-keyword">name</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'M%'</span> <span class="hljs-keyword">THEN</span> salary
            <span class="hljs-keyword">ELSE</span> <span class="hljs-number">0</span>
    <span class="hljs-keyword">END</span> <span class="hljs-keyword">AS</span> bonus
<span class="hljs-keyword">FROM</span> <span class="hljs-string">`Employees`</span>
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> employee_id;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 1757. Recyclable and Low Fat Products]]></title><description><![CDATA[1757. Recyclable and Low Fat Products
題目敘述
SQL Schema >
Create table If Not Exists Products (product_id int, low_fats ENUM('Y', 'N'), recyclable ENUM('Y','N'))
Truncate table Products
insert into Products (product_id, low_fats, recyclable) values ('0...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-1757-recyclable-and-low-fat-products</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-1757-recyclable-and-low-fat-products</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Tue, 03 Jan 2023 01:00:42 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-1757-recyclable-and-low-fat-productshttpsleetcodecomproblemsrecyclable-and-low-fat-products"><a target="_blank" href="https://leetcode.com/problems/recyclable-and-low-fat-products/">1757. Recyclable and Low Fat Products</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema &gt;</p>
<pre><code>Create table If Not Exists Products (product_id int, low_fats ENUM(<span class="hljs-string">'Y'</span>, <span class="hljs-string">'N'</span>), recyclable ENUM(<span class="hljs-string">'Y'</span>,<span class="hljs-string">'N'</span>))
Truncate table Products
insert into Products (product_id, low_fats, recyclable) values (<span class="hljs-string">'0'</span>, <span class="hljs-string">'Y'</span>, <span class="hljs-string">'N'</span>)
insert into Products (product_id, low_fats, recyclable) values (<span class="hljs-string">'1'</span>, <span class="hljs-string">'Y'</span>, <span class="hljs-string">'Y'</span>)
insert into Products (product_id, low_fats, recyclable) values (<span class="hljs-string">'2'</span>, <span class="hljs-string">'N'</span>, <span class="hljs-string">'Y'</span>)
insert into Products (product_id, low_fats, recyclable) values (<span class="hljs-string">'3'</span>, <span class="hljs-string">'Y'</span>, <span class="hljs-string">'Y'</span>)
insert into Products (product_id, low_fats, recyclable) values (<span class="hljs-string">'4'</span>, <span class="hljs-string">'N'</span>, <span class="hljs-string">'N'</span>)
</code></pre><p>Table: <code>Products</code></p>
<pre><code>+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| product_id  | int     |
| low_fats    | enum    |
| recyclable  | enum    |
+-------------+---------+
product_id is the primary key <span class="hljs-keyword">for</span> <span class="hljs-built_in">this</span> table.
low_fats is an ENUM <span class="hljs-keyword">of</span> type (<span class="hljs-string">'Y'</span>, <span class="hljs-string">'N'</span>) where <span class="hljs-string">'Y'</span> means <span class="hljs-built_in">this</span> product is low fat and <span class="hljs-string">'N'</span> means it is not.
recyclable is an ENUM <span class="hljs-keyword">of</span> types (<span class="hljs-string">'Y'</span>, <span class="hljs-string">'N'</span>) where <span class="hljs-string">'Y'</span> means <span class="hljs-built_in">this</span> product is recyclable and <span class="hljs-string">'N'</span> means it is not.
</code></pre><p>Write an SQL query to find the ids of products that are both low fat and recyclable.</p>
<p>Return the result table in <strong>any order</strong>.</p>
<p>The query result format is in the following example.</p>
<p>Example 1:</p>
<pre><code>Input:
Products table:
+-------------+----------+------------+
| product_id  | low_fats | recyclable |
+-------------+----------+------------+
| <span class="hljs-number">0</span>           | Y        | N          |
| <span class="hljs-number">1</span>           | Y        | Y          |
| <span class="hljs-number">2</span>           | N        | Y          |
| <span class="hljs-number">3</span>           | Y        | Y          |
| <span class="hljs-number">4</span>           | N        | N          |
+-------------+----------+------------+
Output:
+-------------+
| product_id  |
+-------------+
| <span class="hljs-number">1</span>           |
| <span class="hljs-number">3</span>           |
+-------------+
Explanation: Only products <span class="hljs-number">1</span> and <span class="hljs-number">3</span> are both low fat and recyclable.
</code></pre><h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<p>從資料表 <code>Products</code> 找出所有可以回收且低脂肪的產品 id，並且不需考慮排序。</p>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<p>很間單的 <code>WHERE</code> 篩選。</p>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-sql">SQL</h4>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> product_id
<span class="hljs-keyword">FROM</span> <span class="hljs-string">`Products`</span>
<span class="hljs-keyword">WHERE</span> low_fats = <span class="hljs-string">"Y"</span>
    <span class="hljs-keyword">AND</span> recyclable = <span class="hljs-string">"Y"</span>;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 595. Big Countries]]></title><description><![CDATA[595. Big Countries
題目敘述
SQL Schema >
Create table If Not Exists World (name varchar(255), continent varchar(255), area int, population int, gdp int)
Truncate table World
insert into World (name, continent, area, population, gdp) values ('Afghanistan'...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-595-big-countries</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-595-big-countries</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Mon, 02 Jan 2023 01:00:42 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-595-big-countrieshttpsleetcodecomproblemsbig-countries"><a target="_blank" href="https://leetcode.com/problems/big-countries/">595. Big Countries</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema &gt;</p>
<pre><code>Create table If Not Exists World (name varchar(<span class="hljs-number">255</span>), continent varchar(<span class="hljs-number">255</span>), area int, population int, gdp int)
Truncate table World
insert into World (name, continent, area, population, gdp) values (<span class="hljs-string">'Afghanistan'</span>, <span class="hljs-string">'Asia'</span>, <span class="hljs-string">'652230'</span>, <span class="hljs-string">'25500100'</span>, <span class="hljs-string">'20343000000'</span>)
insert into World (name, continent, area, population, gdp) values (<span class="hljs-string">'Albania'</span>, <span class="hljs-string">'Europe'</span>, <span class="hljs-string">'28748'</span>, <span class="hljs-string">'2831741'</span>, <span class="hljs-string">'12960000000'</span>)
insert into World (name, continent, area, population, gdp) values (<span class="hljs-string">'Algeria'</span>, <span class="hljs-string">'Africa'</span>, <span class="hljs-string">'2381741'</span>, <span class="hljs-string">'37100000'</span>, <span class="hljs-string">'188681000000'</span>)
insert into World (name, continent, area, population, gdp) values (<span class="hljs-string">'Andorra'</span>, <span class="hljs-string">'Europe'</span>, <span class="hljs-string">'468'</span>, <span class="hljs-string">'78115'</span>, <span class="hljs-string">'3712000000'</span>)
insert into World (name, continent, area, population, gdp) values (<span class="hljs-string">'Angola'</span>, <span class="hljs-string">'Africa'</span>, <span class="hljs-string">'1246700'</span>, <span class="hljs-string">'20609294'</span>, <span class="hljs-string">'100990000000'</span>)
</code></pre><p>Table: <code>World</code></p>
<pre><code>+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| name        | varchar |
| continent   | varchar |
| area        | int     |
| population  | int     |
| gdp         | int     |
+-------------+---------+
name is the primary key column <span class="hljs-keyword">for</span> <span class="hljs-built_in">this</span> table.
Each row <span class="hljs-keyword">of</span> <span class="hljs-built_in">this</span> table gives information about the name <span class="hljs-keyword">of</span> a country, the continent to which it belongs, its area, the population, and its GDP value.
</code></pre><p>A country is <strong>big</strong> if:</p>
<ul>
<li>it has an area of at least three million (i.e., <code>3000000 km2</code>), or</li>
<li>it has a population of at least twenty-five million (i.e., <code>25000000</code>).</li>
</ul>
<p>Write an SQL query to report the name, population, and area of the <strong>big countries</strong>.</p>
<p>Return the result table in <strong>any order</strong>.</p>
<p>The query result format is in the following example.</p>
<p>Example 1:</p>
<pre><code>Input:
World table:
+-------------+-----------+---------+------------+--------------+
| name        | continent | area    | population | gdp          |
+-------------+-----------+---------+------------+--------------+
| Afghanistan | Asia      | <span class="hljs-number">652230</span>  | <span class="hljs-number">25500100</span>   | <span class="hljs-number">20343000000</span>  |
| Albania     | Europe    | <span class="hljs-number">28748</span>   | <span class="hljs-number">2831741</span>    | <span class="hljs-number">12960000000</span>  |
| Algeria     | Africa    | <span class="hljs-number">2381741</span> | <span class="hljs-number">37100000</span>   | <span class="hljs-number">188681000000</span> |
| Andorra     | Europe    | <span class="hljs-number">468</span>     | <span class="hljs-number">78115</span>      | <span class="hljs-number">3712000000</span>   |
| Angola      | Africa    | <span class="hljs-number">1246700</span> | <span class="hljs-number">20609294</span>   | <span class="hljs-number">100990000000</span> |
+-------------+-----------+---------+------------+--------------+
Output:
+-------------+------------+---------+
| name        | population | area    |
+-------------+------------+---------+
| Afghanistan | <span class="hljs-number">25500100</span>   | <span class="hljs-number">652230</span>  |
| Algeria     | <span class="hljs-number">37100000</span>   | <span class="hljs-number">2381741</span> |
+-------------+------------+---------+
</code></pre><h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<p>從資料表 <code>World</code> 找出大城市並回傳其 <code>name</code>, <code>population</code>, <code>area</code>，並且不須排序。而大城市的定義是：</p>
<ul>
<li>區域面積至少 3,000,000</li>
<li>人口數至少 25,000,000</li>
</ul>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-sql">SQL</h4>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">name</span>,
    population,
    area
<span class="hljs-keyword">FROM</span> <span class="hljs-string">`World`</span>
<span class="hljs-keyword">WHERE</span> area &gt;= <span class="hljs-number">3000000</span>
    <span class="hljs-keyword">OR</span> population &gt;= <span class="hljs-number">25000000</span>;
</code></pre>
<p>第二種寫法沒有特別的必要，只是寫來表示也是有這種寫法，就是用 <code>UNION</code> 來連結兩個 Query。</p>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">name</span>,
    population,
    area
<span class="hljs-keyword">FROM</span> <span class="hljs-string">`World`</span>
<span class="hljs-keyword">WHERE</span> area &gt;= <span class="hljs-number">3000000</span>
<span class="hljs-keyword">UNION</span>
<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">name</span>,
    population,
    area
<span class="hljs-keyword">FROM</span> <span class="hljs-string">`World`</span>
<span class="hljs-keyword">WHERE</span> population &gt;= <span class="hljs-number">25000000</span>;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 584. Find Customer Referee]]></title><description><![CDATA[584. Find Customer Referee
題目敘述
SQL Schema >
Create table If Not Exists Customer (id int, name varchar(25), referee_id int)
Truncate table Customer
insert into Customer (id, name, referee_id) values ('1', 'Will', 'None')
insert into Customer (id, nam...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-584-find-customer-referee</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-584-find-customer-referee</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Sun, 01 Jan 2023 09:00:42 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-584-find-customer-refereehttpsleetcodecomproblemsfind-customer-referee"><a target="_blank" href="https://leetcode.com/problems/find-customer-referee/">584. Find Customer Referee</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>SQL Schema &gt;</p>
<pre><code>Create table If Not Exists Customer (id int, name varchar(<span class="hljs-number">25</span>), referee_id int)
Truncate table Customer
insert into Customer (id, name, referee_id) values (<span class="hljs-string">'1'</span>, <span class="hljs-string">'Will'</span>, <span class="hljs-string">'None'</span>)
insert into Customer (id, name, referee_id) values (<span class="hljs-string">'2'</span>, <span class="hljs-string">'Jane'</span>, <span class="hljs-string">'None'</span>)
insert into Customer (id, name, referee_id) values (<span class="hljs-string">'3'</span>, <span class="hljs-string">'Alex'</span>, <span class="hljs-string">'2'</span>)
insert into Customer (id, name, referee_id) values (<span class="hljs-string">'4'</span>, <span class="hljs-string">'Bill'</span>, <span class="hljs-string">'None'</span>)
insert into Customer (id, name, referee_id) values (<span class="hljs-string">'5'</span>, <span class="hljs-string">'Zack'</span>, <span class="hljs-string">'1'</span>)
insert into Customer (id, name, referee_id) values (<span class="hljs-string">'6'</span>, <span class="hljs-string">'Mark'</span>, <span class="hljs-string">'2'</span>)
</code></pre><p>Table: <code>Customer</code></p>
<pre><code>+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| name        | varchar |
| referee_id  | int     |
+-------------+---------+
id is the primary key column <span class="hljs-keyword">for</span> <span class="hljs-built_in">this</span> table.
Each row <span class="hljs-keyword">of</span> <span class="hljs-built_in">this</span> table indicates the id <span class="hljs-keyword">of</span> a customer, their name, and the id <span class="hljs-keyword">of</span> the customer who referred them.
</code></pre><p>Write an SQL query to report the names of the customer that are <strong>not referred by</strong> the customer with <code>id = 2</code>.</p>
<p>Return the result table in <strong>any order</strong>.</p>
<p>The query result format is in the following example.</p>
<p>Example 1:</p>
<pre><code>Input:
Customer table:
+----+------+------------+
| id | name | referee_id |
+----+------+------------+
| <span class="hljs-number">1</span>  | Will | <span class="hljs-literal">null</span>       |
| <span class="hljs-number">2</span>  | Jane | <span class="hljs-literal">null</span>       |
| <span class="hljs-number">3</span>  | Alex | <span class="hljs-number">2</span>          |
| <span class="hljs-number">4</span>  | Bill | <span class="hljs-literal">null</span>       |
| <span class="hljs-number">5</span>  | Zack | <span class="hljs-number">1</span>          |
| <span class="hljs-number">6</span>  | Mark | <span class="hljs-number">2</span>          |
+----+------+------------+
Output:
+------+
| name |
+------+
| Will |
| Jane |
| Bill |
| Zack |
+------+
</code></pre><h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<p>現在有一張資料表 <code>Customer</code>，編寫一個 SQL Query 在不要求排序的情況下找出，沒有連接到 <code>id = 2</code> 的 customer。</p>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<p>基本上就是簡單的用 <code>WHERE</code> 關鍵字來篩選即可，需要注意的就是其中 <code>referee_id</code> 是有 <code>NULL</code> 的值，如果只單純用 <code>&lt;&gt; 2</code> 或 <code>!= 2</code> 會沒有辦法比對出來。所以需要再加上 <code>IS NULL</code> 的條件。</p>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-sql">SQL</h4>
<pre><code class="lang-sql"><span class="hljs-comment"># Write your MySQL query statement below</span>
<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">name</span>
<span class="hljs-keyword">FROM</span> <span class="hljs-string">`Customer`</span>
<span class="hljs-keyword">WHERE</span> referee_id &lt;&gt; <span class="hljs-number">2</span>
    <span class="hljs-keyword">OR</span> referee_id <span class="hljs-keyword">IS</span> <span class="hljs-literal">NULL</span>;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[至 2022 為止個人的軟體技術觀察]]></title><description><![CDATA[前言
要年末的，最近都在忙工作沒有好好的更新 Blog 都要生草了，該來寫點東西了。表示自己還活著呢。
Frontend
覺得開始出現有別於以往御三家的狀態，開始有些人嘗試打破現狀，出現了些滿有意思的 Framework 像是 Qwik。還有因為 Compile 的新工具 Vite 而有其對抗的 Nextjs 的 Turbopack（難怪在 GitHub 一直有人叫他支援 Vite，就是死都不要。原來自己搞了一套）。覺得另外一個滿有看點的就是 Deno 宣佈將會開始往支援 npm 的方向靠攏，會...]]></description><link>https://blog.taiwolskit.com/2022-software-technology-development-observation</link><guid isPermaLink="true">https://blog.taiwolskit.com/2022-software-technology-development-observation</guid><category><![CDATA[technology]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Sun, 25 Dec 2022 06:31:33 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-5ymn6kia">前言</h1>
<p>要年末的，最近都在忙工作沒有好好的更新 Blog 都要生草了，該來寫點東西了。表示自己還活著呢。</p>
<h2 id="heading-frontend">Frontend</h2>
<p>覺得開始出現有別於以往御三家的狀態，開始有些人嘗試打破現狀，出現了些滿有意思的 Framework 像是 Qwik。還有因為 Compile 的新工具 Vite 而有其對抗的 Nextjs 的 Turbopack（難怪在 GitHub 一直有人叫他支援 Vite，就是死都不要。原來自己搞了一套）。覺得另外一個滿有看點的就是 Deno 宣佈將會開始往支援 npm 的方向靠攏，會不會有大批的人員從 Nodejs 加入，還不好說但覺得也是個有可能的發展。</p>
<p>個人並不特別看好 TypeScript，經歷過早期的 CoffeeScript 時期，目前覺得 TypeScript 就是新一代的 CoffeeScript，等到 JavaScript 的迭代應該就會將其優點加入。到頭來你還是需要好好的先把 JavaScript 先寫好再說。後續未來發展覺得重點會是慢慢開始往 micro frontend 和 WASM 靠攏，再來就是預期會有更多的 Lite ML 的加入。</p>
<h2 id="heading-backend">Backend</h2>
<p>Rust 的蓬勃發展的算是有擠壓到 Go 的範疇，也算是有把 C 家族的人帶進來。但我覺得其學習曲線還是有點高，可能發展上還會有些需要再調整的。Go 的泛型還不是很完善，但總是有在進步。個人滿期許 Kotlin 在跨平台到 Server Side 的可能性，但是目前覺得還沒有很爆炸性的成長和實例。</p>
<p>個人覺得在 Backend 伺服器的語言選擇上，會比較推薦 Node.js、Python 和 Java 作為優先的選擇。可能跟個人經驗有關，在常常需要串接第三方服務，像是 Google、Facebook 等。常常會有的 SDK 這三種語言是最常見的，且社群的發展的套件也是多樣在早期找尋 Solution 會比較方便。</p>
<p>MariaDB 居然上市了？坦白說自己還沒什麼聽到比較有名的使用上跟 MySQL 的差異或優勢。如果真的要選擇更優異的還可能直接去選擇 PostgreSQL。</p>
<p>在於監控上比較有看頭的就是 Grafana 體系了，有別於過去大眾的選擇 ELK 體系，Grafana 也開始自成一個系列依序的提供了 Loki、Tempo、Mimir 等，對於 ELK 體系應該挺有壓力的。</p>
<h2 id="heading-cloud">Cloud</h2>
<p>Cloud 上目前的三強鼎立（其實應該沒有鼎立），GCP 感覺就還是維持他的砸錢買服務整併的策略，但是在 Cotainer 服務上還是幾乎是首選。AWS 的 EKS 真的就是個半殘品，其他的 Container 服務也是差不多。但是 AWS 的厲害之處就是服務的多樣和各種 Open Source的選擇。個人滿佩服的就是搞定出 macOS 的 EC2，之前要弄 Apple 系列的 CI/CD 就是要買台裝置在公司內，現在真的有機會完全 Cloud 了。再來是過去 GCP 可以說有台灣機房，但是現在 AWS 也有提供台灣 Local Zone 了，其優勢也被略減。</p>
<p>未來 Cloud 服務的發展應該會依舊的往 ML Data 的處理和多雲管理的方向走。</p>
<p>目前感覺：</p>
<ul>
<li><p>AWS 依舊強勁</p>
</li>
<li><p>Azure 微軟體系首選，穩定發展</p>
</li>
<li><p>GCP 容器化首選，拼裝車</p>
</li>
</ul>
<h2 id="heading-mobile">Mobile</h2>
<p>Swift 的發展目前略微擔心，之前有爆出大佬出走，批評內部決策的問題。希望是能好好發展。Kotlin 感覺是個還在耕耘跨平台的方向，但是 Google 目前秘密研製的 FuchsiaOS。未來 Google 會不會正式 GA FuchsiaOS 後屏棄 Android 系統，不再以 Kotlin 為首選還是難說呢。</p>
<h2 id="heading-sre">SRE</h2>
<p>Kubernetes 依舊橫掃全場，沒有什麼好說的。依舊的強勁，目前還沒有其他的對手出現。但是手動建制和維運還是相當困難的一件事（畢竟本身服務就很複雜了），還是建議直接使用雲端服務吧。</p>
<p>在 Infrastructure As Code 的領域，HashiCorp 系列也依然強勁，尤其是與 AWS 合作推出的 cdktf 讓其觸角更延伸了。但是還是希望 terraform 本身可以好好學習一下 terragrunt 的優點，當服務一大之後那個要 plan 或 apply state 真的是很久且 dependency 容易出錯。或是拓展出 plugin 的系統，可以有更多的變化。</p>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Medium, 198. House Robber]]></title><description><![CDATA[198. House Robber
題目敘述
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems con...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-medium-198-house-robber</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-medium-198-house-robber</guid><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[programming]]></category><category><![CDATA[Dynamic Programming]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Mon, 24 Oct 2022 14:21:15 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-198-house-robberhttpsleetcodecomproblemshouse-robber"><a target="_blank" href="https://leetcode.com/problems/house-robber/">198. House Robber</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and <strong>it will automatically contact the police if two adjacent houses were broken into on the same night</strong>.</p>
<p>Given an integer array <code>nums</code> representing the amount of money of each house, return <em>the maximum amount of money you can rob tonight <strong>without alerting the police</strong></em>.</p>
<p><strong>Example 1:</strong></p>
<pre><code>Input: nums = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">1</span>]
<span class="hljs-attr">Output</span>: <span class="hljs-number">4</span>
<span class="hljs-attr">Explanation</span>: Rob house <span class="hljs-number">1</span> (money = <span class="hljs-number">1</span>) and then rob house <span class="hljs-number">3</span> (money = <span class="hljs-number">3</span>).
Total amount you can rob = <span class="hljs-number">1</span> + <span class="hljs-number">3</span> = <span class="hljs-number">4.</span>
</code></pre><p><strong>Example 2:</strong></p>
<pre><code>Input: nums = [<span class="hljs-number">2</span>,<span class="hljs-number">7</span>,<span class="hljs-number">9</span>,<span class="hljs-number">3</span>,<span class="hljs-number">1</span>]
<span class="hljs-attr">Output</span>: <span class="hljs-number">12</span>
<span class="hljs-attr">Explanation</span>: Rob house <span class="hljs-number">1</span> (money = <span class="hljs-number">2</span>), rob house <span class="hljs-number">3</span> (money = <span class="hljs-number">9</span>) and rob house <span class="hljs-number">5</span> (money = <span class="hljs-number">1</span>).
Total amount you can rob = <span class="hljs-number">2</span> + <span class="hljs-number">9</span> + <span class="hljs-number">1</span> = <span class="hljs-number">12.</span>
</code></pre><p><strong>Constraints:</strong></p>
<ul>
<li><code>1 &lt;= nums.length &lt;= 100</code></li>
<li><code>0 &lt;= nums[i] &lt;= 400</code></li>
</ul>
<h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<p>假設你是一個專業的搶匪，今天的目標是要搶劫一條街上的房子。每個房子都有防盜系統，其條件是當同一晚相鄰的兩間房子都被闖入時會報警。給定一個陣列 <code>nums</code>，每個索引代表每間房子最多可以搶到多少錢。計算出最多可以搶到多少錢。</p>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<p>其解法可以分為三種：Recursion、Iteration 和空間優化後的 Iteration。因為搶了第一間房子的話就不能搶第二間，解答是依據每次的選擇堆疊而成的。所以是典型的 Dynamic programming 問題。</p>
<p>主要的關鍵邏輯就是，每次選擇房子的時候是拿後面兩個來比較。目前在 i = 0 的位置，因為搶了 i = 0 的房子的話，就不能搶 i = 1 的房子。這樣的話至少 <code>i[0] + i[2]</code> &gt;= i[1]<code>才比較有效益，不然的話就是選擇</code>i[1]` 的房子了。每次的選擇都是基於此條件，最後堆疊出最後的答案。</p>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-go">Go</h4>
<h5 id="heading-recursion-with-memoization">Recursion with Memoization</h5>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">rob</span><span class="hljs-params">(nums []<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(nums) == <span class="hljs-number">0</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
    }
    <span class="hljs-keyword">var</span> memo <span class="hljs-keyword">map</span>[<span class="hljs-keyword">int</span>]<span class="hljs-keyword">int</span> = <span class="hljs-built_in">make</span>(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">int</span>]<span class="hljs-keyword">int</span>, <span class="hljs-built_in">len</span>(nums))
    <span class="hljs-keyword">return</span> robFrom(memo, <span class="hljs-number">0</span>, nums)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">robFrom</span><span class="hljs-params">(memo <span class="hljs-keyword">map</span>[<span class="hljs-keyword">int</span>]<span class="hljs-keyword">int</span>, i <span class="hljs-keyword">int</span>, nums []<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">if</span> i &gt;= <span class="hljs-built_in">len</span>(nums) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
    }

    <span class="hljs-keyword">if</span> _, ok := memo[i]; ok {
        <span class="hljs-keyword">return</span> memo[i]
    }
    <span class="hljs-keyword">if</span> robFrom(memo, i+<span class="hljs-number">1</span>, nums) &gt; robFrom(memo, i+<span class="hljs-number">2</span>, nums)+nums[i] {
        memo[i] = robFrom(memo, i+<span class="hljs-number">1</span>, nums)
    } <span class="hljs-keyword">else</span> {
        memo[i] = robFrom(memo, i+<span class="hljs-number">2</span>, nums) + nums[i]
    }
    <span class="hljs-keyword">return</span> memo[i]
}
</code></pre>
<h5 id="heading-dynamic-programming">Dynamic Programming</h5>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">rob</span><span class="hljs-params">(nums []<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(nums) == <span class="hljs-number">0</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
    }

    <span class="hljs-keyword">var</span> N <span class="hljs-keyword">int</span> = <span class="hljs-built_in">len</span>(nums)
    <span class="hljs-keyword">var</span> maxRobbedAmount []<span class="hljs-keyword">int</span> = <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">int</span>, N+<span class="hljs-number">1</span>)

    maxRobbedAmount[N], maxRobbedAmount[N<span class="hljs-number">-1</span>] = <span class="hljs-number">0</span>, nums[N<span class="hljs-number">-1</span>]
    <span class="hljs-keyword">for</span> i := N - <span class="hljs-number">2</span>; i &gt;= <span class="hljs-number">0</span>; i-- {
        <span class="hljs-keyword">if</span> maxRobbedAmount[i+<span class="hljs-number">1</span>] &gt; maxRobbedAmount[i+<span class="hljs-number">2</span>]+nums[i] {
            maxRobbedAmount[i] = maxRobbedAmount[i+<span class="hljs-number">1</span>]
        } <span class="hljs-keyword">else</span> {
            maxRobbedAmount[i] = maxRobbedAmount[i+<span class="hljs-number">2</span>] + nums[i]
        }
    }
    <span class="hljs-keyword">return</span> maxRobbedAmount[<span class="hljs-number">0</span>]
}
</code></pre>
<h5 id="heading-optimized-dynamic-programming">Optimized Dynamic Programming</h5>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">rob</span><span class="hljs-params">(nums []<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(nums) == <span class="hljs-number">0</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
    }
    <span class="hljs-keyword">var</span> N <span class="hljs-keyword">int</span> = <span class="hljs-built_in">len</span>(nums)
    <span class="hljs-keyword">var</span> robNext, robNextPlusOne <span class="hljs-keyword">int</span> = nums[N<span class="hljs-number">-1</span>], <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> i := N - <span class="hljs-number">2</span>; i &gt;= <span class="hljs-number">0</span>; i-- {
        <span class="hljs-keyword">if</span> robNext &gt; robNextPlusOne+nums[i] {
            robNext, robNextPlusOne = robNext, robNext
        } <span class="hljs-keyword">else</span> {
            robNext, robNextPlusOne = robNextPlusOne+nums[i], robNext
        }
    }
    <span class="hljs-keyword">return</span> robNext
}
</code></pre>
<h4 id="heading-javascript">JavaScript</h4>
<h5 id="heading-recursion-with-memoization">Recursion with Memoization</h5>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number}</span></span>
 */</span>
<span class="hljs-keyword">const</span> rob = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">nums</span>) </span>{
    <span class="hljs-keyword">const</span> memo = {};

    <span class="hljs-keyword">const</span> robFrom = <span class="hljs-function">(<span class="hljs-params">i, rob_nums</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (i &gt;= rob_nums.length) {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        }
        <span class="hljs-keyword">if</span> (i <span class="hljs-keyword">in</span> memo) {
            <span class="hljs-keyword">return</span> memo[i];
        }
        <span class="hljs-keyword">const</span> ans = <span class="hljs-built_in">Math</span>.max(rob_nums[i] + robFrom(i + <span class="hljs-number">2</span>, rob_nums), robFrom(i + <span class="hljs-number">1</span>, rob_nums));
        memo[i] = ans;
        <span class="hljs-keyword">return</span> ans;
    };

    <span class="hljs-keyword">return</span> robFrom(<span class="hljs-number">0</span>, nums);
};
</code></pre>
<h5 id="heading-dynamic-programming">Dynamic Programming</h5>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number}</span></span>
 */</span>
<span class="hljs-keyword">const</span> rob = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">nums</span>) </span>{
    <span class="hljs-keyword">if</span> (!nums) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-keyword">const</span> N = nums.length;
    <span class="hljs-keyword">const</span> maxRobbedAmount = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(N + <span class="hljs-number">1</span>).fill(<span class="hljs-number">0</span>);
    maxRobbedAmount[N] = <span class="hljs-number">0</span>;
    maxRobbedAmount[N - <span class="hljs-number">1</span>] = nums[N - <span class="hljs-number">1</span>];

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = N - <span class="hljs-number">2</span>; i &gt;= <span class="hljs-number">0</span>; i--) {
        maxRobbedAmount[i] = <span class="hljs-built_in">Math</span>.max(nums[i] + maxRobbedAmount[i + <span class="hljs-number">2</span>], maxRobbedAmount[i + <span class="hljs-number">1</span>]);
    }
    <span class="hljs-keyword">return</span> maxRobbedAmount[<span class="hljs-number">0</span>];
};
</code></pre>
<h5 id="heading-optimized-dynamic-programming">Optimized Dynamic Programming</h5>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number}</span></span>
 */</span>
<span class="hljs-keyword">const</span> rob = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">nums</span>) </span>{
    <span class="hljs-keyword">if</span> (!nums) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-keyword">const</span> N = nums.length;
    <span class="hljs-keyword">let</span> robNextPlusOne = <span class="hljs-number">0</span>,
        robNext = nums[N - <span class="hljs-number">1</span>];

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = N - <span class="hljs-number">2</span>; i &gt;= <span class="hljs-number">0</span>; i--) {
        <span class="hljs-keyword">const</span> current = <span class="hljs-built_in">Math</span>.max(robNext, robNextPlusOne + nums[i]);
        robNextPlusOne = robNext;
        robNext = current;
    }
    <span class="hljs-keyword">return</span> robNext;
};
</code></pre>
<h4 id="heading-kotlin">Kotlin</h4>
<h5 id="heading-recursion-with-memoization">Recursion with Memoization</h5>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> memo: MutableMap&lt;<span class="hljs-built_in">Int</span>, <span class="hljs-built_in">Int</span>&gt;

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">rob</span><span class="hljs-params">(nums: <span class="hljs-type">IntArray</span>)</span></span>: <span class="hljs-built_in">Int</span> {
        memo = mutableMapOf()
        <span class="hljs-keyword">return</span> robFrom(<span class="hljs-number">0</span>, nums)
    }

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">robFrom</span><span class="hljs-params">(i: <span class="hljs-type">Int</span>, nums: <span class="hljs-type">IntArray</span>)</span></span>: <span class="hljs-built_in">Int</span> {
        <span class="hljs-keyword">if</span> (i &gt;= nums.size) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
        <span class="hljs-keyword">if</span> (memo[i] != <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> memo[i]!!
        <span class="hljs-keyword">val</span> res = Math.max(robFrom(i + <span class="hljs-number">1</span>, nums), nums[i] + robFrom(i + <span class="hljs-number">2</span>, nums))
        memo[i] = res
        <span class="hljs-keyword">return</span> res
    }
}
</code></pre>
<h5 id="heading-dynamic-programming">Dynamic Programming</h5>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">rob</span><span class="hljs-params">(nums: <span class="hljs-type">IntArray</span>)</span></span>: <span class="hljs-built_in">Int</span> {
        <span class="hljs-keyword">if</span> (nums.size == <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
        }

        <span class="hljs-keyword">val</span> N: <span class="hljs-built_in">Int</span> = nums.size
        <span class="hljs-keyword">var</span> maxRobbedAmount: IntArray = IntArray(N + <span class="hljs-number">1</span>)
        maxRobbedAmount[N] = <span class="hljs-number">0</span>
        maxRobbedAmount[N - <span class="hljs-number">1</span>] = nums[N - <span class="hljs-number">1</span>]
        <span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> N - <span class="hljs-number">2</span> downTo <span class="hljs-number">0</span>) {
            maxRobbedAmount[i] = Math.max(maxRobbedAmount[i + <span class="hljs-number">1</span>], maxRobbedAmount[i + <span class="hljs-number">2</span>] + nums[i])
        }
        <span class="hljs-keyword">return</span> maxRobbedAmount[<span class="hljs-number">0</span>]
    }
}
</code></pre>
<h5 id="heading-optimized-dynamic-programming">Optimized Dynamic Programming</h5>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">rob</span><span class="hljs-params">(nums: <span class="hljs-type">IntArray</span>)</span></span>: <span class="hljs-built_in">Int</span> {
        <span class="hljs-keyword">if</span> (nums.size == <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
        }

        <span class="hljs-keyword">val</span> N: <span class="hljs-built_in">Int</span> = nums.size
        <span class="hljs-keyword">var</span> robNext: <span class="hljs-built_in">Int</span> = nums[N - <span class="hljs-number">1</span>]
        <span class="hljs-keyword">var</span> robNextPlusOne: <span class="hljs-built_in">Int</span> = <span class="hljs-number">0</span>
        <span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> N - <span class="hljs-number">2</span> downTo <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">val</span> current: <span class="hljs-built_in">Int</span> = Math.max(robNext, robNextPlusOne + nums[i])
            robNextPlusOne = robNext
            robNext = current
        }
        <span class="hljs-keyword">return</span> robNext
    }
}
</code></pre>
<h4 id="heading-php">PHP</h4>
<h5 id="heading-recursion-with-memoization">Recursion with Memoization</h5>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>
</span>{
    <span class="hljs-keyword">private</span> $memo = [];

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> Integer[] $nums
     * <span class="hljs-doctag">@return</span> Integer
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rob</span>(<span class="hljs-params">$nums</span>)
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;robFrom(<span class="hljs-number">0</span>, $nums);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">robFrom</span>(<span class="hljs-params">$i, $nums</span>)
    </span>{
        <span class="hljs-keyword">if</span> ($i &gt;= count($nums)) {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        }
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>(<span class="hljs-keyword">$this</span>-&gt;memo[$i])) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;memo[$i];
        }
        $ans = max(<span class="hljs-keyword">$this</span>-&gt;robFrom($i + <span class="hljs-number">1</span>, $nums), <span class="hljs-keyword">$this</span>-&gt;robFrom($i + <span class="hljs-number">2</span>, $nums) + $nums[$i]);
        <span class="hljs-keyword">$this</span>-&gt;memo[$i] = $ans;
        <span class="hljs-keyword">return</span> $ans;
    }
}
</code></pre>
<h5 id="heading-dynamic-programming">Dynamic Programming</h5>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>
</span>{
    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> Integer[] $nums
     * <span class="hljs-doctag">@return</span> Integer
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rob</span>(<span class="hljs-params">$nums</span>)
    </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">empty</span>($nums)) {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        }
        $N = count($nums);
        $maxRobbedAmount = array_fill(<span class="hljs-number">0</span>, $N + <span class="hljs-number">1</span>, <span class="hljs-number">0</span>);
        $maxRobbedAmount[$N] = <span class="hljs-number">0</span>;
        $maxRobbedAmount[$N - <span class="hljs-number">1</span>] = $nums[$N - <span class="hljs-number">1</span>];
        <span class="hljs-keyword">for</span> ($i = $N - <span class="hljs-number">2</span>; $i &gt;= <span class="hljs-number">0</span>; $i--) {
            $maxRobbedAmount[$i] = max($maxRobbedAmount[$i + <span class="hljs-number">1</span>], $maxRobbedAmount[$i + <span class="hljs-number">2</span>] + $nums[$i]);
        }
        <span class="hljs-keyword">return</span> $maxRobbedAmount[<span class="hljs-number">0</span>];
    }
}
</code></pre>
<h5 id="heading-optimized-dynamic-programming">Optimized Dynamic Programming</h5>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>
</span>{
    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> Integer[] $nums
     * <span class="hljs-doctag">@return</span> Integer
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rob</span>(<span class="hljs-params">$nums</span>)
    </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">empty</span>($nums)) {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        }
        $N = count($nums);
        $robNext = $nums[$N - <span class="hljs-number">1</span>];
        $robNextPlusOne = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> ($i = $N - <span class="hljs-number">2</span>; $i &gt;= <span class="hljs-number">0</span>; $i--) {
            $current = max($robNext, $robNextPlusOne + $nums[$i]);
            $robNextPlusOne = $robNext;
            $robNext = $current;
        }
        <span class="hljs-keyword">return</span> $robNext;
    }
}
</code></pre>
<h4 id="heading-python">Python</h4>
<h5 id="heading-recursion-with-memoization">Recursion with Memoization</h5>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        self.memo: dict[int, int] = {}

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">rob</span>(<span class="hljs-params">self, nums: list[int]</span>) -&gt; int:</span>
        self.memo = {}
        <span class="hljs-keyword">return</span> self.robFrom(<span class="hljs-number">0</span>, nums)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">robFrom</span>(<span class="hljs-params">self, i: int, nums: list[int]</span>) -&gt; int:</span>
        <span class="hljs-comment"># No more houses left to examine.</span>
        <span class="hljs-keyword">if</span> i &gt;= len(nums):
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>

        <span class="hljs-comment"># Return cached value.</span>
        <span class="hljs-keyword">if</span> i <span class="hljs-keyword">in</span> self.memo:
            <span class="hljs-keyword">return</span> self.memo[i]

        <span class="hljs-comment"># Recursive relation evaluation to get the optimal answer.</span>
        ans: int = max(self.robFrom(i + <span class="hljs-number">1</span>, nums), self.robFrom(i + <span class="hljs-number">2</span>, nums) + nums[i])

        <span class="hljs-comment"># Cache for future use.</span>
        self.memo[i] = ans
        <span class="hljs-keyword">return</span> ans
</code></pre>
<h5 id="heading-dynamic-programming">Dynamic Programming</h5>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">rob</span>(<span class="hljs-params">self, nums: list[int]</span>) -&gt; int:</span>
        <span class="hljs-comment"># Special handling for empty case.</span>
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> nums:
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>

        N: int = len(nums)
        maxRobbedAmount: list[int | <span class="hljs-literal">None</span>] = [<span class="hljs-literal">None</span> <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(N + <span class="hljs-number">1</span>)]

        <span class="hljs-comment"># Base case initialization.</span>
        maxRobbedAmount[N], maxRobbedAmount[N - <span class="hljs-number">1</span>] = <span class="hljs-number">0</span>, nums[N - <span class="hljs-number">1</span>]

        <span class="hljs-comment"># DP table calculations.</span>
        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(N - <span class="hljs-number">2</span>, <span class="hljs-number">-1</span>, <span class="hljs-number">-1</span>):

            <span class="hljs-comment"># Same as recursive solution.</span>
            maxRobbedAmount[i] = max(
                maxRobbedAmount[i + <span class="hljs-number">1</span>], maxRobbedAmount[i + <span class="hljs-number">2</span>] + nums[i]
            )

        <span class="hljs-keyword">return</span> maxRobbedAmount[<span class="hljs-number">0</span>]
</code></pre>
<h5 id="heading-optimized-dynamic-programming">Optimized Dynamic Programming</h5>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">rob</span>(<span class="hljs-params">self, nums: list[int]</span>) -&gt; int:</span>

        <span class="hljs-comment"># Special handling for empty case.</span>
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> nums:
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>

        N: int = len(nums)

        rob_next_plus_one: int = <span class="hljs-number">0</span>
        rob_next: int = nums[N - <span class="hljs-number">1</span>]

        <span class="hljs-comment"># DP table calculations.</span>
        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(N - <span class="hljs-number">2</span>, <span class="hljs-number">-1</span>, <span class="hljs-number">-1</span>):

            <span class="hljs-comment"># Same as recursive solution.</span>
            current: int = max(rob_next, rob_next_plus_one + nums[i])

            <span class="hljs-comment"># Update the variables</span>
            rob_next_plus_one = rob_next
            rob_next = current

        <span class="hljs-keyword">return</span> rob_next
</code></pre>
<h4 id="heading-rust">Rust</h4>
<pre><code class="lang-rust">
</code></pre>
<h4 id="heading-swift">Swift</h4>
<h5 id="heading-recursion-with-memoization">Recursion with Memoization</h5>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{

    <span class="hljs-keyword">var</span> memo: [<span class="hljs-type">Int</span>: <span class="hljs-type">Int</span>] = [<span class="hljs-type">Int</span>: <span class="hljs-type">Int</span>]()

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">rob</span><span class="hljs-params">(<span class="hljs-number">_</span> nums: [Int])</span></span> -&gt; <span class="hljs-type">Int</span> {
        <span class="hljs-keyword">return</span> robFrom(<span class="hljs-number">0</span>, nums: nums)
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">robFrom</span><span class="hljs-params">(<span class="hljs-number">_</span> i: Int, nums: [Int])</span></span> -&gt; <span class="hljs-type">Int</span> {
        <span class="hljs-keyword">if</span> i &gt;= nums.<span class="hljs-built_in">count</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
        }
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> memoized: <span class="hljs-type">Int</span> = memo[i] {
            <span class="hljs-keyword">return</span> memoized
        }
        <span class="hljs-keyword">let</span> result: <span class="hljs-type">Int</span> = <span class="hljs-built_in">max</span>(robFrom(i + <span class="hljs-number">1</span>, nums: nums), nums[i] + robFrom(i + <span class="hljs-number">2</span>, nums: nums))
        memo[i] = result
        <span class="hljs-keyword">return</span> result
    }
}
</code></pre>
<h5 id="heading-dynamic-programming">Dynamic Programming</h5>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">rob</span><span class="hljs-params">(<span class="hljs-number">_</span> nums: [Int])</span></span> -&gt; <span class="hljs-type">Int</span> {
        <span class="hljs-keyword">if</span> nums.<span class="hljs-built_in">count</span> == <span class="hljs-number">0</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
        }

        <span class="hljs-keyword">let</span> <span class="hljs-type">N</span>: <span class="hljs-type">Int</span> = nums.<span class="hljs-built_in">count</span>
        <span class="hljs-keyword">var</span> maxRobbedAmount: [<span class="hljs-type">Int</span>] = <span class="hljs-type">Array</span>(repeating: <span class="hljs-number">0</span>, <span class="hljs-built_in">count</span>: <span class="hljs-type">N</span> + <span class="hljs-number">1</span>)
        maxRobbedAmount[<span class="hljs-type">N</span>] = <span class="hljs-number">0</span>
        maxRobbedAmount[<span class="hljs-type">N</span> - <span class="hljs-number">1</span>] = nums[<span class="hljs-type">N</span> - <span class="hljs-number">1</span>]

        <span class="hljs-keyword">for</span> i: <span class="hljs-type">Int</span> <span class="hljs-keyword">in</span> (<span class="hljs-number">0</span>..&lt;<span class="hljs-type">N</span> - <span class="hljs-number">1</span>).reversed() {
            maxRobbedAmount[i] = <span class="hljs-built_in">max</span>(maxRobbedAmount[i + <span class="hljs-number">1</span>], nums[i] + maxRobbedAmount[i + <span class="hljs-number">2</span>])
        }

        <span class="hljs-keyword">return</span> maxRobbedAmount[<span class="hljs-number">0</span>]
    }
}
</code></pre>
<h5 id="heading-optimized-dynamic-programming">Optimized Dynamic Programming</h5>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">rob</span><span class="hljs-params">(<span class="hljs-number">_</span> nums: [Int])</span></span> -&gt; <span class="hljs-type">Int</span> {
        <span class="hljs-keyword">if</span> nums.<span class="hljs-built_in">count</span> == <span class="hljs-number">0</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
        }

        <span class="hljs-keyword">let</span> <span class="hljs-type">N</span>: <span class="hljs-type">Int</span> = nums.<span class="hljs-built_in">count</span>
        <span class="hljs-keyword">var</span> robNextPlusOne: <span class="hljs-type">Int</span> = <span class="hljs-number">0</span>
        <span class="hljs-keyword">var</span> robNext: <span class="hljs-type">Int</span> = nums[<span class="hljs-type">N</span> - <span class="hljs-number">1</span>]

        <span class="hljs-keyword">for</span> i: <span class="hljs-type">Int</span> <span class="hljs-keyword">in</span> (<span class="hljs-number">0</span>..&lt;<span class="hljs-type">N</span> - <span class="hljs-number">1</span>).reversed() {
            <span class="hljs-keyword">let</span> current: <span class="hljs-type">Int</span> = <span class="hljs-built_in">max</span>(robNext, nums[i] + robNextPlusOne)
            robNextPlusOne = robNext
            robNext = current
        }
        <span class="hljs-keyword">return</span> robNext
    }
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[AWS - How I set up my EKS]]></title><description><![CDATA[Intro
This article is for recording how I set up the AWS EKS for the team.
Here are my requirements.

I could use SSM and SSH keys to access EKS workers from a bastion instance.
All EKS add-ons could install and work.
ALB could create and accept requ...]]></description><link>https://blog.taiwolskit.com/aws-how-i-set-up-my-eks</link><guid isPermaLink="true">https://blog.taiwolskit.com/aws-how-i-set-up-my-eks</guid><category><![CDATA[EKS]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Kubernetes]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Mon, 29 Aug 2022 02:00:44 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-intro">Intro</h1>
<p>This article is for recording how I set up the AWS EKS for the team.</p>
<p>Here are my requirements.</p>
<ul>
<li>I could use SSM and SSH keys to access EKS workers from a bastion instance.</li>
<li>All EKS add-ons could install and work.</li>
<li>ALB could create and accept requests from the internet.</li>
<li>Worker will only host at the private subnet.</li>
</ul>
<p>Here is my network architecture.</p>
<ul>
<li>Build a two-tier network on VPC.</li>
<li>Build a bastion instance on the public subnet.</li>
</ul>
<p><img src="https://docs.aws.amazon.com/vpc/latest/userguide/images/public-nat-gateway-diagram.png" alt="Two-tier network" /></p>
<h2 id="heading-1-set-up-authorize">1. Set up authorize</h2>
<p>Before setting up an EKS, we must prepare the IAM role and security groups for services.</p>
<h3 id="heading-iam">IAM</h3>
<ul>
<li>EKS Master</li>
<li>EKS Worker</li>
<li>Vertical Pod Autoscaler</li>
<li>Application Load Balancer</li>
</ul>
<p>According to <a target="_blank" href="https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html">AWS doc</a></p>
<p>Due to VPA and ALB will use IRSA, therefore we need to wait for EKS creation to finish, then create OIDC. So the IAM role for VPA and ALB will be created later.</p>
<h4 id="heading-role-for-eks-master">Role for EKS Master</h4>
<p>Trust policy：</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
    <span class="hljs-attr">"Statement"</span>: [
        {
            <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
            <span class="hljs-attr">"Principal"</span>: {
                <span class="hljs-attr">"Service"</span>: <span class="hljs-string">"eks.amazonaws.com"</span>
            },
            <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"sts:AssumeRole"</span>
        }
    ]
}
</code></pre>
<p>And attach the policies：</p>
<ul>
<li><code>AmazonEKSClusterPolicy</code>.</li>
</ul>
<h4 id="heading-role-for-eks-worker">Role for EKS Worker</h4>
<p>Trust policy：</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
    <span class="hljs-attr">"Statement"</span>: [
        {
            <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
            <span class="hljs-attr">"Principal"</span>: {
                <span class="hljs-attr">"Service"</span>: <span class="hljs-string">"ec2.amazonaws.com"</span>
            },
            <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"sts:AssumeRole"</span>
        }
    ]
}
</code></pre>
<p>And attach the policies：</p>
<ul>
<li><code>AmazonEBSCSIDriverPolicy</code>, for add-on EBS</li>
<li><code>AmazonEC2ContainerRegistryReadOnly</code>, for ECR</li>
<li><code>AmazonEKS_CNI_Policy</code>, for add-on VPC CNI, if you use IPv6 then you need to create the policy yourself.</li>
<li><code>AmazonEKSWorkerNodePolicy</code>, for EKS worker</li>
<li><code>AmazonSSMManagedInstanceCore</code>, for session manager</li>
</ul>
<h3 id="heading-security-group">Security Group</h3>
<ul>
<li>EKS Master</li>
<li>EKS Worker</li>
</ul>
<p>EKS will create default security groups for the master and node. But I want use the default one, therefore I create other to manage.</p>
<p>Here are the rules.</p>
<h4 id="heading-security-group-for-eks-master">Security group for EKS Master</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Type</td><td>Source</td><td>Protocol</td><td>Port</td></tr>
</thead>
<tbody>
<tr>
<td>Inbound</td><td>Self</td><td>All traffic</td><td>All</td></tr>
<tr>
<td>Inbound</td><td>Bastion</td><td>TCP</td><td>22</td></tr>
<tr>
<td>Inbound</td><td>Bastion</td><td>TCP</td><td>443</td></tr>
<tr>
<td>Outbound</td><td></td><td>All traffic</td><td>0.0.0.0/0</td></tr>
<tr>
<td>Outbound</td><td></td><td>All traffic</td><td>::/0</td></tr>
</tbody>
</table>
</div><h4 id="heading-security-group-for-eks-worker">Security group for EKS Worker</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Type</td><td>Source</td><td>Protocol</td><td>Port</td></tr>
</thead>
<tbody>
<tr>
<td>Inbound</td><td>Self</td><td>All traffic</td><td>All</td></tr>
<tr>
<td>Inbound</td><td>EKS Master</td><td>TCP</td><td>443</td></tr>
<tr>
<td>Inbound</td><td>Bastion</td><td>TCP</td><td>22</td></tr>
<tr>
<td>Outbound</td><td></td><td>All traffic</td><td>0.0.0.0/0</td></tr>
<tr>
<td>Outbound</td><td></td><td>All traffic</td><td>::/0</td></tr>
</tbody>
</table>
</div><h2 id="heading-2-build-up-kubernetes">2. Build up Kubernetes</h2>
<p>At this step, I will use terraform to create the EKS, including OIDC with EKS. You could check the demo at this <a target="_blank" href="https://github.com/Taiwolskit/tf-eks-demo">repository</a>.</p>
<blockquote>
<p>Note: Adot will install fail, we will add the required settings in the next steps. My demo includes creating OIDC.</p>
</blockquote>
<p>After creation, we could run this command to get credential to kubeconfig.</p>
<pre><code class="lang-shell">aws eks update-kubeconfig --region &lt;REGION&gt; --name &lt;CLUSTER_NAME&gt;
</code></pre>
<h2 id="heading-3-add-add-on-and-services">3. Add Add-On and services</h2>
<p>After EKS is created, we will need to add some services to make our services better.</p>
<h3 id="heading-metrics-server">Metrics Server</h3>
<p>This is a very important component in EKS. Horizontal Pod Autoscaler and Vertical Pod Autoscaler depend on this. So we need to install it first.</p>
<pre><code class="lang-shell">kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
kubectl get deployment metrics-server -n kube-system
</code></pre>
<h4 id="heading-reference">Reference</h4>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/eks/latest/userguide/metrics-server.html">Installing the Kubernetes Metrics Server</a></li>
</ul>
<h3 id="heading-aws-distro-for-opentelemetry">AWS Distro for OpenTelemetry</h3>
<ol>
<li><p>Create a Service account &amp; Namespace for Adot</p>
<pre><code class="lang-shell"> kubectl apply -f https://amazon-eks.s3.amazonaws.com/docs/addons-otel-permissions.yaml
 kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml
</code></pre>
</li>
<li><p>Create IRSA for Adot</p>
<pre><code class="lang-shell"> eksctl create iamserviceaccount \
     --name adot-collector \
     --namespace &lt;NAMESPACE&gt; \
     --cluster &lt;CLUSTER_NAME&gt; \
     --attach-policy-arn arn:aws:iam::aws:policy/AmazonPrometheusRemoteWriteAccess \
     --attach-policy-arn arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess \
     --attach-policy-arn arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy \
     --approve \
     --override-existing-serviceaccounts
</code></pre>
</li>
<li><p>Install collector</p>
<ul>
<li>CloudWatch<ul>
<li>Download YAML：<code>curl -o collector-config-cloudwatch.yaml https://raw.githubusercontent.com/aws-observability/aws-otel-community/master/sample-configs/operator/collector-config-cloudwatch.yaml</code></li>
<li>Replace values<ul>
<li>serviceAccount: Check this value should be the same as the previous name field <code>adot-collector</code></li>
<li>value: <code>&lt;YOUR_EKS_CLUSTER_NAME&gt;</code></li>
<li>region: <code>&lt;YOUR_AWS_REGION&gt;</code></li>
<li>name: Check this value should be the same as the previous name field <code>adot-collector</code></li>
</ul>
</li>
<li>Apply YAML：<code>kubectl apply -f collector-config-cloudwatch.yaml</code></li>
</ul>
</li>
<li>X-Ray<ul>
<li>Download YAML：<code>curl -o collector-config-xray.yaml https://raw.githubusercontent.com/aws-observability/aws-otel-community/master/sample-configs/operator/collector-config-xray.yaml</code></li>
<li>Replace values<ul>
<li>serviceAccount: Check this value should be the same as the previous name field <code>adot-collector</code></li>
<li>value: <code>&lt;YOUR_EKS_CLUSTER_NAME&gt;</code></li>
<li>region: <code>&lt;YOUR_AWS_REGION&gt;</code></li>
</ul>
</li>
<li>Apply YAML：<code>kubectl apply -f collector-config-xray.yaml</code></li>
</ul>
</li>
<li>Prometheus on Daemonset<ul>
<li>Download YAML：<code>curl -o collector-config-advanced.yaml https://raw.githubusercontent.com/aws-observability/aws-otel-community/master/sample-configs/operator/collector-config-advanced.yaml</code></li>
<li>Replace values<ul>
<li>serviceAccount: Check this value should be the same as the previous name field <code>adot-collector</code></li>
<li>value: <code>&lt;YOUR_EKS_CLUSTER_NAME&gt;</code></li>
<li>region: <code>&lt;YOUR_AWS_REGION&gt;</code></li>
<li>name: Check this value should be the same as the previous name field <code>adot-collector</code></li>
</ul>
</li>
<li>Apply YAML：<code>kubectl apply -f collector-config-advanced.yaml</code></li>
</ul>
</li>
</ul>
</li>
</ol>
<h4 id="heading-reference">Reference</h4>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/eks/latest/userguide/opentelemetry.html">Amazon EKS add-on support for ADOT Operator</a></li>
<li><a target="_blank" href="https://aws-otel.github.io/">AWS Distro for OpenTelemetry</a></li>
</ul>
<h3 id="heading-vertical-pod-autoscaler">Vertical Pod Autoscaler</h3>
<h4 id="heading-requirements">Requirements</h4>
<ul>
<li>Install metrics server</li>
<li><code>kubectl</code> could communicate with your Amazon EKS cluster.</li>
<li>OpenSSL <code>1.1.1</code> or later installed on your device which is support <code>-addext</code> option.</li>
</ul>
<h4 id="heading-installation">Installation</h4>
<ol>
<li>Download repository：<code>git clone https://github.com/kubernetes/autoscaler.git</code></li>
<li>Go inside：<code>cd autoscaler/vertical-pod-autoscaler/</code></li>
<li>Deploy VPA：<code>./hack/vpa-up.sh</code>：If your OpenSSL is not supported <code>-addext</code> option, you will fail at this step.</li>
</ol>
<blockquote>
<p>If you install another OpenSSL version with another naming. You could change the OpenSSL command naming at <code>autoscaler/vertical-pod-autoscaler/pkg/admission-controller/gencerts.sh</code>. For example, I install <code>openssl11</code> on Amazon Linux. Then I change the <code>openssl</code> to <code>openssl11</code> at <code>gencerts.sh</code>.</p>
</blockquote>
<p>If you have already deployed another version of the Vertical Pod Autoscaler, remove it with the following command.</p>
<pre><code class="lang-shell">./hack/vpa-down.sh
</code></pre>
<h4 id="heading-reference">Reference</h4>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/eks/latest/userguide/vertical-pod-autoscaler.html">Vertical Pod Autoscaler</a></li>
</ul>
<h3 id="heading-application-load-balancer">Application Load Balancer</h3>
<p>Before we install the ALB controller, we need to install External-DNS first. External-DNS could help us update the Route53 record while we could ingress with ALB. But if your ALB is not planning to open to the internet, you could skip this step.</p>
<p>This ALB required OIDC.</p>
<h4 id="heading-install-external-dns">Install external-dns</h4>
<ol>
<li><p>Create IAM Policy</p>
<pre><code class="lang-json"> {
     <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
     <span class="hljs-attr">"Statement"</span>: [
         {
             <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
             <span class="hljs-attr">"Action"</span>: [<span class="hljs-string">"route53:ChangeResourceRecordSets"</span>],
             <span class="hljs-attr">"Resource"</span>: [<span class="hljs-string">"arn:aws:route53:::hostedzone/*"</span>]
         },
         {
             <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
             <span class="hljs-attr">"Action"</span>: [<span class="hljs-string">"route53:ListHostedZones"</span>, <span class="hljs-string">"route53:ListResourceRecordSets"</span>],
             <span class="hljs-attr">"Resource"</span>: [<span class="hljs-string">"*"</span>]
         }
     ]
 }
</code></pre>
</li>
<li><p>Create IRSA. Replace <code>$POLICY_ARN</code> value with IAM policy's arn at step 1.</p>
<pre><code class="lang-shell"> eksctl create iamserviceaccount \
     --cluster $EKS_CLUSTER_NAME \
     --name "external-dns" \
     --namespace ${EXTERNALDNS_NS:-"default"} \
     --attach-policy-arn $POLICY_ARN \
     --approve
</code></pre>
</li>
<li><p>Save external-dns YAML file.</p>
<p> Save to YAML</p>
<pre><code class="lang-yaml"> <span class="hljs-comment"># comment out sa if it was previously created</span>
 <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">ServiceAccount</span>
 <span class="hljs-attr">metadata:</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">external-dns</span>
     <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app.kubernetes.io/name:</span> <span class="hljs-string">external-dns</span>
 <span class="hljs-string">---</span>
 <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">rbac.authorization.k8s.io/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">ClusterRole</span>
 <span class="hljs-attr">metadata:</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">external-dns</span>
     <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app.kubernetes.io/name:</span> <span class="hljs-string">external-dns</span>
 <span class="hljs-attr">rules:</span>
     <span class="hljs-bullet">-</span> <span class="hljs-attr">apiGroups:</span> [<span class="hljs-string">''</span>]
       <span class="hljs-attr">resources:</span> [<span class="hljs-string">'services'</span>, <span class="hljs-string">'endpoints'</span>, <span class="hljs-string">'pods'</span>, <span class="hljs-string">'nodes'</span>]
       <span class="hljs-attr">verbs:</span> [<span class="hljs-string">'get'</span>, <span class="hljs-string">'watch'</span>, <span class="hljs-string">'list'</span>]
     <span class="hljs-bullet">-</span> <span class="hljs-attr">apiGroups:</span> [<span class="hljs-string">'extensions'</span>, <span class="hljs-string">'networking.k8s.io'</span>]
       <span class="hljs-attr">resources:</span> [<span class="hljs-string">'ingresses'</span>]
       <span class="hljs-attr">verbs:</span> [<span class="hljs-string">'get'</span>, <span class="hljs-string">'watch'</span>, <span class="hljs-string">'list'</span>]
 <span class="hljs-string">---</span>
 <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">rbac.authorization.k8s.io/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">ClusterRoleBinding</span>
 <span class="hljs-attr">metadata:</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">external-dns-viewer</span>
     <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app.kubernetes.io/name:</span> <span class="hljs-string">external-dns</span>
 <span class="hljs-attr">roleRef:</span>
     <span class="hljs-attr">apiGroup:</span> <span class="hljs-string">rbac.authorization.k8s.io</span>
     <span class="hljs-attr">kind:</span> <span class="hljs-string">ClusterRole</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">external-dns</span>
 <span class="hljs-attr">subjects:</span>
     <span class="hljs-bullet">-</span> <span class="hljs-attr">kind:</span> <span class="hljs-string">ServiceAccount</span>
       <span class="hljs-attr">name:</span> <span class="hljs-string">external-dns</span>
       <span class="hljs-attr">namespace:</span> <span class="hljs-string">default</span> <span class="hljs-comment"># change to desired namespace: externaldns, kube-addons</span>
 <span class="hljs-string">---</span>
 <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">external-dns</span>
     <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app.kubernetes.io/name:</span> <span class="hljs-string">external-dns</span>
 <span class="hljs-attr">spec:</span>
     <span class="hljs-attr">strategy:</span>
         <span class="hljs-attr">type:</span> <span class="hljs-string">Recreate</span>
     <span class="hljs-attr">selector:</span>
         <span class="hljs-attr">matchLabels:</span>
             <span class="hljs-attr">app.kubernetes.io/name:</span> <span class="hljs-string">external-dns</span>
     <span class="hljs-attr">template:</span>
         <span class="hljs-attr">metadata:</span>
             <span class="hljs-attr">labels:</span>
                 <span class="hljs-attr">app.kubernetes.io/name:</span> <span class="hljs-string">external-dns</span>
         <span class="hljs-attr">spec:</span>
             <span class="hljs-attr">serviceAccountName:</span> <span class="hljs-string">external-dns</span>
             <span class="hljs-attr">containers:</span>
                 <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">external-dns</span>
                   <span class="hljs-attr">image:</span> <span class="hljs-string">k8s.gcr.io/external-dns/external-dns:v0.11.0</span>
                   <span class="hljs-attr">args:</span>
                       <span class="hljs-bullet">-</span> <span class="hljs-string">--source=service</span>
                       <span class="hljs-bullet">-</span> <span class="hljs-string">--source=ingress</span>
                       <span class="hljs-bullet">-</span> <span class="hljs-string">--domain-filter=example.com</span> <span class="hljs-comment"># will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones</span>
                       <span class="hljs-bullet">-</span> <span class="hljs-string">--provider=aws</span>
                       <span class="hljs-bullet">-</span> <span class="hljs-string">--policy=upsert-only</span> <span class="hljs-comment"># would prevent ExternalDNS from deleting any records, omit to enable full synchronization</span>
                       <span class="hljs-bullet">-</span> <span class="hljs-string">--aws-zone-type=public</span> <span class="hljs-comment"># only look at public hosted zones (valid values are public, private or no value for both)</span>
                       <span class="hljs-bullet">-</span> <span class="hljs-string">--registry=txt</span>
                       <span class="hljs-bullet">-</span> <span class="hljs-string">--txt-owner-id=external-dns</span>
                   <span class="hljs-attr">env:</span>
                       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">AWS_DEFAULT_REGION</span>
                         <span class="hljs-attr">value:</span> <span class="hljs-string">us-east-1</span> <span class="hljs-comment"># change to region where EKS is installed</span>
             <span class="hljs-comment"># # Uncommend below if using static credentials</span>
             <span class="hljs-comment">#        - name: AWS_SHARED_CREDENTIALS_FILE</span>
             <span class="hljs-comment">#          value: /.aws/credentials</span>
             <span class="hljs-comment">#      volumeMounts:</span>
             <span class="hljs-comment">#        - name: aws-credentials</span>
             <span class="hljs-comment">#          mountPath: /.aws</span>
             <span class="hljs-comment">#          readOnly: true</span>
             <span class="hljs-comment">#  volumes:</span>
             <span class="hljs-comment">#    - name: aws-credentials</span>
             <span class="hljs-comment">#      secret:</span>
             <span class="hljs-comment">#        secretName: external-dns</span>
</code></pre>
</li>
<li><p>Replace to values at step 3 YAML file.</p>
<ul>
<li>Comment Service account section. We have already created the service account in step 2.</li>
<li>Change the <code>--domain-filter</code> to your domain</li>
<li>Change env <code>AWS_DEFAULT_REGION</code> to your region.</li>
</ul>
</li>
<li><p>Deploy external-dns.</p>
<pre><code class="lang-shell"> kubectl create --filename externaldns-with-rbac.yaml --namespace ${EXTERNALDNS_NS:-"default"}
</code></pre>
</li>
</ol>
<h4 id="heading-install-aws-load-balancer-controller">Install AWS Load Balancer Controller</h4>
<h5 id="heading-requirements">Requirements</h5>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html">Create IAM OIDC for EKS</a></li>
<li>Install EKS Add-ons：VPC CNI, kube-proxy, and CoreDNS</li>
<li>Install Helm</li>
</ul>
<h5 id="heading-installation">Installation</h5>
<ol>
<li><p>Create IAM Policy <code>AWSLoadBalancerControllerIAMPolicy</code></p>
<pre><code class="lang-shell"> aws iam create-policy \
     --policy-name AWSLoadBalancerControllerIAMPolicy \
     --policy-document https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.3/docs/install/iam_policy.json
</code></pre>
</li>
<li><p>Create IRSA, and replace values.</p>
<ul>
<li><code>&lt;IAM_POLICY&gt;</code> with IAM policy arn at step 1</li>
<li><code>&lt;EKS_CLUSTER&gt;</code> EKS cluster name</li>
<li><p><code>&lt;ROLE_NAME&gt;</code> IAM role name</p>
<pre><code class="lang-shell">eksctl create iamserviceaccount \
  --cluster=&lt;EKS_CLUSTER&gt; \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --role-name &lt;ROLE_NAME&gt; \
  --attach-policy-arn=&lt;IAM_POLICY&gt; \
  --approve \
  --override-existing-serviceaccounts
</code></pre>
</li>
</ul>
</li>
<li><p>Install the AWS Load Balancer Controller using Helm V3</p>
<pre><code class="lang-shell"> helm repo add eks https://aws.github.io/eks-charts
 helm repo update
 helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
     -n kube-system \
     --set clusterName=&lt;EKS_CLUSTER&gt; \
     --set serviceAccount.create=false \
     --set serviceAccount.name=aws-load-balancer-controller
</code></pre>
</li>
</ol>
<h4 id="heading-reference">Reference</h4>
<ul>
<li><a target="_blank" href="https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/aws.md">Setting up ExternalDNS for Services on AWS</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html">Installing the AWS Load Balancer Controller add-on</a></li>
<li><a target="_blank" href="https://kubernetes-sigs.github.io/aws-load-balancer-controller">AWS Load Balancer Controller</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html">Application load balancing on Amazon EKS</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Aws 網路架構- 單一 Vpc]]></title><description><![CDATA[簡述
此篇將介紹單一 VPC 情況下，AWS 的解決方案有哪些，也提供了哪些服務和整個網路流量的流程。

從上圖可以先列出有的服務

VPC
Subnet
Network ACL
Security Group
Internet Gateway
Elastic IP
egress-only Internet Gateway 


NAT Gateway / NAT Instance

VPC
一個 VPC 是邏輯層上的網路隔離，可以想像其中有獨立的網域 IP 和網路環境。VPC 在一個 Regio...]]></description><link>https://blog.taiwolskit.com/aws-network-architecture-single-vpc</link><guid isPermaLink="true">https://blog.taiwolskit.com/aws-network-architecture-single-vpc</guid><category><![CDATA[AWS]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Tue, 16 Aug 2022 03:20:24 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-57ch6lw">簡述</h1>
<p>此篇將介紹單一 VPC 情況下，AWS 的解決方案有哪些，也提供了哪些服務和整個網路流量的流程。</p>
<p><img src="https://docs.aws.amazon.com/quickstart/latest/vpc/images/quickstart-vpc-design-fullscreen.png" alt="AWS Network Architecture" /></p>
<p>從上圖可以先列出有的服務</p>
<ul>
<li>VPC</li>
<li>Subnet</li>
<li>Network ACL</li>
<li>Security Group</li>
<li>Internet Gateway<ul>
<li>Elastic IP</li>
<li>egress-only Internet Gateway </li>
</ul>
</li>
<li>NAT Gateway / NAT Instance</li>
</ul>
<h2 id="heading-vpc">VPC</h2>
<p>一個 VPC 是邏輯層上的網路隔離，可以想像其中有獨立的網域 IP 和網路環境。VPC 在一個 Region，跨 AZ 的網路環境(無法 Cross Region)。一個 Region 中可以有多個 VPC。</p>
<p>在建立 VPC 的時候，需要指定 IPv4 的 CIDR 範圍(必須的)，此外也能設定 IPv6 的範圍。</p>
<ul>
<li>IPv4 (CIDR 接受 16 ~ 28)<ul>
<li>CIDR 手動設定</li>
<li>IPAM 管理</li>
</ul>
</li>
<li>IPv6<ul>
<li>IPAM 管理</li>
<li>Amazon 提供（固定長度為 <code>/56</code>）</li>
<li>自有的 IPv6 CIDR</li>
</ul>
</li>
</ul>
<p>需要注意建立時的 CIDR 範圍不能與現有的其他 VPC 重疊，可以參考<a target="_blank" href="https://docs.aws.amazon.com/zh_tw/vpc/latest/userguide/amazon-vpc-limits.html">限制</a>。預設 一個 Region 最多有 5 個 VPC，可以申請擴充最多到 100 個。</p>
<p>最後可以設定 <code>Tenancy</code>，這是表示說當選擇為 <code>Dedicated</code> 時，代表在這 VPC 中使用的 EC2 都會是 dedicated tenancy instances，不管其 tenancy 設定為何。</p>
<p>IPAM 是一個 IP 管理服務，後續會再詳細介紹。這邊先知道如果選擇由 IPAM 管理的話，則 VPC 的 CIDR 大小會由 IPAM 的規則來規範。</p>
<p>IPv6 如果選擇使用 Amazon 提供的話，會像 Amazon 的 IPv6 位址池申請，會固定其長度在 <code>/56</code>，無法做修改。</p>
<p>IPv4 最多可以跟 5 個 CIDR 範圍關聯也可以取消關聯，但是只能全部取消，不能選擇 CIDR 中的一部分取消。</p>
<p>如果要刪除 VPC 的話，需要先中止或刪除 VPC 內的 ENI。</p>
<p>DNS resolution 是由 Route53 resolver 處理，如果沒有開啟此設定就會需要自己建立 DNS Server。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660614824267/L58kVbWoc.png" alt="dns-res.png" /></p>
<p>DNS hostnames 則是每個有 Public IP 的 Instance 都會有一個對應的 Public hostname</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660614827618/Jv6dfr9rH.png" alt="dns-host.png" /></p>
<blockquote>
<p>如果 Route53 有設定 Private host zone 就必須開啟以上兩個 DNS 設定。</p>
</blockquote>
<h3 id="heading-vpc">預設 VPC</h3>
<p>一開始使用 VPC 時，AWS 會在每個 Region 建立預設的 VPC。預設會附帶以下服務。</p>
<ul>
<li><p>VPC</p>
<ul>
<li>預設 CIDR <code>172.31.0.0/16</code></li>
</ul>
</li>
<li><p>Public subnet</p>
<ul>
<li>預設每個 AZ 有 CIDR <code>/20</code> 長度</li>
</ul>
</li>
<li>Internet gateway</li>
<li>Network ACL</li>
<li>Route table：將 <code>0.0.0.0/0</code> 指向 Internet gateway</li>
<li>DNS options set</li>
</ul>
<p><img src="https://docs.aws.amazon.com/zh_tw/vpc/latest/userguide/images/default-vpc.png" alt="default VPC" /></p>
<h2 id="heading-subnet">Subnet</h2>
<p>VPC 下可以再區分不同的 Subnet，在實際場景上我們通常可能會區分三層式網路架構：Access layer、Application layer、Core layer。但是如果再簡化一點，我們可以就是分兩層：Public layer 和 Private layer。後續的服務也會先依照兩層的方式做說明。</p>
<p>在 VPC 有說到是單一 Region 的，Subnet 則是單一 AZ 的，而且 CIDR 的範圍是要在 VPC CIDR 的範圍內，所以在建立時需要指定 AZ 和 CIDR。根據 VPC 的設定 subnet 也可以決定是只要有 IPv4 還是 IPv6 還是兩者皆有。</p>
<blockquote>
<p>要注意 Amazon 會預留 5 個 IP 位置，無法使用每個 Subnet CIDR 中的前四個 IP 地址和最後一個 IP 地址，並且無法將這些 IP 地址指派給資源，如 EC2 執行個體。IPv4 和 IPv6 都會。</p>
</blockquote>
<p><img src="https://docs.aws.amazon.com/zh_tw/vpc/latest/userguide/images/subnet-diagram.png" alt="Subnet" /></p>
<p>而大多數的網路服務都會是依靠在 Subnet 之下，通常如果有連接 Internet gateway 的 subnet 為視為是 Public subnet，反之就是 Private subnet。Private subnet 無法連向外網也無法被外網連接，只能透過 Public subnet 做連線。</p>
<h2 id="heading-route-table">Route Table</h2>
<p>Route Table 包含一組規則(稱為 route)，用來決定 Subnet 或 Gateway 的網路流量被導向到哪裡。每個 VPC 中會有一個預設的 Main route table 會控制所有並未與任何其他 Route Table 建立關聯之 Subnet 的流量。Route Table 一但跟 Subnet 做關聯就無法被刪除。實作上建議保留預設 Route Table，建立其他 Route Table 做規則上的疊加。Route Table 跟 Subnet 之間的關係是多對一，一個  Subnet 只能關聯一個 Route Table，但一個 Route Table 可以給多個 Subnet 使用。</p>
<p>預設下 VPC 中 Subnet 之間的流量會依靠 Local route 達到互通，而 Local route 是預設且無法修改的，只要是沒有跟其他 Route Table 做關聯的流量就會自動被其管理。IPv4 和 IPv6 的 route 是需要分別設定的。當不同的 Subnet 之間要溝通的時候，實際上會先透過 local route 做中繼站。</p>
<p><img src="https://docs.aws.amazon.com/zh_tw/vpc/latest/userguide/images/case-3_updated.png" alt="Route talbe" /></p>
<ul>
<li>Destination：您希望 IP 地址範圍（目標 CIDR）的流量要被導向</li>
<li>Target：流量要被導向的目標</li>
</ul>
<h3 id="heading-gateway-route-table">Gateway Route Table</h3>
<p>如果 Route Table 有關聯到 Internet Gateway 或是 Virtual Private Gateway 的話，可以被稱為 Gateway Route Table，用來控制進入到 VPC 的流量。</p>
<p>其他再額外延伸的還有跟 Transit Gateways 關聯的 Transit gateway route table 和跟 AWS Outposts 關聯的 Local gateway route table。</p>
<h2 id="heading-network-acl">Network ACL</h2>
<p>Network ACL 可以看作是 Subnet 層級的防火牆服務，用來允許或拒絕 Subnet inbound 和 outbound 的流量。系統一樣會有預設的 Network ACL，設定為允許所有流量流進和流出其相關聯的 subnet。</p>
<p>Network ACL 跟 Subnet 的關聯跟 Route Table 一樣，多對一的關係。沒有關聯的就會使用預設的 Network ACL。</p>
<p>Network ACL 是屬於 Stateless 服務，所以 inbound 和 outbound 要分別設定，可以看作是處理黑名單的管理，Rule 值越小權限越高，相同值時則以 <code>DENY</code> 為優先。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660617313784/s-9L3Vxff.png" alt="Network ACL" /></p>
<p>要注意規則上的設定，不然可能會造成一些 AWS 服務不能正常運作。例如可能把 ELB status check 不能正常運作。</p>
<h2 id="heading-security-group">Security Group</h2>
<p>Instance 層級的防火牆設定，屬於 stateful 服務因為其狀態會保存，當 Inbound 中允許的規則會自動開放對應的 outbound。即使移除 allow outbound traffic 的規則依舊還是可以連通。是唯一可以用來管控 Subnet 之間的流量方式。只能設定 allow rules，管控白名單，所以跟 Network ACL 不同沒有 Deny。其底層是使用了 Elastic Network Interface 類似虛擬網卡的方式做處理。預設阻擋所有 inbound，但允許所有 outbound。要注意 Name 在 VPC 中要是唯一的。</p>
<hr />
<p>前面的服務都在介紹的是流量在 VPC 內的控制，接下來的部分則是往外連線出去的服務</p>
<p><img src="https://docs.aws.amazon.com/zh_tw/vpc/latest/userguide/images/connectivity-overview.png" alt="Connectivity overview" /></p>
<h2 id="heading-internet-gateway">Internet gateway</h2>
<p>Internet Gateway 是一個水平擴展具有備援且高可用的 VPC 元件，可以讓 Subnet 中的服務連線到外部網路，或是讓外部網路做連線，也因此跟 Internet Gateway 做關聯的 Subnet 會被稱作 Public Subnet。主要的兩個功能：可以在 VPC Route Table 中作為外網流量的目標，以及針對已獲 Public IPv4 Instance 執行 NAT。</p>
<h3 id="heading-elastic-ip">Elastic IP</h3>
<p>如果要對外存取的話，該 Instance 需要具有 Public IP 或是有跟 Elastic IP 做關聯。而 Elastic IP 是一個靜態的 Public IP，可以跟任意的 Instance 或 Network Interface 做關聯。有點像是你就固定好一個 IP 位址，然後可以決定要指派到哪個 Instances。不管換到哪個 Instance，其對外的 IP 都是固定的。</p>
<h3 id="heading-egress-only-internet-gateway">Egress-only Internet Gateway</h3>
<p>算是一個分支的服務，主要是提供 Private Subnet 中 IPv6 對外網存取的管道(但不包含讓外網存取)。IPv4 的話則是會使用 NAT。</p>
<h2 id="heading-nat-gateway-nat-instance">NAT gateway / NAT instance</h2>
<p>如果今天在 Private Subnet 中的服務需要存取外網或是其他 VPC 的服務，就需要使用 NAT。可以選擇使用 AWS 管理的 NAT Gateway 或是在 EC2 上建立自己的 NAT instance。</p>
<h3 id="heading-nat-gateway">NAT Gateway</h3>
<ul>
<li>是獨立 AZ 的，可以多個 AZ 共用一個，或是每個 AZ 有各自的 NAT Gateway</li>
<li>支援以下通訊協定：TCP、UDP 和 ICMP</li>
<li>支援 5 Gbps 的頻寬，並可自動擴展至 100 Gbps。</li>
<li>每秒可以處理 100 萬個封包，並自動擴展至每秒 1000 萬個封包。若超過會丟棄封包</li>
<li>可支援最多 55,000 個連至每個唯一目標的同時連線</li>
</ul>
<h3 id="heading-nat-device">NAT Device</h3>
<p>需要建立自己的 NAT AMI，因為 AWS 自 2020/12/31 已正式停止支援，會建議直接使用 NAT Gateway 更快。需要建立在 Public Subnet 中，需要關閉 <code>Source &amp; Destination Check</code>，才能 Proxy 其他 Instance 的封包，需要額外設定 Security Group，Private Subnet 也需要設定 Route 導向 NAT Instance。其乘載量取決於 Instance 的規格，還需要另外自我處理 HA 的問題。</p>
<h2 id="heading-reference">Reference</h2>
<p>-<a target="_blank" href="https://docs.aws.amazon.com/zh_tw/quickstart/latest/vpc/overview.html">使用 Amazon VPC 建置模組化且可擴展的虛擬網路架構</a></p>
<ul>
<li><a target="_blank" href="https://aws.amazon.com/tw/vpc/">邏輯隔離的 Virtual Private Cloud</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/zh_tw/vpc/latest/userguide/what-is-amazon-vpc.html">「什麼是 Amazon VPC？」</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/zh_tw/vpc/latest/userguide/VPC_Scenario1.html">具有單一公有子網路的 VPC</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[LeetCode Solution, Easy, 746. Min Cost Climbing Stairs]]></title><description><![CDATA[746. Min Cost Climbing Stairs
題目敘述
You are given an integer array cost where cost[i] is the cost of ith step on a staircase. Once you pay the cost, you can either climb one or two steps.
You can either start from the step with index 0, or the step wi...]]></description><link>https://blog.taiwolskit.com/leetcode-solution-easy-746-min-cost-climbing-stairs</link><guid isPermaLink="true">https://blog.taiwolskit.com/leetcode-solution-easy-746-min-cost-climbing-stairs</guid><category><![CDATA[learn coding]]></category><category><![CDATA[leetcode]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[learning]]></category><category><![CDATA[Dynamic Programming]]></category><dc:creator><![CDATA[攻城獅]]></dc:creator><pubDate>Mon, 15 Aug 2022 12:23:43 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-746-min-cost-climbing-stairshttpsleetcodecomproblemsmin-cost-climbing-stairs"><a target="_blank" href="https://leetcode.com/problems/min-cost-climbing-stairs/">746. Min Cost Climbing Stairs</a></h1>
<h2 id="heading-6agm55uu5pwy6lw">題目敘述</h2>
<p>You are given an integer array <code>cost</code> where <code>cost[i]</code> is the cost of <code>ith</code> step on a staircase. Once you pay the cost, you can either climb one or two steps.</p>
<p>You can either start from the step with index <code>0</code>, or the step with index <code>1</code>.</p>
<p>Return <em>the minimum cost to reach the top of the floor</em>.</p>
<p><strong>Example 1:</strong></p>
<pre><code><span class="hljs-attr">Input:</span> <span class="hljs-string">cost</span> <span class="hljs-string">=</span> [<span class="hljs-number">10</span>,<span class="hljs-number">15</span>,<span class="hljs-number">20</span>]
<span class="hljs-attr">Output:</span> <span class="hljs-number">15</span>
<span class="hljs-attr">Explanation:</span> <span class="hljs-string">You</span> <span class="hljs-string">will</span> <span class="hljs-string">start</span> <span class="hljs-string">at</span> <span class="hljs-string">index</span> <span class="hljs-number">1</span><span class="hljs-string">.</span>

<span class="hljs-bullet">-</span> <span class="hljs-string">Pay</span> <span class="hljs-number">15</span> <span class="hljs-string">and</span> <span class="hljs-string">climb</span> <span class="hljs-string">two</span> <span class="hljs-string">steps</span> <span class="hljs-string">to</span> <span class="hljs-string">reach</span> <span class="hljs-string">the</span> <span class="hljs-string">top.</span>
<span class="hljs-string">The</span> <span class="hljs-string">total</span> <span class="hljs-string">cost</span> <span class="hljs-string">is</span> <span class="hljs-number">15</span><span class="hljs-string">.</span>
</code></pre><p><strong>Example 2:</strong></p>
<pre><code><span class="hljs-attr">Input:</span> <span class="hljs-string">cost</span> <span class="hljs-string">=</span> [<span class="hljs-number">1</span>,<span class="hljs-number">100</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">100</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">100</span>,<span class="hljs-number">1</span>]
<span class="hljs-attr">Output:</span> <span class="hljs-number">6</span>
<span class="hljs-attr">Explanation:</span> <span class="hljs-string">You</span> <span class="hljs-string">will</span> <span class="hljs-string">start</span> <span class="hljs-string">at</span> <span class="hljs-string">index</span> <span class="hljs-number">0</span><span class="hljs-string">.</span>

<span class="hljs-bullet">-</span> <span class="hljs-string">Pay</span> <span class="hljs-number">1</span> <span class="hljs-string">and</span> <span class="hljs-string">climb</span> <span class="hljs-string">two</span> <span class="hljs-string">steps</span> <span class="hljs-string">to</span> <span class="hljs-string">reach</span> <span class="hljs-string">index</span> <span class="hljs-number">2</span><span class="hljs-string">.</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">Pay</span> <span class="hljs-number">1</span> <span class="hljs-string">and</span> <span class="hljs-string">climb</span> <span class="hljs-string">two</span> <span class="hljs-string">steps</span> <span class="hljs-string">to</span> <span class="hljs-string">reach</span> <span class="hljs-string">index</span> <span class="hljs-number">4</span><span class="hljs-string">.</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">Pay</span> <span class="hljs-number">1</span> <span class="hljs-string">and</span> <span class="hljs-string">climb</span> <span class="hljs-string">two</span> <span class="hljs-string">steps</span> <span class="hljs-string">to</span> <span class="hljs-string">reach</span> <span class="hljs-string">index</span> <span class="hljs-number">6</span><span class="hljs-string">.</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">Pay</span> <span class="hljs-number">1</span> <span class="hljs-string">and</span> <span class="hljs-string">climb</span> <span class="hljs-string">one</span> <span class="hljs-string">step</span> <span class="hljs-string">to</span> <span class="hljs-string">reach</span> <span class="hljs-string">index</span> <span class="hljs-number">7</span><span class="hljs-string">.</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">Pay</span> <span class="hljs-number">1</span> <span class="hljs-string">and</span> <span class="hljs-string">climb</span> <span class="hljs-string">two</span> <span class="hljs-string">steps</span> <span class="hljs-string">to</span> <span class="hljs-string">reach</span> <span class="hljs-string">index</span> <span class="hljs-number">9</span><span class="hljs-string">.</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">Pay</span> <span class="hljs-number">1</span> <span class="hljs-string">and</span> <span class="hljs-string">climb</span> <span class="hljs-string">one</span> <span class="hljs-string">step</span> <span class="hljs-string">to</span> <span class="hljs-string">reach</span> <span class="hljs-string">the</span> <span class="hljs-string">top.</span>
<span class="hljs-string">The</span> <span class="hljs-string">total</span> <span class="hljs-string">cost</span> <span class="hljs-string">is</span> <span class="hljs-number">6</span><span class="hljs-string">.</span>
</code></pre><p><strong>Constraints:</strong></p>
<ul>
<li><code>2 &lt;= cost.length &lt;= 1000</code></li>
<li><code>0 &lt;= cost[i] &lt;= 999</code></li>
</ul>
<p><strong>Hint 1:</strong></p>
<p>Build an array <code>dp</code> where <code>dp[i]</code> is the minimum cost to climb to the top starting from the ith staircase.</p>
<p><strong>Hint 2:</strong></p>
<p>Assuming we have <code>n</code> staircase labeled from <code>0</code> to <code>n - 1</code> and assuming the top is <code>n</code>, then <code>dp[n] = 0</code>, marking that if you are at the top, the cost is <code>0</code>.</p>
<p><strong>Hint 3:</strong></p>
<p>Now, looping from <code>n - 1</code> to <code>0</code>, the <code>dp[i] = cost[i] + min(dp[i + 1], dp[i + 2])</code>. The answer will be the minimum of <code>dp[0]</code> and <code>dp[1]</code></p>
<h3 id="heading-6agm55uu5776k2v">題目翻譯</h3>
<p>會有一個整數陣列 <code>cost</code> 每個位置代表了爬到這一階樓梯要花費的費用，每次移動可以選擇要一階還是兩階。要找出到達最高層時，所需最少的的成本是多少。</p>
<h2 id="heading-6kej5rov6kej5p6q">解法解析</h2>
<p>因為每一次操作的花費成本都是基於之前的操作結果為基礎來計算的，所以是一個典型的 Dynamic programming 的題目。所以當然的就基本上可以有種解法：Tabulation 和 Memoization。</p>
<p>Dynamic Programming 最主要的解法就是找出<strong>小問題</strong>，因為最後的答案都是基於前面的答案為基礎累積的，所以其實就是每次解出<strong>小問題</strong>的答案。所以回到最原本的問題，當然就是你要踏出一階還是兩階哪個成本最低。成為函示就是：</p>
<p><code>minimumCost[i] = min(minimumCost[i - 1] + cost[i - 1], minimumCost[i - 2] + cost[i - 2])</code></p>
<p>而以下的解法差別就只是在於怎麼處理每次的小問題，依照 Dynamic programming 的解法，基本上就是分為 Tabulation 和 Memoization 兩種方式。</p>
<p><strong>Bottom-Up Dynamic Programming (Tabulation)</strong></p>
<p>這個解法主要就是使用了遍歷的方式來處理</p>
<p><strong>Top-Down Dynamic Programming (Recursion + Memoization)</strong></p>
<p>這一種解決小問題的解法就是遞迴了</p>
<p><strong>Bottom-Up, Constant Space</strong></p>
<p>這個方式跟第一種解法類似，只是不再使用陣列儲存之前處理的結果，而是直接用一個變數紀錄最新的結果。</p>
<h3 id="heading-6kej5rov56e5l6l">解法範例</h3>
<h4 id="heading-go">Go</h4>
<h5 id="heading-bottom-up-dynamic-programming-tabulation">Bottom-Up Dynamic Programming (Tabulation)</h5>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">minCostClimbingStairs</span><span class="hljs-params">(cost []<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">var</span> minimumCost []<span class="hljs-keyword">int</span> = <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">int</span>, <span class="hljs-built_in">len</span>(cost)+<span class="hljs-number">1</span>)
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-built_in">len</span>(cost); i++ {
        minimumCost[i] = <span class="hljs-number">0</span>
    }
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">2</span>; i &lt;= <span class="hljs-built_in">len</span>(cost); i++ {
        <span class="hljs-keyword">var</span> takeOneStep <span class="hljs-keyword">int</span> = minimumCost[i<span class="hljs-number">-1</span>] + cost[i<span class="hljs-number">-1</span>]
        <span class="hljs-keyword">var</span> takeTwoStep <span class="hljs-keyword">int</span> = minimumCost[i<span class="hljs-number">-2</span>] + cost[i<span class="hljs-number">-2</span>]
        <span class="hljs-keyword">if</span> takeOneStep &lt; takeTwoStep {
            minimumCost[i] = takeOneStep
        } <span class="hljs-keyword">else</span> {
            minimumCost[i] = takeTwoStep
        }
    }
    <span class="hljs-keyword">return</span> minimumCost[<span class="hljs-built_in">len</span>(cost)]
}
</code></pre>
<h5 id="heading-top-down-dynamic-programming-recursion-memoization">Top-Down Dynamic Programming (Recursion + Memoization)</h5>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">minCostClimbingStairs</span><span class="hljs-params">(cost []<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">var</span> memo <span class="hljs-keyword">map</span>[<span class="hljs-keyword">int</span>]<span class="hljs-keyword">int</span> = <span class="hljs-built_in">make</span>(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">int</span>]<span class="hljs-keyword">int</span>)
    <span class="hljs-keyword">return</span> minimumCost(cost, memo, <span class="hljs-built_in">len</span>(cost))
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">minimumCost</span><span class="hljs-params">(cost []<span class="hljs-keyword">int</span>, memo <span class="hljs-keyword">map</span>[<span class="hljs-keyword">int</span>]<span class="hljs-keyword">int</span>, i <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">if</span> i &lt;= <span class="hljs-number">1</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
    }

    <span class="hljs-keyword">if</span> val, ok := memo[i]; ok {
        <span class="hljs-keyword">return</span> val
    }

    <span class="hljs-keyword">var</span> downOne <span class="hljs-keyword">int</span> = minimumCost(cost, memo, i<span class="hljs-number">-1</span>) + cost[i<span class="hljs-number">-1</span>]
    <span class="hljs-keyword">var</span> downTwo <span class="hljs-keyword">int</span> = minimumCost(cost, memo, i<span class="hljs-number">-2</span>) + cost[i<span class="hljs-number">-2</span>]
    <span class="hljs-keyword">if</span> downOne &gt; downTwo {
        memo[i] = downTwo
    } <span class="hljs-keyword">else</span> {
        memo[i] = downOne
    }
    <span class="hljs-keyword">return</span> memo[i]
}
</code></pre>
<h5 id="heading-bottom-up-constant-space">Bottom-Up, Constant Space</h5>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">minCostClimbingStairs</span><span class="hljs-params">(cost []<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">var</span> downOne <span class="hljs-keyword">int</span> = <span class="hljs-number">0</span>
    <span class="hljs-keyword">var</span> downTwo <span class="hljs-keyword">int</span> = <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">2</span>; i &lt;= <span class="hljs-built_in">len</span>(cost); i++ {
        <span class="hljs-keyword">var</span> temp <span class="hljs-keyword">int</span> = downOne
        <span class="hljs-keyword">if</span> downOne+cost[i<span class="hljs-number">-1</span>] &lt; downTwo+cost[i<span class="hljs-number">-2</span>] {
            downOne += cost[i<span class="hljs-number">-1</span>]
        } <span class="hljs-keyword">else</span> {
            downOne = downTwo + cost[i<span class="hljs-number">-2</span>]
        }
        downTwo = temp
    }
    <span class="hljs-keyword">return</span> downOne
}
</code></pre>
<h4 id="heading-javascript">JavaScript</h4>
<h5 id="heading-bottom-up-dynamic-programming-tabulation">Bottom-Up Dynamic Programming (Tabulation)</h5>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">cost</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number}</span></span>
 */</span>
<span class="hljs-keyword">var</span> minCostClimbingStairs = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">cost</span>) </span>{
    <span class="hljs-keyword">const</span> minimumCost = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(cost.length + <span class="hljs-number">1</span>).fill(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">2</span>; i &lt;= cost.length; i++) {
        minimumCost[i] = <span class="hljs-built_in">Math</span>.min(minimumCost[i - <span class="hljs-number">1</span>] + cost[i - <span class="hljs-number">1</span>], minimumCost[i - <span class="hljs-number">2</span>] + cost[i - <span class="hljs-number">2</span>]);
    }
    <span class="hljs-keyword">return</span> minimumCost[cost.length];
};
</code></pre>
<h5 id="heading-top-down-dynamic-programming-recursion-memoization">Top-Down Dynamic Programming (Recursion + Memoization)</h5>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">cost</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number}</span></span>
 */</span>
<span class="hljs-keyword">var</span> minCostClimbingStairs = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">cost</span>) </span>{
    <span class="hljs-keyword">const</span> memo = {};

    <span class="hljs-keyword">const</span> minimumCost = <span class="hljs-function">(<span class="hljs-params">i</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (i &lt;= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">if</span> (i <span class="hljs-keyword">in</span> memo) <span class="hljs-keyword">return</span> memo[i];
        <span class="hljs-keyword">return</span> (memo[i] = <span class="hljs-built_in">Math</span>.min(minimumCost(i - <span class="hljs-number">1</span>) + cost[i - <span class="hljs-number">1</span>], minimumCost(i - <span class="hljs-number">2</span>) + cost[i - <span class="hljs-number">2</span>]));
    };
    <span class="hljs-keyword">return</span> minimumCost(cost.length);
};
</code></pre>
<h5 id="heading-bottom-up-constant-space">Bottom-Up, Constant Space</h5>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">cost</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number}</span></span>
 */</span>
<span class="hljs-keyword">var</span> minCostClimbingStairs = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">cost</span>) </span>{
    <span class="hljs-keyword">let</span> downOne = <span class="hljs-number">0</span>,
        downTwo = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">2</span>; i &lt;= cost.length; i++) {
        <span class="hljs-keyword">const</span> down = <span class="hljs-built_in">Math</span>.min(downOne + cost[i - <span class="hljs-number">1</span>], downTwo + cost[i - <span class="hljs-number">2</span>]);
        downTwo = downOne;
        downOne = down;
    }
    <span class="hljs-keyword">return</span> downOne;
};
</code></pre>
<h4 id="heading-kotlin">Kotlin</h4>
<h5 id="heading-bottom-up-dynamic-programming-tabulation">Bottom-Up Dynamic Programming (Tabulation)</h5>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">minCostClimbingStairs</span><span class="hljs-params">(cost: <span class="hljs-type">IntArray</span>)</span></span>: <span class="hljs-built_in">Int</span> {
        <span class="hljs-keyword">var</span> minimumCost: IntArray = IntArray(cost.size + <span class="hljs-number">1</span>, { <span class="hljs-number">0</span> })

        <span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> <span class="hljs-number">2</span>..cost.size) {
            minimumCost[i] =
                    Math.min(minimumCost[i - <span class="hljs-number">1</span>] + cost[i - <span class="hljs-number">1</span>], minimumCost[i - <span class="hljs-number">2</span>] + cost[i - <span class="hljs-number">2</span>])
        }
        <span class="hljs-keyword">return</span> minimumCost[cost.size]
    }
}
</code></pre>
<h5 id="heading-top-down-dynamic-programming-recursion-memoization">Top-Down Dynamic Programming (Recursion + Memoization)</h5>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">minCostClimbingStairs</span><span class="hljs-params">(cost: <span class="hljs-type">IntArray</span>)</span></span>: <span class="hljs-built_in">Int</span> {
        <span class="hljs-keyword">val</span> memo = mutableMapOf&lt;<span class="hljs-built_in">Int</span>, <span class="hljs-built_in">Int</span>&gt;()

        <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">minimumCost</span><span class="hljs-params">(i: <span class="hljs-type">Int</span>)</span></span>: <span class="hljs-built_in">Int</span> {
            <span class="hljs-keyword">if</span> (i &lt;= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
            <span class="hljs-keyword">if</span> (i <span class="hljs-keyword">in</span> memo) <span class="hljs-keyword">return</span> memo[i]!!
            memo[i] = Math.min(minimumCost(i - <span class="hljs-number">1</span>) + cost[i - <span class="hljs-number">1</span>], minimumCost(i - <span class="hljs-number">2</span>) + cost[i - <span class="hljs-number">2</span>])
            <span class="hljs-keyword">return</span> memo[i]!!
        }

        <span class="hljs-keyword">return</span> minimumCost(i = cost.size)
    }
}
</code></pre>
<h5 id="heading-bottom-up-constant-space">Bottom-Up, Constant Space</h5>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">minCostClimbingStairs</span><span class="hljs-params">(cost: <span class="hljs-type">IntArray</span>)</span></span>: <span class="hljs-built_in">Int</span> {
        <span class="hljs-keyword">var</span> downOne: <span class="hljs-built_in">Int</span> = <span class="hljs-number">0</span>
        <span class="hljs-keyword">var</span> downTwo: <span class="hljs-built_in">Int</span> = <span class="hljs-number">0</span>
        <span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> <span class="hljs-number">2</span>..cost.size) {
            <span class="hljs-keyword">val</span> temp: <span class="hljs-built_in">Int</span> = downOne
            downOne = Math.min(downOne + cost[i - <span class="hljs-number">1</span>], downTwo + cost[i - <span class="hljs-number">2</span>])
            downTwo = temp
        }
        <span class="hljs-keyword">return</span> downOne
    }
}
</code></pre>
<h4 id="heading-php">PHP</h4>
<h5 id="heading-bottom-up-dynamic-programming-tabulation">Bottom-Up Dynamic Programming (Tabulation)</h5>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>
</span>{

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> Integer[] $cost
     * <span class="hljs-doctag">@return</span> Integer
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">minCostClimbingStairs</span>(<span class="hljs-params">$cost</span>)
    </span>{
        $minimumCost = array_fill(<span class="hljs-number">0</span>, count($cost) + <span class="hljs-number">1</span>, <span class="hljs-number">0</span>);
        <span class="hljs-keyword">for</span> ($i = <span class="hljs-number">2</span>; $i &lt;= count($cost); $i++) {
            $minimumCost[$i] = min($minimumCost[$i - <span class="hljs-number">1</span>] + $cost[$i - <span class="hljs-number">1</span>], $minimumCost[$i - <span class="hljs-number">2</span>] + $cost[$i - <span class="hljs-number">2</span>]);
        }
        <span class="hljs-keyword">return</span> $minimumCost[count($cost)];
    }
}
</code></pre>
<h5 id="heading-top-down-dynamic-programming-recursion-memoization">Top-Down Dynamic Programming (Recursion + Memoization)</h5>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>
</span>{

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> Integer[] $cost
     * <span class="hljs-doctag">@return</span> Integer
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">minCostClimbingStairs</span>(<span class="hljs-params">$cost</span>)
    </span>{
        $memo = [];
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;minimumCost($cost, count($cost), $memo);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">minimumCost</span>(<span class="hljs-params">$cost, $i, $memo</span>)
    </span>{
        <span class="hljs-keyword">if</span> ($i &lt;= <span class="hljs-number">1</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        }
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>($memo[$i])) {
            <span class="hljs-keyword">return</span> $memo[$i];
        }
        $memo[$i] = min(<span class="hljs-keyword">$this</span>-&gt;minimumCost($cost, $i - <span class="hljs-number">1</span>, $memo) + $cost[$i - <span class="hljs-number">1</span>], <span class="hljs-keyword">$this</span>-&gt;minimumCost($cost, $i - <span class="hljs-number">2</span>, $memo) + $cost[$i - <span class="hljs-number">2</span>]);
        <span class="hljs-keyword">return</span> $memo[$i];
    }
}
</code></pre>
<h5 id="heading-bottom-up-constant-space">Bottom-Up, Constant Space</h5>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>
</span>{

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> Integer[] $cost
     * <span class="hljs-doctag">@return</span> Integer
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">minCostClimbingStairs</span>(<span class="hljs-params">$cost</span>)
    </span>{
        $downOne = <span class="hljs-number">0</span>;
        $downTwo = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> ($i = <span class="hljs-number">2</span>; $i &lt;= count($cost); $i++) {
            $temp = $downOne;
            $downOne = min($downOne + $cost[$i - <span class="hljs-number">1</span>], $downTwo + $cost[$i - <span class="hljs-number">2</span>]);
            $downTwo = $temp;
        }
        <span class="hljs-keyword">return</span> $downOne;
    }
}
</code></pre>
<h4 id="heading-python">Python</h4>
<h5 id="heading-bottom-up-dynamic-programming-tabulation">Bottom-Up Dynamic Programming (Tabulation)</h5>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">minCostClimbingStairs</span>(<span class="hljs-params">self, cost: list[int]</span>) -&gt; int:</span>
        <span class="hljs-comment"># The array's length should be 1 longer than the length of cost</span>
        <span class="hljs-comment"># This is because we can treat the "top floor" as a step to reach</span>
        minimum_cost: list[int] = [<span class="hljs-number">0</span>] * (len(cost) + <span class="hljs-number">1</span>)

        <span class="hljs-comment"># Start iteration from step 2, since the minimum cost of reaching</span>
        <span class="hljs-comment"># step 0 and step 1 is 0</span>
        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>, len(cost) + <span class="hljs-number">1</span>):
            take_one_step: int = minimum_cost[i - <span class="hljs-number">1</span>] + cost[i - <span class="hljs-number">1</span>]
            take_two_steps: int = minimum_cost[i - <span class="hljs-number">2</span>] + cost[i - <span class="hljs-number">2</span>]
            minimum_cost[i] = min(take_one_step, take_two_steps)

        <span class="hljs-comment"># The final element in minimum_cost refers to the top floor</span>
        <span class="hljs-keyword">return</span> minimum_cost[<span class="hljs-number">-1</span>]
</code></pre>
<h5 id="heading-top-down-dynamic-programming-recursion-memoization">Top-Down Dynamic Programming (Recursion + Memoization)</h5>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">minCostClimbingStairs</span>(<span class="hljs-params">self, cost: list[int]</span>) -&gt; int:</span>
        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">minimum_cost</span>(<span class="hljs-params">i: int</span>):</span>
            <span class="hljs-comment"># Base case, we are allowed to start at either step 0 or step 1</span>
            <span class="hljs-keyword">if</span> i &lt;= <span class="hljs-number">1</span>:
                <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>

            <span class="hljs-comment"># Check if we have already calculated minimum_cost(i)</span>
            <span class="hljs-keyword">if</span> i <span class="hljs-keyword">in</span> memo:
                <span class="hljs-keyword">return</span> memo[i]

            <span class="hljs-comment"># If not, cache the result in our hash map and return it</span>
            down_one: int = cost[i - <span class="hljs-number">1</span>] + minimum_cost(i - <span class="hljs-number">1</span>)
            down_two: int = cost[i - <span class="hljs-number">2</span>] + minimum_cost(i - <span class="hljs-number">2</span>)
            memo[i] = min(down_one, down_two)
            <span class="hljs-keyword">return</span> memo[i]

        memo: dict[int, int] = {}
        <span class="hljs-keyword">return</span> minimum_cost(len(cost))
</code></pre>
<h5 id="heading-bottom-up-constant-space">Bottom-Up, Constant Space</h5>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">minCostClimbingStairs</span>(<span class="hljs-params">self, cost: list[int]</span>) -&gt; int:</span>
        down_one = down_two = <span class="hljs-number">0</span>
        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>, len(cost) + <span class="hljs-number">1</span>):
            temp: int = down_one
            down_one = min(down_one + cost[i - <span class="hljs-number">1</span>], down_two + cost[i - <span class="hljs-number">2</span>])
            down_two = temp

        <span class="hljs-keyword">return</span> down_one
</code></pre>
<h4 id="heading-rust">Rust</h4>
<pre><code class="lang-rust">
</code></pre>
<h4 id="heading-swift">Swift</h4>
<h5 id="heading-bottom-up-dynamic-programming-tabulation">Bottom-Up Dynamic Programming (Tabulation)</h5>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">minCostClimbingStairs</span><span class="hljs-params">(<span class="hljs-number">_</span> cost: [Int])</span></span> -&gt; <span class="hljs-type">Int</span> {
        <span class="hljs-keyword">var</span> minimumCost: [<span class="hljs-type">Int</span>] = <span class="hljs-type">Array</span>(repeating: <span class="hljs-number">0</span>, <span class="hljs-built_in">count</span>: cost.<span class="hljs-built_in">count</span> + <span class="hljs-number">1</span>)
        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">2</span>...cost.<span class="hljs-built_in">count</span> {
            <span class="hljs-keyword">let</span> takeOneStep: <span class="hljs-type">Int</span> = minimumCost[i - <span class="hljs-number">1</span>] + cost[i - <span class="hljs-number">1</span>]
            <span class="hljs-keyword">let</span> takeTwoSteps: <span class="hljs-type">Int</span> = minimumCost[i - <span class="hljs-number">2</span>] + cost[i - <span class="hljs-number">2</span>]
            minimumCost[i] = <span class="hljs-built_in">min</span>(takeOneStep, takeTwoSteps)
        }

        <span class="hljs-keyword">return</span> minimumCost[cost.<span class="hljs-built_in">count</span>]
    }
}
</code></pre>
<h5 id="heading-top-down-dynamic-programming-recursion-memoization">Top-Down Dynamic Programming (Recursion + Memoization)</h5>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">minCostClimbingStairs</span><span class="hljs-params">(<span class="hljs-number">_</span> cost: [Int])</span></span> -&gt; <span class="hljs-type">Int</span> {
        <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">minimumCost</span><span class="hljs-params">(<span class="hljs-number">_</span> i: Int)</span></span> -&gt; <span class="hljs-type">Int</span> {
            <span class="hljs-keyword">guard</span> i &gt; <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
            }

            <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> val = memo[i] {
                <span class="hljs-keyword">return</span> val
            }

            <span class="hljs-keyword">let</span> downOne: <span class="hljs-type">Int</span> = minimumCost(i - <span class="hljs-number">1</span>) + cost[i - <span class="hljs-number">1</span>]
            <span class="hljs-keyword">let</span> downTwo: <span class="hljs-type">Int</span> = minimumCost(i - <span class="hljs-number">2</span>) + cost[i - <span class="hljs-number">2</span>]
            memo[i] = <span class="hljs-built_in">min</span>(downOne, downTwo)
            <span class="hljs-keyword">return</span> memo[i]!
        }

        <span class="hljs-keyword">var</span> memo = [<span class="hljs-type">Int</span>: <span class="hljs-type">Int</span>]()
        <span class="hljs-keyword">return</span> minimumCost(cost.<span class="hljs-built_in">count</span>)
    }
}
</code></pre>
<h5 id="heading-bottom-up-constant-space">Bottom-Up, Constant Space</h5>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">minCostClimbingStairs</span><span class="hljs-params">(<span class="hljs-number">_</span> cost: [Int])</span></span> -&gt; <span class="hljs-type">Int</span> {
        <span class="hljs-keyword">var</span> downOne: <span class="hljs-type">Int</span> = <span class="hljs-number">0</span>
        <span class="hljs-keyword">var</span> downTwo: <span class="hljs-type">Int</span> = <span class="hljs-number">0</span>
        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">2</span>...cost.<span class="hljs-built_in">count</span> {
            <span class="hljs-keyword">let</span> temp: <span class="hljs-type">Int</span> = downOne
            downOne = <span class="hljs-built_in">min</span>(downOne + cost[i - <span class="hljs-number">1</span>], downTwo + cost[i - <span class="hljs-number">2</span>])
            downTwo = temp
        }
        <span class="hljs-keyword">return</span> downOne
    }
}
</code></pre>
]]></content:encoded></item></channel></rss>