跳到主要內容

發表文章

[C++] getline 空白的一行

 以下為一個簡單讀檔範例: #include<bits/stdc++.h> using namespace std; int main(int argc, char** argv) { ifstream inputFile("haha"); string line; while(getline(inputFile, line)) { int a = 0; stringstream tkn(line); tkn >> a; cout << " a = " << a << endl; } return 0; } 文字檔 haha 內容: 3 5 6 注意結尾有多一換行。 ----------------------------------------------------- 此情況下,程式執行結果: a = 3 a = 5 a = 6 a = 0 ----------------------------------------------------- getline 在讀檔最後一行,會讀到空的字串。造成多了一筆無效資料。 所以 stringstream 切 token 時,要特別小心,用 if(tkn >> a)  條件判斷 stringstream 是否 fail。
最近的文章

[Linux] sed replace with regex

以下有個例子,說明 sed 如何將檔案中: #include "../bbb/file.h" 這個字串中的 ../bbb 刪除,變成: #include "file.h" 指令如下: sed -i -r 's/(#include.*)\".*\/(.*\.h)\"/\1\"\2\"/g' ./file.cpp 其中 -i 代表作用在輸入檔案。 -r 代表要使用 regex。 如果要對某個資料夾內的所有檔案執行上述 sed 操作: find <folder_path> -type f -exec sed -i -r 's/(#include.*)\".*\/(.*\.h)\"/\1\"\2\"/g' {} \;

[Software] Bazel 於 Linux 安裝(Ubuntu)

 根據官方的作法,最快的方法如下: sudo apt-get install curl gnupg curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg sudo mv bazel.gpg /etc/apt/trusted.gpg.d/ echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list 然後: sudo apt-get update && sudo apt-get install bazel

[Training] GCJ 2021 Qualification Round - Reversort

 第一次參加 GCJ,之前一直沒時間完成這個夢想,這次勇敢踏出第一步。 Qualification Round 已經晉級,我檢討並總結自己的 Code,將比較好的寫法整理下來。 第一題 Reversort 很簡單,沒太大的問題。 題目要求實現 Reversort 演算法,Pseudo Code 已經給予,直接依照 Pseudo Code 刻程式碼即可: Reversort(L):   for i := 1 to length(L) - 1     j := position with the minimum value in L between i and length(L), inclusive     Reverse(L[i..j]) 這裡要注意,矩陣 reverse 有既有的函式可以用,以及 Case 輸出 index 是從 1 開始計,而非 0 開始起算。 以下是我總結較好的寫法: // by EdocZec on 2021/04/03 // Google Code Jam 2021-01 #include <bits/stdc++.h> using namespace std; template<typename T> ostream& operator<<(ostream&os, const vector<T>& v) { for(int i=0; i<v.size(); i++) os << v[i] << " "; return os; } int readi() { int i; cin >> i; return i; } int alg(vector<int>& a) { int score = 0; for(int i=0; i<(a.size()-1); i++) { int min_idx = i; for(int j=i+1; j<(a.size()); j++) { if(a[min_idx] > a[j]) m

[Vim] 我的 .vimrc

我用過的文字編輯器有 sublime text/atom/notepad++/gedit 等等。 後來我在 window 和 Linux 寫程式還是比較慣用 vim。 以下整理我常用的 .vimrc:  set nu "show line number. set rnu "related line number. nmap ; : "replace ';' with ':' in normal mode. set ai "auto indent set mouse=a "activate mouse set expandtab "replace tab with space. set tabstop=4 "replace tab with 4 spaces. set bg=dark "background set to dark. color desert "color scheme. syntax on "enable syntax highlight. " auto complete: inoremap ( ()<Esc>i inoremap ' ''<Esc>i inoremap " ""<Esc>i inoremap [ []<Esc>i inoremap { {}<Esc>i set cursorline " active cursorline 到此 vim 搭配 Ctrl + N 當自動補全,已經很好用了,之後有好用設定會再補上來。

[Tool] cmder + python + MinGW for windows

推薦適用於 windows 的好用 shell terminal 工具 cmder,它能提供類似 Linux 的終端機介面跟指令,且我覺得它比 Windows 10 內建的 Bash 終端好用。 cmder 下載網址: https://cmder.net/ cmder 不需要安裝,下載後直接執行主程式即可。 一般我都在 Linux 環境編程,但如果使用的電腦是 Windows 10,我會用 cmder 建立熟悉的 Linux 終端機環境。 以下提供我常用來編程的初始化設定。 cmder 按 Win+Alt+P,可以啟動設定介面,在這個介面內先設定 bash 預設的 Shell,否則啟動時可能會出現錯誤訊息,因為 cmder 預設 使用 PowerShell,但因簽證問題造成 Windows PowerShell 出現錯誤訊息。 在 Startup 選單: 在 General 選單: 接著微調一些設定: 字體調整到舒適的字型和大小。 可以開啟 Quake 模式。這個模式在程式競賽或是工作時很好用,可以透過 Ctrl+` 這個組合鍵將終端機顯示在最上方,或隱藏終端機成為背景模式。 這個組合鍵是可以修改的,在 Keys & Macro 選單: 下載 MinGW Installer,安裝 MinGW,然後在系統環境變數加入 MinGW 的 bin 資料夾位置。 http://mingw-w64.org/doku.php 安裝 vim,cmder 切換到家目錄 “~,可以在裡面設定 .vimrc 檔案,來調整 vim 設定。 安裝 python,一樣將 python bin 資料夾新增到環境變數。

[C++] 用 stringstream 分割同時包含 ASCII 和 Unicode 中文的字串

假設有一個檔案,內容包含中文,也包含 ASCII 字元(皆是可顯示字元)。 如果這個檔案格式為 UTF-8,則 ASCII 碼佔用 1 個 byte,中文字佔用 3 個 byte。且代表中文的這 3 個 byte,必定是負值。 (其他語言的文字,未必是用 3 byte 儲存,但繁體中文佔用了 3 byte,UTF-8 的特性就是 byte 數是變動的) 所以 stringstream 用 UTF-8 的 ASCII 的可顯示字元,來當作 delimiter分割字串,是很安全的,例如用 ASCII 的 "空白" 來將以下的檔案,每一行輸入都拆解成兩個獨立字串: apple 蘋果 橘子 哈哈 兔子 rabbit 可以這樣寫: ifstream inputFile(fileName.c_str());  string a, b, line; while(getline(inputFile, line)) {     stringstream tkn(line);     tkn >> a >> b;         cout << " [Debug] a == " << a << endl;     cout << " [Debug] b == " << b << endl; } inputFile.close(); 輸出會是: [Debug] a == apple [Debug] b == 蘋果 [Debug] a == 橘子 [Debug] b == 哈哈 [Debug] a == 兔子 [Debug] b == rabbit 一般我很少直接採用 Unicode 編碼來處理字串,較常採用 UTF-8 。因為 UTF-8 的前 128 個編碼,跟 ASCII 編碼是完全相同的,如此方便程式碼可以相容 ASCII 編碼,同時又可以處理寬字元。許多支持多國語言的程式,預設都用 UTF-8 就是這個緣故。 注意在 Window 系統記事本若將檔案存成 UTF-8 編碼,檔頭會多了 0xefbbbf 這 3 個 b

[Code Daily] 2020/06/18 單字記憶遊戲(一)

今天要開始實作一個小遊戲:單字記憶遊戲。 遊戲的規則,就是有許多蓋著的牌,每張牌有一個英文單字,或者某個英文單字的中文翻譯。 玩家僅能翻開牌觀看單字幾秒,牌會自動蓋上。必須將單字牌跟對應的翻譯牌在短時間內同時掀開,才能得到分數。 先從最簡單的功能開始實作:如何用滑鼠觸發事件,把牌掀開,並顯示單字。 程式語言採用 C++ 搭配 SDL2。 工作環境:elementary OS. 1.     首先我想要在某個位置 rendering true type font,這就需要安裝 SDL_ttf.h: sudo apt-get install libsdl2-ttf-dev g++ compile 時記得要 link: -lSDL2_ttf 2.      到 fontsquirrel 可以下載免費的 ttf 字型。我選擇的字型是 "Raleway"。 接下來分成三個步驟: initialized SDL_Renderer。 讀 Texture 圖檔,讀 ttf 檔案。把所有牌的可能圖案都先畫到一個 SDL_Texture 內。 滑鼠觸發事件處理。繪圖。 重點在第三個步驟 滑鼠觸發了某個按鈕,按鈕物件就會更新自己的狀態,例如將狀態更新為 Botton UP/Down,然後根據這個狀態值,去將 SDL_Texture 裁切出要顯示的部份,把切下來的部份 render 到一個 SDL_Renderer 物件上。 明天繼續完成細節的部份。

[C++] 計算程式執行時間:clock 和 time 函式

要計算一段程式碼執行時間,可以用 time 函式: 1 2 3 4 5 time_t start, end; start = time(NULL); // DO SOMETHING... end = time(NULL); cout << " [Msg] total time: " << difftime(end, start) << " sec" << endl; time 函式的精確度只到達秒,如果要精確到毫秒等級,要用 clock 函式: 1 2 3 4 5 6 clock_t start, end; start = clock(); // DO SOMETHING... end = clock(); cout << ( double )(finish - start) / CLOCKS_PER_SEC << endl;

[開箱] Filco Majestouch 2 忍者鍵盤第二代

最近買了一個新款的 Filco 忍者鍵盤第二代,NINJA Majestouch 2: 鍵盤對我來說蠻重要的,以前就很喜歡 Filco 品牌的鍵盤,我大學使用的第一支茶軸鍵盤就是 Filco 的牌子,現在已經充滿了灰塵,使用了至少已有 8 年了吧: 畢業後有買另一個 irock 鍵盤: 這禮拜拆開新鍵盤來看看: 內部包裝 內部包裝 採用按鍵的文字採用側印 鍵帽與拔鍵器 整體外觀 整體而言,美感簡約低調,按鍵的反饋力也很好,是一個適合寫程式的鍵盤。 相較於我的另一個也是德國櫻桃茶軸鍵盤 irock 品牌,我覺得 Filco 的按鍵回饋比較綿密,有漸層的回饋感,且按鍵聲音比較安靜。irock 則比較像機械打字的回饋感,敲字時也都蠻舒壓。

[心得] 復古、老派的程式設計之路

最近看到 John Carmack 2018 年的貼文中的幾段話: I’m not a Unix geek.  I get around ok, but I am most comfortable developing in Visual Studio on Windows.  I thought a week of full immersion work in the old school Unix style would be interesting, even if it meant working at a slower pace.  It was sort of an adventure in retro computing — this was fvwm and vi.  Not vim, actual BSD vi. In the end, I didn’t really explore the system all that much, with 95% of my time in just the basic vi / make / gdb operations.  I appreciated the good man pages, as I tried to do everything within the self contained system, without resorting to internet searches.  Seeing references to 30+ year old things like Tektronix terminals was amusing. In the spirit of my retro theme, I had printed out several of Yann LeCun’s old papers and was considering doing everything completely off line, as if I was actually in a mountain cabin somewhere, but I wound up watching a lot of the Stanford CS231N lectures on YouTube, and found them

[Concept] 二補數(2's Complement)除法跟模數的意義

計算機領域,負數常用二補數表示。 很多計算機書籍有介紹二補數,不再贅述。 這裡討論的是:把一個二補數,除以一個數 K,或對 K 取 Mod,得到的答案意義為何? 首先,二補數可視為 2^N ( 2 的 N 次方)減一純量,N 視為無窮大。 例如:-3 二補數表示法為:2^N - 3 二進位表示:(100000000...) - (11) 將 2^N 除以 K 取商,餘數丟棄,K 是 2 的冪次方(2, 4, 8, 16...),此商在數線上意義為何? 把 2^N 看成無窮多個班級所組成的人數,每班 K 人。由於 K 是 2 的冪次方,所以 2^N 人剛好能排滿 n 個班級, n 剛好也是 2 的冪次方 :  K  K  K  K   ...   K   K    做以下觀察: 任意正數 P ,(2^N - P) 是 -P 的二補數表示法。 (2^N - P) / K = n - Q = 2^某次方 - Q,是 Q 的二補數。 Q = ceiling(P/K),也就是假如 P/K = 3.45,那麼 Q 就是 3.45 進位 = 4。 所以 2^某次方 - Q 就是 - ceiling(P/K) 的二補數表示。 (2^N - P) % K,也就是取模數,為 K - (P%K) = 1。 結論: 二補數除以 K,K 為 2 的冪次方,商還是二補數。 二補數 Mod K,即取模數,K 為 2 的冪次方,得到的結果,是一個純量,這個純量不是二補數。 二補數除以 K,K 為 2 的冪次方,跟正數除以 K 的意義有一樣的地方,算出的商為一個編號,代表第幾個班級,班級的編號從 0 開始。 例如:P = 第 0, 1, 2, ... , K-1 個同學,被編在編號為 P/K = 0 的班級,P = 第 K+0, K+1, K+2, ... , 2K-1 被編在編號為 P/K = 1 的班級。 同理,P = -1, -2, -3, ... , -K 的同學,屬於編號為二補數 (-P)/K = -1 的班級,-K-1, -K-2, -K-3, ... , -2K 屬於在編號為 -2 的班級。 二補數 (-P) % K,跟正數 P % K 行為意義有一樣的地方。 假設 K = 8 ,即每 8 個人一班,每班學號從 0 開始到 7,假設 P 等於 15, P/K = 1,P % K = 1

[Git] Bitbucket 建立 Repository Using Git

以下介紹用 bitbucket 搭配 git 控管程式碼的快速上手。 首先在 bitbucket 建立新的 Repository。申請完畢後,假設 Repository 的名稱叫做 test,可以按 bitbucket 網頁上的 Clone 按鈕,會出現 git clone 指令,通常為: git clone https://<user_name>@bitbucket.org/<user_name>/test.git <user_name> 那裡寫的是你的 bitbucket 帳號名稱。 clone 完畢,本地端出現 test 資料夾。 將要新增的檔案,用以下指令 add 到 repo 內: git add <file_name> 然後 commit: git commit -m "這裡打註解" 最後 push 上 code,就會正式將本地端檔案上傳 bitbucket: git push origin master 大功告成!

[Python] 輸出二進位檔案

記錄一下 python 如何輸出成二進位檔案。 我輸出二進位檔案的方法,採用的是 bytearray 這個函式。 我會先把我要輸出的數字,以 byte 為單位,先放入一個 list 陣列,然後將 list 陣列用 bytearray 轉成 byte 格式,寫入檔案: #!/usr/bin/env python3 import struct def main (): outputFile = open( "tmp.bin" , "wb" ) byte_dat = [ 0xab , 0xcd , 0xef ] binary_pack = bytearray(byte_dat) outputFile.write(binary_pack) outputFile.close() if (__name__ == "__main__" ): main() 我們用 Linux 的 xxd 指令 一個一個 byte 看一下輸出的檔案長什麼樣子: 在終端機輸入: xxd -g1 -c1 ./tmp.bin 輸出結果: 00000000: ab  . 00000001: cd  . 00000002: ef  . 可知第一個 byte 是放在陣列 index 0 的位置,第二個 byte 是放在陣列 index 1 的位置,餘類推。

[Linux] 安裝 conda 並用 conda 安裝套件

本篇文章介紹 conda 在 Linux 安裝與基本使用方法。 conda 是一個套件包管理器,跟 apt-get 一樣。conda 的宗旨最初是為了管理複雜的 Python 語言包安裝,後來開始支援其它語言包的安裝(例如 R 語言)。 在 Linux 安裝 conda 指令無法採用 apt-get 指令,要安裝 conda 有兩種方式: 安裝 Anaconda。Anaconda 是一個 Python 的發行版,專門用於計算科學,內建很多的預設數據科學的軟體包,因此會安裝 Anaconda 會需要較大的硬碟空間,會安裝約 3 GB 大的檔案到電腦內。 安裝 Miniconda,是最小安裝版本的 Anaconda,內建 conda、Python 和一些基本套件和基本工具。我目前是安裝這個,因為我不想要安裝一些目前還用不到的語言包。 Minicoda 可以在 這個網站 下載。 我選擇 Python 2.7 的 Linux 64-bit 版本下載,安裝過程 不需要使用 sudo 權限 ,否則之後 conda 執行上會有權限問題,conda 在執行的時候是無法使用 sudo conda ... 來執行指令的。 安裝過程如下(作業系統為 Linux 發行版:Elementary OS): 執行 (不需要加 sudo)  bash ./Miniconda2-latest-Linux-x86_64.sh 會出現歡迎畫面: Welcome to Miniconda2 4.7.12 In order to continue the installation process, please review the license agreement. Please, press ENTER to continue >>> 按 Enter 後,閱讀完授權合約,輸入 yes 接受合約條款。 Do you accept the license terms? [yes|no] [no] >>> 預設安裝路徑是家目錄的 minicoda2,按下 Enter 可即刻安裝。 Miniconda2 will now be installed into this location

[C++] 電影駭客任務 Matrix 文字效果

1999 年上映的電影駭客任務(Matrix)於明年要推出第四集了。這部電影不論在哲學觀以及拍攝效果,在當年的影史上都是一個突破。 其中這部電影中最著名的電腦執行畫面深植在多少技術愛好者的心中: 本篇文章記錄我如何用 C++ 實作這種電影 matrix 文字下雨(raining)效果,這種文字效果有很多種作法,可以做得很精緻,我採取比較簡單的一種實現方法: 首先程式的邏輯從如何刷新 M x N 的文字 random 陣列開始。 假設有一個 M x N 的 random 文字陣列,我們可以從第 0 個 row 開始刷新每個字元。 假設現在正在處理第 0 個 row,我們走訪每個字元,然後隨機挑選某幾個文字更新,更新的方法有將當前字元用空白字元替換,或用任意非空白字元替換兩種情況。 當第 0 個 row 更新完之後,就刷新螢幕,然後繼續更新下一條 row,也就是更新第 1 個 row。 重點來了。 刷新螢幕的方法,順序為: 先清空螢幕 先顯示最新刷新的 row。 依序顯示之前刷新的 row。 原始碼如下: // C++ program for implementation of falling matrix effect #include<iostream> #include<string> #include<thread> #include<cstdlib> #include<ctime> #include<chrono> const int cols = 60 ; const int rows = 30 ; const int switch_num = 5 ; const int delay = 90 ; char screen[rows][cols]; using namespace std; int main ( int argc, char ** argv) { srand(time(NULL)); bool status[cols] = { 0 };

[C++] CMake 建置 C/C++ 程式

在編譯程式的時候,會設定一些組態(configuration,簡稱 config)。 這些組態包含我們的編譯過程需要用哪一種編譯器,哪一些函式庫,要編譯哪些檔案和編譯的指令等等。 以 Linux 環境而言(Windows 系統的操作也大同小異,原理都是一樣的),在編譯 C++ 專案時,上述這些組態可以寫在一個叫做 Makefile 的檔案裡。在 Makefile 檔案所在資料夾執行 make 指令,make 這隻程式,就會吃進 Makefile 並根據 Makefile 內的組態設定做出對應編譯的動作。 通常這個 Makefile 寫起來很繁瑣,因此才會有 cmake 這個工具的誕生。 CMake 是一個能自動幫我們產生 Makefile 的程式。 CMake 基本的觀念就是,我們只要指定好編譯器種類,以及我們要編譯的目錄、執行檔名稱等等設定,CMake 就會產生 Makefile。 CMake 基本使用方式,假如我們有個資料夾結構如下: . ├── build ├── CMakeLists.txt ├── lib ├── reference │   └── matrix_effect.cpp └── src └── meffect.cpp 這種資料夾結構是我習慣的 hierarchy。用這樣的資料夾做管理,專案比較不會凌亂。 src 資料夾裡面放 .cpp 程式碼。 lib 資料夾放程式碼用到的外部函式庫,即 include 的 header file。 而程式碼編譯成執行檔的動作,則在 build 資料夾內操作。 reference 資料夾內則放一些參考資料跟文件。 build 資料夾內有個 CMakeLists.txt,這個檔案就是 cmake 指令需要的檔案,以這個專案資料夾結構為例,CMakeLists.txt 內容可以這樣寫: cmake_minimum_required( VERSION 2.8.9 ) project( meffect ) include_directories( lib ) file( GLOB SOURCES "src/*.cpp" ) add_executable( meffect ${ SOURCES }) 然後在 build

[Linux] 用 dd 指令燒錄 usb 開機碟

環境:elementary os 目標:把預燒錄的 iso 檔案燒錄到 usb 隨身碟內,做成開機磁碟。 用 lsblk 指令看隨身碟掛載在哪個位置。(通常掛載在 /media/... 路徑內,或是用視窗的檔案瀏覽器觀看顯示的 usb 磁碟名稱,再看 /media/ 下哪一個磁碟名稱跟 usb 隨身碟同名) lsblk 顯示的畫面會類似: sdc          8:32   1   7.1G  0 disk └─sdc1   8:33   1   7.1G  0 part /media/<這裡會顯示 usb 路徑及名稱> 下指令卸載隨身碟: umount /media/<usb 路徑及名稱> 然後再次用 lsblk 檢查是否卸載成功。 用 sudo 權限下 dd 指令燒錄: sudo dd if=<path_of_iso_file>.iso of=/dev/sdc bs=1M bs=1M 意思是一次要寫入幾個 byte,官方說明寫著: bs=BYTE:  read and write up to BYTES bytes at a time (default: 512); overrides ibs and obs. 燒錄結束時,會顯示類似如下的 report: 輸入 1419+1 個紀錄 輸出 1419+1 個紀錄 1488797696 bytes (1.5 GB, 1.4 GiB) copied, 831.393 s, 1.8 MB/s

[Training] UVA 1595 Symmetry

本題為 Brute Force 可以迅速解題。 題目給予一些二維座標,求是否所有點左右對稱。 看似簡單,但需要注意以下幾點,不然很容易拖掉 Debug 時間。 1.   scanf 讀取輸入的時候,遇到自定義的 struct,不必遲疑,直接把 “&” 寫在前面:           scanf("%d %d", &a[i].x, &a[i].y); 2.   取 x 最大值和最小值,相加當作中點,不需要除以 2,避免出現浮點數問題。 3.   x_min 和 x_max 取完,要馬上回歸初始值。x_min 初始值要是很大的值,x_max 初始值是很小的值。 4.   要考慮座標有可能落在對稱線上,for 迴圈掃過所有點,某一點自己也可以跟自己取中點來做判斷。 完整程式碼: // This code is created by EdocZec on 2020/01/25 #include <bits/stdc++.h> #define _for(i,a,b) for(int i=(a); i<(b); ++i) // this has been verified and can work correctly. #define _dbg(arr,n) _for(i,0,n){cout << " [Debug] arr[" << i << "] = " << (arr)[i] << endl;} // this has been verified and can work correctly. using namespace std; struct point { int x; int y; }; point a[4000]; int main(int argc, char** argv) { int case_num; scanf("%d", &case_num); _for(i,0,case_num) { int num, x_mi

[Linux] Elementary OS 安裝

本篇記錄 Elementary OS 的安裝過程。 1.   先去網站上下載 Elementary OS 的映像檔: 網址: https://elementary.io/ 點選要捐贈給 Elementary OS 團隊的費用,也可以是 0 元。然後下載映像檔。 2.   接著開始燒錄 USB: 先準備一個 USB 隨身碟,然後將 Elementary OS 的映像檔燒錄到這個 USB 隨身碟內,製作成開機 USB 磁碟。 我使用 UNetbootin 來燒錄 USB,UNetbootin 下載網址: https://unetbootin.github.io/ 啟動 UNetbootin,選擇映像檔的選項,檔案的類別選擇 ISO,然後選擇 Elementary OS 映像檔路徑: 按下 [確定] 按鈕,開始燒錄: 燒錄完成畫面: 按下 [結束] 按鈕離開 UNetbootin,並退出隨身碟,完成 USB 開機磁碟的製作。 有時候,燒錄完成的 USB 會出現無法開機的情況,此時可嘗試用其它的燒錄軟體,例如 Etcher 或者 Rufus 。 3.   接著用剛燒錄完成的 USB 開機。首先在電腦開機時,按住 Delete 鍵進入 BIOS 設定畫面,將開機磁碟設定為 USB 開機。 4.   依造 官方的說明 安裝即可。在安裝之前,先把磁碟的資料備份,然後安裝 elementary os 時選擇格式化所有磁碟內的資料,就可以了。 安裝完的開機畫面:

[開箱] 寫 code 專用螢幕 Samsung UHD Monitor 32 吋

過年買了 Samsung UHD 32 吋寬螢幕,用來寫程式以及編輯影片,今天來開箱吧。 外箱設計的部分,簡約乾淨地把產品特色標註在包裝上。 內層有保麗龍保護防震。 面板邊框不會太寬整體看起來很和諧,質感不錯。 附贈的配件也很簡單,一條 HDMI 的線,電源供應器,支架和說明書。 將支架與螢幕組裝起來,不需要螺絲起子,用手就可以旋緊大板的螺絲。 接上電腦後,相較於往常許多的螢幕有許多按鍵,這個螢幕的按鈕設計十分簡約,只有一個按鈕,設置在螢幕背部。這讓我想到賈伯斯當 2007 年發表 iphone 第一代時說的話: “get rid of these buttons, buttons and controls can't change.” 設置完畢: 設定抗藍光(長期寫 code 容易盯著螢幕),跟調整亮度: 心得: 三星螢幕的品質一直都算蠻領先的。在 UI 以及外觀上,最近幾年都有往簡約的方向改良。我覺得不論設計什麼產品,簡約這個觀念,在使用者的印象跟舒適度上,是很加分,也很重要的一種風格。

[Training] GCJ 2015 Round 2 Kiddie Pool

Kiddie Pool 問題簡化如下: n 個水龍頭 1...n,每個水龍頭出水速度 Ri,各自水溫為 Ci 。今要混合成溫度 X 且體積 V 的水,求最小時間? 題目給的溫度公式,跟質心公式一樣。所以目標溫度 X,可以平移到數線 0 的位置。也就是每個水龍頭溫度都改為 X-Ci,目標改為配出溫度 0 度的水,方便計算。 考慮某個水龍頭開的時間最久,開啟時間為 t 秒,則得知其他的水龍頭最多也只能開啟 t 秒,不能再多。現在的目標為 t 需最小。 因此本題化簡為:假設最終答案就是 t 秒,每個水龍頭假設都先開啟 t 秒,各自裝入各自的水杯,然後計算有哪些水杯內的水是多餘的,需要倒掉。倒掉後的每杯水體積總和要逼近目標的體積 V,總和超過或小於 V,就要調整 t 的大小,直到體積總和等於 V 為止。 解上述第 3 點的問題,可以想像成有一蹺蹺板,上面放著 n 杯水。每杯水重量為 Ri × t。每杯水跟支點距離 abs(X-Ci)。為了維持平衡,必須將多餘的水從某幾杯中倒出,微調到蹺蹺板平衡時,所有水杯總重量總和需逼近 V。 利用貪婪演算法,從靠近支點處往遠離支點處走訪每個水杯,並累計力矩的值,左右兩邊一定會至少有一邊走訪到盡頭,此時若有一邊的力矩比較多,將力矩多的那邊當前走訪到的水杯,透過倒掉水的方式使左右平衡。 調整到支點左右力矩相等時,檢查水的體積總和是否符合要求,如果總體積太小,就拉高 t 值,否則降低 t 值。t 值的逼近,用 Binary Search 逼近法。 本題要十分注意的地方是 IMPOSSIBLE 的判斷。如果蹺蹺板支點沒有任何物品,且支點左邊全空或右邊全空,就是 IMPOSSIBLE 的情況。如果支點有物品,或者支點左右都有物品,此時 t 已經快要趨近極大,就代表 IMPOSSIBLE。 核心程式碼如下: 其中 left/right 代表支點左右的力矩,v_max 為當前 t 值下,力矩平衡的最大體積,center 是用來判斷支點有沒有物品。binary search 的 iteration 共 1000 次。 // binary search double low = 0, high = 1e20; for(int it = 0; it < 1000;

[有感而發] 硬體,軟體?

硬體跟軟體有什麼差別? 我的哲學是,設計軟體其實就是在控制硬體。但是設計硬體,是用更 hackable 的方法控制硬體。 我們下載的 APP,玩的遊戲,幾乎都是軟體程式,但我們常常忘記,我們操作軟體的同時,實際上是在控制硬體的訊號。以前大學時代,我遇到很多研究生想把硬體跟軟體硬生生分開,認為硬體跟軟體是兩個不同的研究領域,我認為這種觀念需要修正。 軟體的開發,只是把硬體的控制工作,建一套完整的 flow,包裝成程式語言,讓硬體開發,更容易掌握。 軟體開發最大的優點,就是開發的流程靈活,這種靈活性,造成許多人覺得軟體比硬體更生動有趣。現在程式語言很成熟,只要有個想法,可以輕鬆地用各種程式語言,在短時間內寫出程式。但我們常常忘記,程式語言的誕生,一開始也是從硬體的角度去設計編譯器,經過很多硬體工程師的努力,才讓程式語言普及,也大大降低寫程式的門檻,許多國家的小學,都已經有寫軟體的課程,即使不需要懂得太多的硬體知識,也能無腦地完成強大的程式,人人都可以是一名小駭客。 另一方面,從硬體的角度來開發,好處是開發出來的應用很省電,運算通常較有效率。 以晶片設計為例,晶片就是用奈米等級的電路,來實現某個想法跟功能。硬體的程式開發,需要考慮用到的資源。在寫硬體程式時,通常面對的都是線路層級,以及線路之間的邏輯接線,這造成設計硬體的過程,比軟體繁瑣,開發過程也比較耗時。 我認為做硬體需要一種態度,就是從「小事做起」。在硬體設計中是不可能體會到做大事的感覺。因為設計硬體,跟設計軟體的感覺不同。設計硬體很難在短時間內獲得成就感。在做硬體的時候,有時花了很深的功夫,搞了老半天,最終獲得的也只是把資料從一個記憶體搬到另一個記憶體而已。而設計軟體,卻能在短時間內,完成一個生動的遊戲。 但是,如果你想成為一名駭客,你必須學會硬體。 只會設計軟體,永遠只能在現有的硬體架構上,執行你的想法,而真正的創意,是軟體跟硬體都要互相溝通,靈活地運用硬體跟軟體的優勢,才能設計出高效能的技術。            by 最近有感而發的我。

[C++] g++ compile for Windows

How to compile executable binaries for Windows? First of all, install mingw-w64(for 64-bit Windows) sudo apt-get install mingw-w64 Then compile the source.cpp file, the command is: x86_64-w64-mingw32-g++ -static-libstdc++ -static-libgcc -static -o output.exe Source.cpp for 32-bit Windows, replace the "x86_64ㄦ-w64-mingw32-g++" with "i686-w64-mingw32-g++". The flag "-static-libstdc++" and "-static-libgcc" are for linking some standard library dependencies statically.

[SDL] First Program: Show Image

This is my first time using SDL. Install SDL2 for my Linux system: sudo apt-get install libsdl2-dev libsdl2-image-dev Now we can test our first SDL program. This program is pretty simple, I want to show an image as the background of a main window. In Linux system, #include <SDL2/SDL.h> as well as #include <SDL2/SDL_image.h> SDL_Init(SDL_INIT_VIDEO) should be called before initializing the main window. Using SDL_Surface for loading image, SDL_Renderer and SDL_Texture for rendering operation. Free memory. Code: #include <iostream> #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> using namespace std; const int SCREEN_WIDTH = 800; const int SCREEN_HEIGHT = 600; int main( int argc, char** argv) { if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {     cout << " [Error] SDL initialization fail: " << SDL_GetError() << endl;         exit(1); } SDL_Window* main_win = SDL_CreateWindow( "Practice_01",

[Python] Call by reference

Python 有 call by reference 嗎? 有的。在預設情況,傳入 mutable object 給一個函式,那個函式會將那個物件用傳參考的方式處理。 但是如果在函式內將物件的參考指向其他的地方,在這樣的情況下,不會改變傳入物件的內容的,因為 Reference Object 指向別的地方,並不會影響原本傳入物件指向的記憶體位置: 什麼是 mutable object? 在物件導向中,mutable object 就是指可變物件,在物件一生成時,物件內容還能改變。 Python 的 list 就是 mutable object,但 string 不是。 詳細的說明 參考這裡 。

[Python] 單引號,雙引號和三引號

在此解釋各種引號的意義。 雙引號跟單引號,在 Python 中的基本上沒差別,都可以代表字串: "This is a string" 'This is a string' 並且雙引號內可包含單引號,反之,如果用的是單引號,則單引號內可包含雙引號: "We call it 'Dog'...... " 'We call it "Dog"...... ' 三個雙引號,就可以直接輸入有換行的字串: """haha, this is a dog.""" 三個單引號要換行,就要輸入"\": '''haha, \ this is a dog.'''

[Python] dictionary 基本用法

Perl 有 hash,python 有 dictionary。 Dictionary 的用法,可以想成一個陣列裡面,每個元素裡面存的是一個 key 值,以及那個 key 值對應的 value。在 python terminal 可以測試以下程式,就可以了解 dictionary 使用方法: dict = {'name': 'Jack', 'gender': 'male'} print "name: ", dict['name'], " gender: ", dict['gender'] 執行結果: name:  Jack  gender:  male 判斷一個 value 是否存在: if 'Jack' in dict.values()   # exist -> return Ture 判斷一個 key 是否存在: if dict.has_key('name'):   # exist -> return True 初始化一個空的 dictionary: dict = {} 回傳某個特定的 value 的 key 值: 只能用 for 迴圈了... 如下: for key in dict:     if dict[key] == 'Jack':         print " I find: ", key 執行結果:  I find:  name 增加一個 item 在 dictionary 內: dict['new_key'] = 'item' 或者: dict.update({'new_key', 'item'})

[Vim] 自動備份,auto backup

在 vim 儲存某個檔案後,可以將更改前的檔案,備份成檔名結尾為波浪(即 “~” 符號,又稱為 tilde 符號)的備份檔。 要開啟這個功能,可在 .vimrc 內,輸入以下設定: "開啟自動備份設定: set backup  "設定備份資料夾: set backupdir=~/vimbackup/  "在備份檔名加上時間章戳: au BufWritePre * let &bex = '#' . strftime("%F.%H.%M")

[Concept] Edoc 的由來

"Edoc" 是我小時候研究學問時,創造的名詞。這個詞的意義,我將它定義為「懂得反向思考的學者」,或是「技術遊俠」。它的起源,是 "Code" 這個詞的反序,到後期,我將這個詞衍深為一種思考的態度。 這個名詞的精神,簡述如下: 尊敬知識 不論從事什麼職業,無論性別、年齡、貧富,皆需尊敬自己領域的知識,並有學習的熱誠。必須熟練自己領域的知識,發展方法,去解決任何問題。 重視實作 發明方法時,必須捲起袖子實作。在方法尚未實作出來時,一切推理皆需視為假說。 自學 自己具備收集資料、觀察現象以及主動學習的能力。不需要被動等待別人來教我們。 持續往前 遇到困境跟不完美,必須相信會有解決的方法。遇到困難無法解決,即使帶著挫折跟憂慮,也必須持續往前,做該做的事。 徽章 為自己設計一個簡單的 Logo 徽章,時刻提醒自己,自己是有價值的,不要辜負自己。 愛好自然 文明源自於良好的自然資源。新鮮的空氣,和乾淨的水源,都能讓思考清澈。 尊重想像力 異想天開的態度,應該被肯定。不論想法多麼不成熟,只要肯運用想像力,就有可能成功。 寫作 每天撰寫個人部落格,個人網站,或透過親筆寫作,累積自己的著作,分享成果。即使你或妳不識字,或沒有寫作的資源,也可以透過吟唱歌謠,編織藝術品,透過俯拾即是的一草一木,傳遞並記錄自己的想法。 每天都有成果 每天完成一件有價值的事,往目標邁進一點點,不可整天頹廢。不論你或妳完成的事情多麼微小,都需肯定自己。 充足睡眠 不熬夜是耕夢者基本的習慣,盡量維持充足睡眠。犧牲睡眠來工作,表面上贏在前面,但會輸在後面。 不怕承認錯誤 發現自己的錯誤,是一件可喜的事,不要害怕承認錯誤,不要怕接受不同的觀念。 不怕孤獨 不要害怕孤獨。不要害怕站在人群之外。不要害怕別人跟你或妳的興趣不同,要學習在孤獨中勤勉。而最終,只要肯往前,會找到很多一起努力的摯友。 聽電音 (what? 這個不一定要做到啦) 不論你或妳的年齡,學歷,職業,貧富,如果認同並實踐以上的理念,那麼你或妳,就是一名技術遊俠 (Edoc) 。