$4 blog
GNU/Linux, Debian/Ubuntu, Free Software/Open Source Software, and Programming.
2026年1月20日 星期二
修復 v4l2loopback 0.15.0 的 V4L2 緩衝區佇列問題
解析位元運算公式 n & ~(((n + 1) & ~n) >> 1)
2026年1月17日 星期六
在 Copilot CLI 使用 Spec Kit 流程圖
我把使用的大概細節跟過程記錄在 https://hackmd.io/@fourdollars/SpecKit 上面,用 feat: Add shared storage support for multi-unit Concourse CI deployments #5 這個 Pull Request 來練習完整走過整個流程,總共產生了 122 commits 跟 43 個檔案變更,過程有苦有樂也有辛酸,感覺在帶一個做事很快不會抱怨也很主動積極的新同事,但是就是要處處盯著他做事,幫他解決一些卡住的地方。
Concourse CI Machine Charm 是我正在開發的一個使用 Juju 快速架構管理維護 Concourse CI 服務的一套解決方案,已經可以從 edge channel 拿來使用了,不過還在開發中還有許多地方沒有完善,所以還沒有穩定釋出版本。
2026年1月6日 星期二
深入解析 grep 的「Broken pipe」錯誤:隨機出現的原因與優雅解法
2026年1月5日 星期一
自幹了一個 Agent Skills - Launchpad Skill
放在 https://github.com/fourdollars/lp-api/ 專案底下的 launchpad 目錄底下,當然就是用 lp-api 這個小工具來串接。
我自己有在 OpenCode, GitHub Copilot CLI, Gemini CLI 上面成功掛載起來使用。
基本上就是把 AI Agent 接上 Launchpad,用自然語言去叫 AI 做自己想要做的事情。
以下是幾張 OpenCode 上使用的示範。
有興趣的人可以去看看 Agent Skills 了解一下。
2025年11月28日 星期五
Kadane's algorithm
昨天練習的題目是 3381. Maximum Subarray Sum With Length Divisible by K,題目的最佳解是利用 Kadane's algorithm,我覺得比較容易理解的方式是先計算前面 k-1 個 kSum 之後,再往後面用 Kadane's algorithm 來解。
如果是寫 C++ 是這樣:
class Solution {
public:
long long maxSubarraySum(vector< int>& nums, int k) {
const int n = nums.size();
vector< long long> kSum(k, 0);
long long maxSum = numeric_limits< long long>::min(), prefixSum = 0;
for (int i = 0; i < k - 1; ++i) {
prefixSum += nums[i];
kSum[i] = prefixSum;
}
for (int i = k - 1; i < n; ++i) {
prefixSum += nums[i];
int r = i % k;
maxSum = max(maxSum, prefixSum - kSum[r]);
kSum[r] = min(kSum[r], prefixSum);
}
return maxSum;
}
};
寫 Python3 是這樣:
class Solution:
def maxSubarraySum(self, nums: List[int], k: int) -> int:
n = len(nums)
kSum = [0] * k
prefixSum = 0
maxSum = float("-inf")
for i in range(k - 1):
prefixSum += nums[i]
kSum[i] = prefixSum
for i in range(k - 1, n):
prefixSum += nums[i]
r = i % k
maxSum = max(maxSum, prefixSum - kSum[r])
kSum[r] = min(kSum[r], prefixSum)
return maxSum
寫 Go 是這樣,這邊要注意即便是使用 math.MinInt64 還是要用 int64() 明確轉型,不然預設會用 int 然後就會跟後面的 int64 衝突。
func maxSubarraySum(nums []int, k int) int64 {
n := len(nums)
kSum := make([]int64, k)
prefixSum, maxSum := int64(0), int64(math.MinInt64)
for i := range n {
prefixSum += int64(nums[i])
if i < k-1 {
kSum[i] = prefixSum
continue
}
r := i % k
maxSum = max(maxSum, prefixSum-kSum[r])
kSum[r] = min(kSum[r], prefixSum)
}
return maxSum
}
寫 Rust 是這樣,沒什麼特別要注意的地方,反正寫錯時編譯器會提醒你該如何修正。 :-P
impl Solution {
pub fn max_subarray_sum(nums: Vec< i32>, k: i32) -> i64 {
let k = k as usize;
let n = nums.len();
let mut kSum = vec![0i64; k];
let mut prefixSum = 0i64;
let mut maxSum = i64::MIN;
for i in 0..(k-1) {
prefixSum += nums[i] as i64;
kSum[i] = prefixSum;
}
for i in (k-1)..n {
prefixSum += nums[i] as i64;
let r = i % k;
maxSum = maxSum.max(prefixSum - kSum[r]);
kSum[r] = kSum[r].min(prefixSum);
}
maxSum
}
}
不曉得為何,寫 Rust 有最愉快的感覺。 :-P
2025年11月17日 星期一
Binary Search
今日練習的題目是 300. Longest Increasing Subsequence 主要是需要使用到 Binary Search
首先是 C++ 的 lower_bound
class Solution {
public:
int lengthOfLIS(vector< int>& nums) {
vector< int> arr;
arr.reserve(nums.size());
for (auto& num : nums) {
auto ptr = ranges::lower_bound(arr.begin(), arr.end(), num);
if (ptr == arr.end()) {
arr.push_back(num);
} else {
*ptr = num;
}
}
return arr.size();
}
};
然後是 Python 的 bisect.bisect_left()
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
arr = []
for num in nums:
i = bisect.bisect_left(arr, num)
if i == len(arr):
arr.append(num)
else:
arr[i] = num
return len(arr)
然後是 Go 的 sort.Search()
func lengthOfLIS(nums []int) int {
arr := make([]int, 0, len(nums))
for _, num := range nums {
idx := sort.Search(len(arr), func(i int) bool {
return arr[i] >= num
})
if idx == len(arr) {
arr = append(arr, num)
} else {
arr[idx] = num
}
}
return len(arr)
}
最後是 Rust 的 binary_search
impl Solution {
pub fn length_of_lis(nums: Vec< i32>) -> i32 {
let mut arr = Vec::with_capacity(nums.len());
for num in nums {
let i = match arr.binary_search(&num) {
Ok(index) => index,
Err(index) => index,
};
if i == arr.len() {
arr.push(num);
} else {
arr[i] = num;
}
}
arr.len() as i32
}
}
每種程式語言使用方式都有所不同。



