置頂

我的 VPython 教學文件 (HackMD 版本)

VPython 教學文件目錄 安裝及測試 基本語法 等速度直線運動 自由落下 終端速度 水平抛射 使用For迴圈計算水平抛射資料 斜向抛射 圓周運動 簡諧運動 單擺 木塊彈簧系統分離 重力及簡諧 行星運動 相疊木塊 雙重簡諧運動 一維彈性碰撞 ...

熱門文章

2023年8月6日 星期日

C++ 陣列 array 及 STL vector

作者:王一哲
日期:2023年8月6日



傳統的陣列 array


C++ 傳統的陣列 array,可以用來儲存多筆相同格式的資料,儲存這些資料的記憶體位址是連續的,所以讀取資料時,是依據陣列開頭的記憶體位址再加上索引值,索引值由 0 開始。以下是關於 array 的基礎知識。


産生 array


可以使用所有內建的資料格式,例如 int、float、char、string,也可以使用自訂的資料格式,但是一個 array 當中所有的資料只能是同一種格式。語法通常有以下3種
資料格式 名稱[長度];
資料格式 名稱[長度] = {資料1, 資料2, 資料3, ...};
資料格式 名稱[長度] = {0};
  1. 第一種:産生 array 時沒有指定資料內容,切記在讀取 array 前一定要填入資料,否則無法預測會讀到什麼數值。
  2. 第二種:可以省略長度,編譯器會自動根據資料內容決定 array 的長度。
  3. 第三種:産生指定長度、所有資料皆為 0 的 array。
int a[5];           // 長度為 5 的整數 array,沒有指定資料內容
int b[] = {0, 1, 2, 3, 4};  // 長度為 5 的整數 array,內容為 {0, 1, 2, 3, 4}
int c[5] = {0};     // 長度為 5 的整數 array,內容為 {0, 0, 0, 0, 0}
int d[5] = {1};     // 不好的寫法,長度為 5 的整數 array,內容為 {1, 0, 0, 0, 0}
int e[5] = {-1};    // 不好的寫法,長度為 5 的整數 array,內容為 {-1, 0, 0, 0, 0}
bool f[5] = {true}; // 不好的寫法,長度為 5 的整數 array,內容為 {1, 0, 0, 0, 0}
bool g[5] = {false};// 長度為 5 的整數 array,內容為 {0, 0, 0, 0, 0}
char alphabet[] = {'A', 'B', 'C', 'D', 'E'};// 長度為 5 的字元 array
string names[] = {"Albert", "Bob", "Conan", "David", "Ethan"};// 長度為 5 的字串 array


搭配 memset 設定 array 內容


如果想要使用 memset,需要先引入函式庫 cstring,語法為
memset(名稱, 0, sizeof(名稱));  // 將指定名稱的 array 資料全部設定為 0
memset(名稱, -1, sizeof(名稱)); // 將指定名稱的 array 資料全部設定為 -1
例如以下的程式碼
int a[5];
memset(a, 0, sizeof(f));  // 長度為 5 的整數 array,內容為 {0, 0, 0, 0, 0}
int b[5];
memset(b, -1, sizeof(f)); // 長度為 5 的整數 array,內容為 {-1, -1, -1, -1, -1}


2023年8月5日 星期六

Python 及 C++ 雙向佇列 (deque)

作者:王一哲
日期:2023年8月5日



前言


雙向佇列 (double-ended queue, deque) 的性質與佇列很像,但是可以從最前面或最後面填入、取出資料,可以涵蓋 queue 及 stack 的功能。以下是在 Python 及 C++ 的實作方法。


Python 方法1:引入 collections 函式庫中的 deque


要先引入函式庫,函式庫的官方說明書在此 class collections.deque
from collections import deque


建立雙向佇列


語法為
雙向佇列名稱 = deque(資料, maxlen=長度)
如果不輸入資料,會先建立空的雙向佇列,之後再填入資料。maxlen 可以不加,預設值為 None,如果有設定 maxlen,當雙向佇列已滿且要從最後面填入新資料時,會將最前面的資料推出去;反之,當雙向佇列已滿且要從最前面填入新資料時,會將最後面的資料推出去。以下的程式碼會建立名稱為 q、資料為 [0, 1, 2]、maxlen 為3的雙向佇列。
q = deque([0, 1, 2], maxlen=3)
如果想要知道 q 的內容,只要用 print 就可以了
print(q)
輸出內容為
deque([0, 1, 2], maxlen=3)


從最前面填入資料


語法為
雙向佇列名稱.appendleft(資料)
當雙向佇列已滿且要從最前面填入新資料時,會將最後面的資料推出去,例如以下的程式碼
q = deque([0, 1, 2], maxlen=3)
q.appendleft(3)  # q 的內容變為 [3, 0, 1]
如果沒有限制雙向佇列最大長度,例如以下的程式碼
q = deque([0, 1, 2])
q.appendleft(3)  # q 的內容變為 [3, 0, 1, 2]


從最後面填入資料


語法為
雙向佇列名稱.append(資料)
當雙向佇列已滿且要從最後面填入新資料時,會將最前面的資料推出去,例如以下的程式碼
q = deque([0, 1, 2], maxlen=3)
q.append(3)  # q 的內容變為 [1, 2, 3]
如果沒有限制雙向佇列最大長度,例如以下的程式碼
q = deque([0, 1, 2])
q.append(3)  # q 的內容變為 [0, 1, 2, 3]


2023年8月4日 星期五

Python 及 C++ 堆疊 (stack)

作者:王一哲
日期:2023年8月4日



前言


堆疊 (stack) 是一種 後進先出 (the last in is the first out, LIFO) 的資料格式,只能從最後面(最上面)填入資料,從最後面(最上面)取出資料,無法從堆疊中間存取資料,以下是在 Python 及 C++ 的實作方法。


Python 方法1:引入 queue 函式庫中的 LifoQueue


要先引入函式庫,函式庫的官方說明書在此 queue — A synchronized queue class,操作方式與 queue 基本上相同,可以參考另一篇文章〈Python 及 C++ 佇列 (queue)〉。
from queue import LifoQueue


建立堆疊


語法為
堆疊名稱 = LifoQueue(maxsize=長度)
maxsize 可以不加,預設值為 0;如果有設定 maxsize,當堆疊已滿且要填入新資料時,會回傳錯誤訊息 Full。以下的程式碼會建立名稱為 mystack、maxsize 為3的堆疊。
mystack = LifoQueue(maxsize=3)


填入資料


語法為
堆疊名稱.put(資料, block=布林, timeout=秒數)
block 可以不加,預設值為 True。timeout 可以不加,預設值為 None。
  1. 如果 block=True,當堆疊已滿且要填入新資料時,會先等待一段時間,當堆疊有空間時再填入資料,或是到達 timeout 設定的秒數時回傳錯誤訊息 Full,但如果沒有設定 timeout,程式就會停在這一行,不會執行後面的程式碼。
  2. 如果 block=False,當堆疊已滿且要填入新資料時,立刻回傳錯誤訊息 Full
延續前面的程式碼,可以試試看第5、6行程式碼執行時的差異。
mystack = LifoQueue(maxsize=3)
mystack.put(0)  # mystack 的內容為 [0]
mystack.put(1)  # mystack 的內容為 [0, 1]
mystack.put(2)  # mystack 的內容為 [0, 1, 2] 且已填滿
mystack.put(3, block=True, timeout=1)  # 等待 1 秒後回傳錯誤訊息 Full
#mystack.put(3, block=False)  # 立刻回傳錯誤訊息 Full


2023年8月3日 星期四

Python 及 C++ 佇列 (queue)

作者:王一哲
日期:2023年8月3日



前言


佇列 (queue) 是一種 先進先出 (the first in is the first out, FIFO) 的資料格式,只能從最後面填入資料,從最前面取出資料,無法從佇列中間存取資料,以下是在 Python 及 C++ 的實作方法。


Python 方法1:引入 queue 函式庫中的 Queue


要先引入函式庫,函式庫的官方說明書在此 Python 3.11.4 queue — A synchronized queue class
from queue import Queue


建立佇列


語法為
佇列名稱 = Queue(maxsize=長度)
maxsize 可以不加,預設值為 0;如果有設定 maxsize,當佇列已滿且要填入新資料時,會回傳錯誤訊息 Full。以下的程式碼會建立名稱為 q、maxsize 為3的佇列。
q = Queue(maxsize=3)


填入資料


語法為
佇列名稱.put(資料, block=布林, timeout=秒數)
block 可以不加,預設值為 True。timeout 可以不加,預設值為 None。
  1. 如果 block=True,當佇列已滿且要填入新資料時,會先等待一段時間,當佇列有空間時再填入資料,或是到達 timeout 設定的秒數時回傳錯誤訊息 Full,但如果沒有設定 timeout,程式就會停在這一行,不會執行後面的程式碼。
  2. 如果 block=False,當佇列已滿且要填入新資料時,立刻回傳錯誤訊息 Full
延續前面的程式碼,可以試試看第5、6行程式碼執行時的差異。
q = Queue(maxsize=3)
q.put(0)  # q 的內容為 [0]
q.put(1)  # q 的內容為 [0, 1]
q.put(2)  # q 的內容為 [0, 1, 2] 且已填滿
q.put(3, block=True, timeout=1)  # 等待 1 秒後回傳錯誤訊息 Full
#q.put(3, block=False)  # 立刻回傳錯誤訊息 Full


2023年7月31日 星期一

Python 及 C++ 字串處理

作者:王一哲
日期:2023年7月31日



前言


以下的內容包含
  1. 取得字串長度
  2. 判斷字串是否為空字串
  3. 比較字串內容是否相等
  4. 複製字串
  5. 連接字串
  6. 改變字串內容



取得字串長度


Python 語法


語法為
len(字串名稱)
回傳值格式為 int,例如
s = "abcde"
print(len(s))
印出的值為5。

C++ 語法


需要先引入函式庫 string,取得字串長度的語法有兩種
字串名稱.size();
字串名稱.length();
回傳值格式為沒有正負號的整數 sizt_t,例如
#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "abcde";
    cout << s.size() << endl;
    cout << s.length() << endl;
    return 0;
}
兩種寫法印出的值都是5。接下來的文章中,C++ 的程式碼都會省略 int main() 以外的部分。


2023年7月29日 星期六

Python 及 C++ 遍歷字串

作者:王一哲
日期:2023年7月29日



前言


由於我大約一年前開始寫 APCS、ZeroJudge 的題目,最近又開始寫 LeetCode,我會先用比較熟悉的 Python 解題,確定程式碼的邏輯正確後,再用 C++ 重寫一遍。在重寫的過程中,因為我對於 C++ 的語法不太熟悉,經常需要上網找資料,沒想到現在 C++ 多了很多方便的工具,甚至有些寫法跟 Python 很像。

遍歷字串是指依序讀取字串中的字元並做一些處理,例如將每個字元依照 ASCII 編碼加1,再儲存到另一個字串中,以下是 Python 及 C++ 的寫法。

Python 語法



方法1:使用 for 迴圈及索引值



Python 中的字串類似由字元組成的陣列,索引值由 0 開始,可以用索引值取出字串中的內容。方法1是用 for 迴圈,將變數 i 的值依序由 0、1、2、... 代入,直到(字串長度 - 1)為止,再用 s[i] 就可以依序讀取字串中的字元。
s = "Hello World!"
s2 = ""

for i in range(len(s)):
    s2 += chr(ord(s[i])+1)
print(s2)


方法2:使用 for 迴圈並暫存字元



Python 的 for 迴圈有一種特別的用法,可以由 in 後方的物件依序取出元素,例如第3行,就是將字串 s 中的字元依序取出並暫存於變數 c,變數 c 在離開 for 迴圈時就會消失。
s = "Hello World!"
s2 = ""
for c in s:
    s2 += chr(ord(c)+1)
print(s2)


以上兩種寫法印出的字串 s2 內容皆為Ifmmp!Xpsme"


2023年5月11日 星期四

Matplotlib 繪圖技巧:加上資料標籤及改變字型

作者:王一哲
日期:2023年5月11日


加上資料標籤



在某些特殊的狀況下,會在數據點旁邊標示資料點的數值。下方程式碼第14 ~ 16行,依序讀取串列 x、y 的元素,組合成字串 txt,再用 annotate [1] 將 txt 標示在數據點的右側,下圖是採用預設字型的效果。
import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [3, 5, 7, 9, 11]

plt.figure(figsize=(8, 6), dpi=96)
plt.xlabel("x", fontsize=24)
plt.ylabel("y", fontsize=24)
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.grid(color="grey", linestyle="--", linewidth=1)
plt.plot(x, y, marker="o", markerfacecolor="blue", markersize=8, linestyle="")

for i in range(len(x)):
    txt = "(" + str(x[i]) + ", " + str(y[i]) + ")"
    plt.annotate(txt, (x[i]+0.1, y[i]-0.1), fontsize=18)

plt.show()

預設樣式


2023年5月6日 星期六

將 GlowScript 線上版 VPython 動畫發布到 Blogger

步驟



  1. 開啟要發布的 GlowScript 線上版動畫編輯視窗,也就是程式碼頁面,不是動畫頁面。
  2. 點選發布動畫的連結,英文是 Share or export this program。
  3. 複製下方格子中的 HTML 程式碼,進到 Blogger 編輯文章畫面,於 HTML 檢視 模式下貼上剛才複製的程式碼。
  4. 刪除第4行的程式碼就可以發布了。
<link type="text/css" href="https://www.glowscript.org/css/ide.css" rel="stylesheet" />


發布的動畫



以下的動畫是以 進階教材:按鈕 線上版為例。

2023年4月17日 星期一

無限多個電阻器連接的等效電阻

作者:王一哲
日期:2023/4/17


題目



下圖的每一個電阻器的電阻值皆為 $r$,若每3個電阻器為一組,不斷地向右連接了無窮多組的電阻器,則節點 a、b 之間的等效電阻量值為何?
等效電阻題目電路圖


理論解



由於題目的圖中有無窮多組電阻器,若在節點 a、b 的右側另取兩個節點 c、d,則 a、b 及 c、d 的等效電阻值應該會相等,也就是 $R = R_{ab} = R_{cd}$,可以將電路圖改為下圖。
等效電阻題目電路圖


由上圖可得 $$ R = (R /\mkern-5mu/ r) + 2r ~\Rightarrow~ R = \frac{Rr}{R+r} + 2r ~\Rightarrow~ R^2 + Rr = Rr + 2Rr + 2r^2 \\ \Rightarrow~ R^2 - 2Rr - 2r^2 = 0 ~\Rightarrow~ R = \frac{2r \pm \sqrt{4r^2 + 8r^2}}{2} = (1 \pm \sqrt 3)r $$ 由於電阻值不可能是負值,因此答案為 $(\sqrt 3 + 1)r$


2023年3月24日 星期五

電路模擬軟體 Circuit Simulator

作者:王一哲
日期:2023/3/24


前言



最近我正好教到高三選修物理第5冊第1章電流與電路,書上有一個求等效電阻的題目,由於圖中的電阻器不是單純的串聯或並聯,如果要計算節點a、b之間的等效電阻,我通常會在兩點之間接上一個理想電池,用克希荷夫定律計算通過每個電阻器的分支電流,再用電池電動勢及總電流計算等效電阻。但是這個題目的分支電流數字並不好看,假設理想電池的電動勢為 1 V,則通過 5 Ω 電阻器與 2 Ω 電阻器的的電流分別為 $$ I_1 = \frac{7}{40} = 0.175 ~\mathrm{A} ~~~~~ I_2 = \frac{13}{40} = 0.325 ~\mathrm{A} $$ 等效電阻 $$ R_{eq} = \frac{1}{I_1 + I_2} = \frac{1}{0.175 + 0.325} = 2 ~\Omega $$
於是我想要找幾個簡單的電路模擬軟體,理論上只要在軟體裡畫好電路圖,應該就可以得到各個分支電流。網路上免費的電路圖軟體還不少,但是其中好幾個是線上版軟體,無法離線使用,後來我找到了這個網站 https://www.falstad.com/circuit/
等效電阻題目電路圖


Circuit Simulator



連上 這個網頁之後,可以直接在網頁上使用軟體,也可以點擊網頁下方的 Standalone (offline) versions.連結,下載離線版本的軟體。
Circuit Simulator 網站首頁

Circuit Simulator 離線版下載頁面