-
更新于 2023-03-31 271d17a
+
更新于 2024-01-04 6fea1fe
diff --git a/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/index.md b/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/index.md
index f6b449d3..83e8d333 100755
--- a/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/index.md
+++ b/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/index.md
@@ -1,8 +1,6 @@
# Depay: 使用USDT消费的虚拟美元信用卡
-{{< admonition info >}}
Depay的注册和下载链接:[https://depay.depay.one/web-app/register-h5?invitCode=606096&lang=zh-cn](https://depay.depay.one/web-app/register-h5?invitCode=606096&lang=zh-cn),推荐码:**606096**。
-{{< /admonition >}}
我找到了[Depay老板在v2ex上发的主题](https://www.v2ex.com/t/912011),本文的内容主要根据这个主题以及我自己的体验。
diff --git a/zh-cn/index.json b/zh-cn/index.json
index 1ca15e96..2b6b621e 100755
--- a/zh-cn/index.json
+++ b/zh-cn/index.json
@@ -1 +1 @@
-[{"categories":["项目"],"content":" Node-Depend-View https://github.com/kayak4665664/Node-Depend-View 我在学习前端和Node.js开发的过程中完成了这个小项目,它可以将一个项目的依赖关系以图形的形式展示出来,我还将它发布到了npm上,具体还请看上面的链接。感觉用TypeScript做全栈开发还是很有意思的,希望在新的一年里可以先找到一份实习工作!好了,不多说了,加油!💪 ","date":"2024-01-04","objectID":"/zh-cn/node-depend-view/:0:0","tags":["TypeScript","Node.js","命令行工具","前端","全栈","算法","Github"],"title":"Node-Depend-View","uri":"/zh-cn/node-depend-view/"},{"categories":["笔记"],"content":"LeetCode Linked List ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:0","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"707. Design Linked List class MyLinkedList { val: number | undefined; next: MyLinkedList | undefined; prior: MyLinkedList | undefined; constructor () { this.val = undefined; this.next = undefined; this.prior = undefined; } get ( index: number ): number { if ( index == 0 ) return this.val != undefined ? this.val : -1; else if ( !this.next ) return -1; else { let ptr = this.next, i = 1; while ( i \u003c index \u0026\u0026 ptr.next ) { ptr = ptr.next; ++i; } if ( i == index ) return ptr.val != undefined ? ptr.val : -1; else return -1; } } addAtHead ( val: number ): void { if ( this.val == undefined ) this.val = val; else { const next = new MyLinkedList(); next.val = this.val; next.next = this.next; if ( next.next ) next.next.prior = next; next.prior = this; this.val = val; this.next = next; this.prior = undefined; } } addAtTail ( val: number ): void { if ( this.val == undefined ) this.val = val; else { const tail = new MyLinkedList(); tail.val = val; let ptr = this.next; if ( !ptr ) { this.next = tail; tail.prior = this; } else { while ( ptr.next ) ptr = ptr.next; ptr.next = tail; tail.prior = ptr; } } } addAtIndex ( index: number, val: number ): void { if ( index == 0 ) this.addAtHead( val ); else { if ( !this.next ) { if ( index == 1 \u0026\u0026 this.val != undefined ) this.addAtTail( val ); else return; } else { let i = 1, ptr = this.next; while ( i \u003c index \u0026\u0026 ptr.next ) { ++i; ptr = ptr.next; } if ( i == index ) { const prior = new MyLinkedList(); prior.val = val; if ( ptr.prior ) { ptr.prior.next = prior; prior.prior = ptr.prior; } prior.next = ptr; ptr.prior = prior; } else if ( i + 1 == index ) { const tail = new MyLinkedList(); tail.val = val; ptr.next = tail; tail.prior = ptr; } } } } deleteAtIndex ( index: number ): void { if ( index == 0 ) { if ( this.next ) { this.val = this.next.val; this.next = this.next.next; if ( this.next ) this.next.prior = this; } else this.val = undefined; } else if ( !this.next ) return; else { let i = 1, ptr = this.next; while ( i \u003c index \u0026\u0026 ptr.next ) { ++i; ptr = ptr.next; } if ( i == index \u0026\u0026 ptr.prior ) { if ( ptr.next ) { ptr.prior.next = ptr.next; ptr.next.prior = ptr.prior; } else ptr.prior.next = undefined; } } } } /** * Your MyLinkedList object will be instantiated and called as such: * var obj = new MyLinkedList() * var param_1 = obj.get(index) * obj.addAtHead(val) * obj.addAtTail(val) * obj.addAtIndex(index,val) * obj.deleteAtIndex(index) */ ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:1","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"141. Linked List Cycle /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function hasCycle ( head: ListNode | null ): boolean { const m: Map\u003cListNode, boolean\u003e = new Map(); let ptr = head, res = false; while ( ptr !== null ) { if ( !m.has( ptr ) ) { m.set( ptr, true ); ptr = ptr.next; } else { res = true; break; } } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:2","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"142. Linked List Cycle II /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function detectCycle ( head: ListNode | null ): ListNode | null { const m: Map\u003cListNode, boolean\u003e = new Map(); let ptr = head, res: ListNode | null = null; while ( ptr !== null ) { if ( !m.has( ptr ) ) { m.set( ptr, true ); ptr = ptr.next; } else { res = ptr; break; } } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:3","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"160. Intersection of Two Linked Lists /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function getIntersectionNode ( headA: ListNode | null, headB: ListNode | null ): ListNode | null { let m: Map\u003cListNode, boolean\u003e = new Map(), ptrA = headA, ptrB = headB, res: ListNode | null = null; while ( ptrA !== null ) { m.set( ptrA, true ); ptrA = ptrA.next; } while ( ptrB !== null ) { if ( !m.has( ptrB ) ) { m.set( ptrB, true ); ptrB = ptrB.next; } else { res = ptrB; break; } } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:4","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"19. Remove Nth Node From End of List /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function removeNthFromEnd ( head: ListNode | null, n: number ): ListNode | null { let ptr = head, res: ListNode | null, list: ListNode[] = []; while ( ptr !== null ) { list.push( ptr ); ptr = ptr.next; } let len = list.length; if ( n == len \u0026\u0026 head ) res = head.next; else { let prior = list[ len - n - 1 ], next = n == 1 ? null : list[ len - n + 1 ]; prior.next = next; res = head; } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:5","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"206. Reverse Linked List /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function reverseList ( head: ListNode | null ): ListNode | null { let res: ListNode | null = null, list: ListNode[] = [], ptr = head; while ( ptr !== null ) { list.push( ptr ); ptr = ptr.next; } let len = list.length; res = list[ len - 1 ] === undefined ? null : list[ len - 1 ]; for ( let i = len - 1; i \u003e 0; --i ) { let prior = list[ i - 1 ], node = list[ i ]; node.next = prior; } if ( len \u003e 0 ) list[ 0 ].next = null; return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:6","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"203. Remove Linked List Elements /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function removeElements ( head: ListNode | null, val: number ): ListNode | null { let res: ListNode | null = null, list: ListNode[] = [], ptr = head; while ( ptr !== null ) { if ( ptr.val != val ) list.push( ptr ); ptr = ptr.next; } let len = list.length; if ( len \u003e 0 ) res = list[ 0 ]; for ( let i = 0; i \u003c len - 1; ++i ) list[ i ].next = list[ i + 1 ]; if ( len \u003e 0 ) list[ len - 1 ].next = null; return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:7","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"328. Odd Even Linked List /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function oddEvenList ( head: ListNode | null ): ListNode | null { let odd = head, ptr = head, oddTail: ListNode | null = head, even: ListNode | null = null, i = 1, evenTail: ListNode | null = null; while ( ptr !== null ) { if ( i % 2 != 0 ) { if ( i \u003e 1 \u0026\u0026 oddTail ) { oddTail.next = ptr; oddTail = ptr; } } else { if ( i == 2 ) { even = ptr; evenTail = ptr; } else { if ( evenTail ) { evenTail.next = ptr; evenTail = ptr; } } } ptr = ptr.next; ++i; } if ( oddTail ) oddTail.next = even; if ( evenTail ) evenTail.next = null; return odd; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:8","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"234. Palindrome Linked List /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function isPalindrome ( head: ListNode | null ): boolean { let list: number[] = [], ptr = head, res = true; while ( ptr !== null ) { list.push( ptr.val ); ptr = ptr.next; } let left = 0, right = list.length - 1; while (left \u003c= right) { if (list[right] != list[left]) { res = false; break; } ++left; --right; } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:9","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"21. Merge Two Sorted Lists /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { if (list1 == nullptr \u0026\u0026 list2 == nullptr) return nullptr; else if (list1 == nullptr) return list2; else if (list2 == nullptr) return list1; else { ListNode *front, *p, *p1, *p2; if (list1-\u003eval \u003c= list2-\u003eval) { front = list1; p1 = list1-\u003enext; p2 = list2; } else { front = list2; p1 = list1; p2 = list2-\u003enext; } p = front; while (p1 != nullptr \u0026\u0026 p2 != nullptr) { if (p1-\u003eval \u003c= p2-\u003eval) { p-\u003enext = p1; p1 = p1-\u003enext; } else { p-\u003enext = p2; p2 = p2-\u003enext; } p = p-\u003enext; } if (p1 == nullptr) p-\u003enext = p2; else p-\u003enext = p1; return front; } } }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:10","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"2. Add Two Numbers /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function addTwoNumbers ( l1: ListNode | null, l2: ListNode | null ): ListNode | null { let ptr1 = l1, ptr2 = l2; while ( ptr2 !== null || ptr1 !== null ) { if ( ptr2 !== null \u0026\u0026 ptr1 !== null ) { ptr1.val += ptr2.val; if ( ptr1.val \u003e 9 ) { if ( ptr1.next ) { ptr1.next.val += 1; ptr1.val -= 10; } else { let next = new ListNode( 1 ); ptr1.val -= 10; ptr1.next = next; } } if ( ptr2.next \u0026\u0026 ptr1.next === null ) ptr1.next = new ListNode( 0 ); ptr1 = ptr1.next; ptr2 = ptr2.next; } else if ( ptr2 === null \u0026\u0026 ptr1 ) { if ( ptr1.val \u003e 9 ) { if ( ptr1.next ) { ptr1.next.val += 1; ptr1.val -= 10; if ( ptr1.next.val \u003c 10 ) break; ptr1 = ptr1.next; } else { let next = new ListNode( 1 ); ptr1.val -= 10; ptr1.next = next; } } else break; } } return l1; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:11","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"430. Flatten a Multilevel Doubly Linked List /** * Definition for node. * class Node { * val: number * prev: Node | null * next: Node | null * child: Node | null * constructor(val?: number, prev? : Node, next? : Node, child? : Node) { * this.val = (val===undefined ? 0 : val); * this.prev = (prev===undefined ? null : prev); * this.next = (next===undefined ? null : next); * this.child = (child===undefined ? null : child); * } * } */ function flatten ( head: Node | null ): Node | null { let ptr = head; while ( ptr !== null ) { if ( ptr.child ) { let next = ptr.next; let child = flatten( ptr.child ); ptr.child = null; if ( child ) { ptr.next = child; child.prev = ptr; while ( ptr.next ) ptr = ptr.next; ptr.next = next; if ( next ) next.prev = ptr; } } ptr = ptr.next; } return head; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:12","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"138. Copy List with Random Pointer /** * Definition for Node. * class Node { * val: number * next: Node | null * random: Node | null * constructor(val?: number, next?: Node, random?: Node) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * this.random = (random===undefined ? null : random) * } * } */ function copyRandomList ( head: Node | null ): Node | null { let res: Node | null = null, list: Node[] = [], map: Map\u003cNode, number\u003e = new Map(), ptr = head, i = 0; while ( ptr !== null ) { let node = new Node( ptr.val ); list.push( node ); map.set( ptr, i ); ++i; ptr = ptr.next; } ptr = head; i = 0; while ( ptr !== null ) { if ( list[ i ] ) { list[ i + 1 ] ? list[ i ].next = list[ i + 1 ] : null; if ( ptr.random ) { let index = map.get( ptr.random ); index !== undefined ? list[ i ].random = list[ index ] : null; } else list[ i ].random = null; } ++i; ptr = ptr.next; } res = list[ 0 ]; return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:13","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"61. Rotate List /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function rotateRight ( head: ListNode | null, k: number ): ListNode | null { if ( k == 0 ) return head; let map: Map\u003cnumber, ListNode\u003e = new Map(), ptr = head, i = 0, res: ListNode | null = null; while ( ptr ) { map.set( i, ptr ); ptr = ptr.next; ++i; } if ( i \u003c 2 || k % i == 0 ) return head; k = i - k % i; if ( k == 0 ) res = head; else { let node = map.get( k ); node ? res = node : res = null; if ( res ) { ptr = res; while ( ptr.next ) ptr = ptr.next; ptr.next = head; ptr = head; while ( ptr \u0026\u0026 ptr.next !== res ) ptr = ptr.next; if ( ptr ) ptr.next = null; } } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:14","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"最近需要在iPhone上模拟定位,研究了一下,终于发现了一个简单有效的方法。 我在网上找到了好几种办法,在不越狱iPhone的情况下。第一种是使用AnyGo,这个软件是有效的,但是需要付费。第二种是用一个具有root权限的安卓手机,在上面安装这个OTGLocation,之后把iPhone连接到这个安卓手机上。其他方法还有借助Xcode、爱思助手,或者是外接设备,甚至还可以模拟卫星信号欺骗手机。 我觉得这些办法都太麻烦了,在https://shawnhuangyh.com/post/ios-17-location-simulation/这里找到一个简单有效的办法,主要使用了pymobiledevice3。 ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:0","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"1. 在macOS上安装pymobiledevice3: python3 -m pip install -U pymobiledevice3 ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:1","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"2. 在iPhone中开启开发者模式,位于Settings -\u003e Privacy \u0026 Security -\u003e Developer Mode。 ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:2","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"3. 将iPhone连接到macOS上,在macOS上执行: sudo python3 -m pymobiledevice3 remote start-quic-tunnel 将会打印类似以下内容: Interface: utun6 RSD Address: fd7b:e5b:6f53::1 RSD Port: 64337 Use the follow connection option: --rsd fd7b:e5b:6f53::1 64337 RSD Address和RSD Port在第5步要用到。 ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:3","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"4. 确保iPhone此时还没有锁屏,在macOS上执行: sudo pymobiledevice3 mounter auto-mount ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:4","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"5. 继续在macOS中执行: pymobiledevice3 developer dvt simulate-location set --rsd \u003cRSD Address\u003e \u003cRSD Port\u003e -- \u003clatitude\u003e \u003clongtitude\u003e 将\u003c\u003e中的内容替换为自己的内容,分别为第3步中的RSD Address和RSD Port,以及要模拟的纬度和经度。此时在iPhone上查看,定位应该已经变成了模拟的位置。在停止模拟后,iPhone的定位会自动恢复正常。 ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:5","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"Leetcode Arrays 101 ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:0","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"485. Max Consecutive Ones const findMaxConsecutiveOnes = (nums: number[]): number =\u003e { let res = 0, len = 0, end = nums.length; for (let i = 0; i \u003c end; ++i) { if (nums[i] == 1) ++len; else { res = Math.max(res, len); len = 0; } } res = Math.max(res, len); return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:1","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"1295. Find Numbers with Even Number of Digits const findMaxConsecutiveOnes = (nums: number[]): number =\u003e { let res = 0, len = 0, end = nums.length; for (let i = 0; i \u003c end; ++i) { if (nums[i] == 1) ++len; else { res = Math.max(res, len); len = 0; } } res = Math.max(res, len); return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:2","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"977. Squares of a Sorted Array function sortedSquares(nums: number[]): number[] { nums = nums.map(num =\u003e num * num); nums.sort((a, b) =\u003e a - b); return nums; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:3","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"1089. Duplicate Zeros /** Do not return anything, modify arr in-place instead. */ function duplicateZeros ( arr: number[] ): void { let i = 0, len = arr.length; while ( i \u003c len ) { if ( arr[ i ] != 0 ) ++i; else { arr.splice( i, 0, 0 ); arr.pop(); i += 2; } } }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:4","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"88. Merge Sorted Array /** Do not return anything, modify nums1 in-place instead. */ function merge ( nums1: number[], m: number, nums2: number[], n: number ): void { let i = 0, end = m; for ( let num of nums2 ) { while ( i \u003c end \u0026\u0026 nums1[ i ] \u003c num ) ++i; nums1.splice( i, 0, num ); nums1.pop(); ++end; } }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:5","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"27. Remove Element function removeElement ( nums: number[], val: number ): number { let res = 0, i = 0; while ( i \u003c nums.length ) { if ( nums[ i ] != val ) { ++res; ++i; } else nums.splice( i, 1 ); } return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:6","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"26. Remove Duplicates from Sorted Array function removeDuplicates(nums: number[]): number { const set: Set\u003cnumber\u003e = new Set(); let i = 0; while (i \u003c nums.length) { if (set.has(nums[i])) nums.splice(i, 1); else { set.add(nums[i]); ++i; } } return nums.length; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:7","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"1346. Check If N and Its Double Exist function checkIfExist(arr: number[]): boolean { let res = false; const set: Set\u003cnumber\u003e = new Set(arr); const zeros = arr.filter(num =\u003e num == 0); const len = zeros.length; for (let s of set) { if (set.has(2 * s)) { if (s == 0 \u0026\u0026 len \u003c 2) continue; res = true; break; } } return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:8","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"941. Valid Mountain Array function validMountainArray(arr: number[]): boolean { let res = true, inc = true, len = arr.length; if (len \u003c 3 || arr[0] \u003e= arr[1] ) return false; for (let i = 0; i \u003c len; ++i) { if (inc \u0026\u0026 (arr[i] \u003c arr[i - 1])) inc = false; if (arr[i] == arr[i - 1] || (!inc \u0026\u0026 (arr[i] \u003e= arr[i - 1]))) { res = false; break; } } if (inc) res = false; return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:9","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"1299. Replace Elements with Greatest Element on Right Side function replaceElements(arr: number[]): number[] { let res: number[] = [], len = arr.length; for (let i = 0; i \u003c len - 1; ++i) { let max = Math.max(...arr.slice(i + 1, len)); res.push(max); } res.push(-1); return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:10","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"26. Remove Duplicates from Sorted Array function removeDuplicates(nums: number[]): number { const set: Set\u003cnumber\u003e = new Set(); let i = 0; while (i \u003c nums.length) { if (set.has(nums[i])) nums.splice(i, 1); else { set.add(nums[i]); ++i; } } return nums.length; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:11","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"283. Move Zeroes /** Do not return anything, modify nums in-place instead. */ function moveZeroes ( nums: number[] ): void { let i = 0, j = 1, len = nums.length; while ( i \u003c len \u0026\u0026 j \u003c len ) { if ( nums[ i ] == 0 \u0026\u0026 nums[ j ] != 0 ) { let temp = nums[ i ]; nums[ i ] = nums[ j ]; nums[ j ] = temp; } if ( nums[ i ] != 0 ) ++i; if ( j \u003c i ) j = i; else if ( nums[ j ] == 0 ) ++j } }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:12","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"905. Sort Array By Parity function sortArrayByParity(nums: number[]): number[] { let res: number[] = []; res = nums.sort((a, b) =\u003e { if (a % 2 == 0 \u0026\u0026 b % 2 != 0) return -1; else if (a % 2 != 0 \u0026\u0026 b % 2 == 0) return 1; else return 0; }); return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:13","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"27. Remove Element function removeElement ( nums: number[], val: number ): number { let res = 0, i = 0; while ( i \u003c nums.length ) { if ( nums[ i ] != val ) { ++res; ++i; } else nums.splice( i, 1 ); } return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:14","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"1051. Height Checker function heightChecker(heights: number[]): number { let res = 0, len = heights.length; const temp = [...heights]; heights.sort((a, b) =\u003e a - b); for (let i = 0; i \u003c len; ++i) { if (temp[i] != heights[i]) ++res; } return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:15","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"414. Third Maximum Number function thirdMax ( nums: number[] ): number { let a = -Infinity, b = -Infinity, c = -Infinity; for ( let n of nums ) { if ( n \u003e a || n \u003e b \u0026\u0026 n \u003c a || n \u003e c \u0026\u0026 n \u003c b ) c = n; if ( c \u003e b ) { let t = c; c = b; b = t; } if ( b \u003e a ) { let t = b; b = a; a = t; } } if ( c != -Infinity ) return c; else return a; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:16","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"448. Find All Numbers Disappeared in an Array function findDisappearedNumbers(nums: number[]): number[] { const len = nums.length, s: Set\u003cnumber\u003e = new Set(nums), res: number[] = []; for (let i = 1; i \u003c= len; ++i) { if (!s.has(i)) res.push(i); } return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:17","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"977. Squares of a Sorted Array function sortedSquares(nums: number[]): number[] { nums = nums.map(num =\u003e num * num); nums.sort((a, b) =\u003e a - b); return nums; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:18","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["日记"],"content":" 希望下周能到50小时🌲 ","date":"2023-10-01","objectID":"/zh-cn/focus-statistics-40-2023/:0:0","tags":["专注统计"],"title":"专注统计 (2023 40周)","uri":"/zh-cn/focus-statistics-40-2023/"},{"categories":["笔记"],"content":"今天发现了一个有可以限制Apple Silicon Macbook电池充电的命令行工具,名字叫做battery。 battery https://github.com/actuallymentor/battery 之前我一直在用AlDente,与它相比,battery的优点是可以直接在命令行中使用,而且完全免费,而AlDente如果不付费就只能使用最基础的功能,而且它的图标还一直在菜单栏占用了一个位置。 只需一行命令即可安装: curl -s https://raw.githubusercontent.com/actuallymentor/battery/main/setup.sh | bash 安装完成后,可以使用battery help查看帮助信息,就是这么简单。 ","date":"2023-09-23","objectID":"/zh-cn/battery-battery-charge-limiter-for-apple-silicon-macbook-devices/:0:0","tags":["macOS","命令行工具"],"title":"battery: 限制Apple Silicon Macbook的电池充电","uri":"/zh-cn/battery-battery-charge-limiter-for-apple-silicon-macbook-devices/"},{"categories":["项目"],"content":"前天忽然发现Chrome Devtools里的字体家族不能直接修改,查了一下发现可以写一个扩展来解决这个问题。 Devtools-Font https://github.com/kayak4665664/Devtools-Font 我主要参考了https://gist.github.com/vbsessa/e337d0add70a71861b8c580d5e16996e,但是按照这个教程“Sources”中的字体没有变化,我在这个基础上做了一些修改。最后我把字体改成了FiraCode Nerd Font,不得不说这个字体真的好看,还有连笔效果。 ","date":"2023-08-26","objectID":"/zh-cn/devtools-font/:0:0","tags":["浏览器","Chrome扩展","前端"],"title":"Devtools-Font","uri":"/zh-cn/devtools-font/"},{"categories":["日记"],"content":"我们于7月12日从雁栖湖校区搬到了北京城里,这里放一些我在雁栖湖校区最后几天拍的照片。 彩虹 两头驴 乌鸦 蜂 山上的彩灯 路灯 鸭子 电线上的鸟 金鱼 鸬鹚 鸬鹚 鸬鹚 山上的雾 下雨之后 ","date":"2023-07-16","objectID":"/zh-cn/last-days-at-yanqi-lake-campus/:0:0","tags":["UCAS","转悠"],"title":"在雁栖湖校区最后的几天","uri":"/zh-cn/last-days-at-yanqi-lake-campus/"},{"categories":["笔记"],"content":"我在完成Springboot-Demo的过程中,遇到了一个获取资源文件的问题。 刚开始,我使用Maven将项目打包成了jar包,然后运行,程序报错找不到json文件了。经过排查,我发现问题出在了我获取json文件的方式上,我使用了相对路径,但是在运行jar包时,相对路径是相对于jar包所在的目录,而不是相对于源代码目录,这样就找不到json文件了。 解决的方法是使用ClassLoader类的getResourceAsStream方法,它可以根据给定的路径名返回一个InputStream对象,然后就可以使用这个对象来读取资源文件的内容。比如: //假如存在一个Main类,获取类加载器对象 ClassLoader classLoader = Main.class.getClassLoader(); //根据资源文件名获取输入流对象 InputStream inputStream = classLoader.getResourceAsStream(\"test.log\"); ","date":"2023-06-11","objectID":"/zh-cn/get-resource-files-through-classloader/:0:0","tags":["Java"],"title":"通过类加载器获取资源文件","uri":"/zh-cn/get-resource-files-through-classloader/"},{"categories":["项目"],"content":"这个学期我选了一门Java编程课,最后要完成一个项目,就是Springboot-Demo。 Springboot-Demo https://github.com/kayak4665664/Springboot-Demo 这个程序的功能就是从json文件中读取数据,再显示到页面上。除了Springboot框架,前端还是我常用的Layui和Highcharts。 我选这门Java课主要就是想练习一下Java的Web开发。我记得我大三的时候有一门软件工程实践课,有一个实验就是要做一个Web应用。当时我第一次接触Web开发,本来想用Java和Springboot来完成,我在网上找了教程,感觉有点看不明白。然后我又了解了一下python的Django框架,发现比较容易理解,最后我就用Django做了那个实验。这次我用Springboot,感觉和Django其实也差不多。 ","date":"2023-06-11","objectID":"/zh-cn/springboot-demo/:0:0","tags":["Java"],"title":"Springboot-Demo","uri":"/zh-cn/springboot-demo/"},{"categories":["日记"],"content":"以前的眼镜是上大学之前配的,已经有点看不清了。正好我在北京,听说潘家园(北京眼镜城)的眼镜特别便宜,我就去了。 之前忘了在哪看到了变色眼镜,可以根据紫外线强度变色,我决定这次就配一副变色眼镜。我在网上查了一下,大家都说蔡司和依视路的镜片比较好,我比较了一番,最后决定买一副蔡司焕色视界X镜片。我的度数应该在800度以内,所以可以选择折射率1.6的镜片。 我看到有攻略说网上配眼镜比较便宜,先去验光,再到实体店试戴镜框,记下镜框型号,然后再到网上购买镜框,再把镜框和验光单发给卖镜片的商家,加工好之后再邮寄过来。我觉得这个方法环节太多,而且我尤其不喜欢等快递,所以我还是决定去潘家园看看。网上都说潘家园的水很深,我在知乎和小红书上看到了好多攻略,看得云里雾里的,我后来感觉这些多半都是软广告,不如不看。我觉得只要不比网上的价格高,镜片是正品,镜框合适,就可以了。 另外还有一点,大家都说不要在潘家园的眼镜店里验光,结果不太准确。最好去北京同仁验光配镜中心,但是需要提前预约,我预约的时候已经约满了。我就预约了去宝岛眼镜验光,宝岛眼镜是全国连锁的,也是比较专业的。 国科大雁栖湖校区离北京城区太远了,好在学校每天都有来回的班车。周六比较空闲,我预定了周六早上7点的班车。我第一次坐班车去城里,没想到周六进城的人这么多,我赶到车站时已经坐满了一辆车,我上了第二辆车也只剩下四、五个座位了。不到一个小时就到了奥运村下车点,自从2月开学以来还是第一次进城。 我马上又坐上了地铁,先去宝岛眼镜验光。下了地铁慢慢走过去刚好9点,店里一个顾客都没有。免费注册了一个会员,“精致验光”服务可以优惠10元到50元。之后开始验光,大概用了3种仪器,用了十几分钟。验光师告诉我结果,左右眼都是600多度,都有100度左右的散光。还好,和我上大学之前的差不多。戴上插片眼镜试了试,感觉不错。宝岛眼镜的验光结果可以直接在微信公众号里查看,这一点是很方便的。验光师还说,如果常看近处最好不要戴矫正到1.0的眼镜,0.8、0.9的就可以了。根据验光结果,我确实需要配一副变色眼镜。 从宝岛眼镜出来直奔公交车站,赶往潘家园。到站大概是10点,和网上说的一样,一下车就有不少拉客配眼镜的人。在过街天桥上,对面就是北京眼镜城。一进大门,全是眼镜店,网上都说楼层越高的眼镜店越便宜,我就直接上楼了。在三楼四楼全转了一圈,不知道该进谁家。我看到了几家网红店,里面的顾客确实要比一般的店多一些。 我下到了二楼,这次我决定,哪家店招揽我我就进哪家。进了第一家,我直接和老板说我要焕色视界X镜片。老板拿出了一个蔡司产品手册,开始翻找,找了半天没有找到,我一看他的产品手册是去年的,焕色视界X是新出的,应该确实不在里面。第二家也是一样的情况,我又看了几家,也都没有我要的镜片。我怀疑是不是都没有,我决定再看几家,如果还没有就回去在网上买。 又进了一家店,这家店的老板是一位南方口音的阿姨。她说她的产品手册是今年的,应该可以找到。翻了翻册子,果然找到了。我问她多少钱,她拿出了计算器,用一个折扣系数乘以产品手册上的定价。潘家园的眼镜店一般都可以打定价的3至4折,每家店的老板都有一个长得差不多的计算器。她给出了一个价格,但是要比网上的高不少。开始和她讨价还价,最后我拿出了京东购物车里的镜片价格给她看,终于把价格压了下来,镜片和镜框1000元全包了。之后开始选镜框,拿出了十几个挨个试,大概选出了几个。我又和她再确认镜片的型号规格,这时候我发现刚才看错了,刚才看的是一个其他型号的,不太一样。她又说我要的型号1000元拿不下来,可是我刚才给她看京东购物车里的我要的型号的镜片1000元可以拿下。总之又是一阵讨价还价,我觉得这是在浪费时间,我和她说不行的话我再去其他店看看吧。她看我要走她就松口了,她赶紧让我给她验光单,但是这个时候我真的有点不想在她家配眼镜了。我问她什么时候可以拿到眼镜,她说定制镜片至少要等5到7天,我还以为在实体店可以当场带走。我又问她普通镜片可不可以当场带走,她告诉我等1个小时就可以了,她极力推荐我购买普通镜片。看得出来,她对变色镜片不太熟悉。总的来说,我觉得这家店的体验不太好,我决定还是去其他店看看。但是这位老板还是非常热情地让我购买普通镜片,我看了看表,11点多了,我只好借口肚子饿了要吃午饭先走一步。 我又上了三楼,和二楼差不多,产品手册上都没有我要的镜片,好几家店的老板都给一个人打电话,估计是蔡司镜片代理,都说我要的镜片没有现片,必须找厂家调货。我又随便进了一家店,这家店的老板是一个年轻人,说话比较爽快。我看他对变色镜片好像比较熟悉,他给我镜片定价的3折大概1100元,我拿出手机给他看京东购物车里镜片的价格,我还告诉他刚才我看了一家可以1000元镜片镜框全拿下。他很快就说可以,比我想象得快。之后开始挑选镜框,大概选出了几个。我又和他确认了镜片的型号规格和价格,没有问题。他也说定制镜片需要5至7天才能拿到,我在变色镜片和普通镜片之间犹豫,我借口肚子饿了要吃午饭再考虑考虑。 我又上了四楼,情况差不多,而且给的价格都比较高。我决定就去三楼那家店。我逛了半个小时,回到了那家店。我又挑选了几个镜框,又和老板确认了镜片的型号规格和价格。我付了钱,加了老板的微信,眼镜制作好后他会通知我。我下到了一楼,这时候刚过12点。我之前买了下午4点半从北京北站到怀柔北站的火车票,我看时间比较富余,我想改签到下午2点半的车次。但是人满了不能改签。我开始思考我如何打发中间的几个小时,我决定先去吃饭。 在北京吃饭太贵了,在路边小店随便吃一碗面条就得20元,里面还没有肉。我沿着马路一路向北,发现了一家麦当劳。比起其他饭店,我觉得麦当劳还是不错的,价格可以接受,可以吃到货真价实的肉,味道也可以,不用担心食品安全,尤其是那个随心配套餐,13.9元可以买一个双层吉士汉堡和菠萝派,虽然比以前涨价了。我在麦当劳里找了个位置坐下,继续考虑吃完饭去哪。我决定从这里骑车到北京北站,可以看看沿途的街景,打发时间。 从麦当劳出来,找了一辆哈啰单车,我之前买了月卡,两个小时之内免费。从东三环到长安街再到北二环,用了一个半小时。到了北站还剩几十分钟,去旁边凯德MALL随便逛了逛,然后上了火车,回到了学校。 过了一周,我的眼镜制作好了。我又约好了周六早上7点的班车,买了下午两点半的火车票。 和上次一样,不到8点就到了奥运村下车点。时间还早,我先去奥林匹克公园转了转,里面人很少。 之后上了地铁前往潘家园,大概9点多到达。上了三楼我发现我找不到那家店在哪了,绕了一圈才找到了。我拿到了眼镜,检查了一下,查验了镜片的真伪,没有发现什么问题。我走出大楼,眼镜果然变色了,感觉真不错。 我早上6点吃了早饭,已经饿了。我又走到了那家麦当劳,但是刚过10点,还在卖早餐,我找位置坐下休息了半个小时。 吃完饭,我开始朝着北京北站的方向闲逛,一会坐地铁一会步行。 到了北站还有几十分钟,我去旁边的凯德MALL逛了逛,逛到了小米之家,看了看小米最新的产品。之后坐上了火车,回到了学校。 总的来说,潘家园的水确实很深,有很多坑,不过在价格上有优势。假如不差钱的话,其实去宝岛眼镜这种大型连锁店是一个更好的选择,服务更好更省心。这次配的眼镜还是比较符合我的预期,比较满意。 ","date":"2023-04-26","objectID":"/zh-cn/go-to-panjiayuan-to-get-glasses/:0:0","tags":["转悠"],"title":"去潘家园配眼镜","uri":"/zh-cn/go-to-panjiayuan-to-get-glasses/"},{"categories":["项目"],"content":"上一篇文章介绍了如何抓包,这篇文章介绍编写程序解析抓包文件。 信息 本文涉及的源代码在GitHub仓库: Pcap-Parser https://github.com/kayak4665664/Pcap-Parser Pcap文件中包含了网络数据包的信息,包括源IP地址、目的IP地址、源端口、目的端口、传输层协议、应用层协议等。因此,程序的思路就是从数据链路层开始解析,直到应用层,解析出每一层的协议类型和协议数据。在实现上可以参考Wireshark的解析结果。 对于C/C++,可以使用\u003cpcap.h\u003e处理Pcap文件。之后,使用\u003cnet/ethernet.h\u003e、\u003cnetinet/ip.h\u003e、\u003cnetinet/tcp.h\u003e定义的以太网头部、IP头部、TCP头部结构体解析数据链路层、网络层、传输层。另外,IP头部和TCP头部都有options,这个字段结构体中没有。 应用层的协议种类比较多,需要针对每一种协议编写程序。我的程序支持解析HTTP和TLS协议。 HTTP是明文协议,数据字段之间是用\\r\\n分隔的,另外需要考虑一个HTTP消息分成了好多个packet,对相关packet重组之后才能解析出正确的结果。而TLS是加密协议,比较复杂,要按照协议的结构进行解析,也要考虑重组的情况。 以上只是一些简单的思路,实际上还有许多复杂的情况没有覆盖。 ","date":"2023-04-11","objectID":"/zh-cn/pcap-parser/:0:0","tags":["C++","Github","算法","抓包","命令行工具"],"title":"Pcap-Parser","uri":"/zh-cn/pcap-parser/"},{"categories":["笔记"],"content":"使用Charles、Wireshark和tcpdump对手机App抓包。 信息 我在macOS上对iPhone进行抓包,但是对于其他系统和设备,方法和原理也是类似的。 ","date":"2023-04-10","objectID":"/zh-cn/capture-packets-for-mobile-apps/:0:0","tags":["抓包","iPhone","macOS","命令行工具"],"title":"手机App抓包","uri":"/zh-cn/capture-packets-for-mobile-apps/"},{"categories":["笔记"],"content":"Wireshark Wireshark是一个开源的网络分析工具,可以用来抓取网络数据包。它可以在macOS、Windows和Linux上运行。 在macOS上,可以使用brew安装Wireshark: brew install --cask wireshark 使用Wireshark抓包也很简单,比如选择Wi-Fi接口就可以抓无线网卡的数据包。 ","date":"2023-04-10","objectID":"/zh-cn/capture-packets-for-mobile-apps/:1:0","tags":["抓包","iPhone","macOS","命令行工具"],"title":"手机App抓包","uri":"/zh-cn/capture-packets-for-mobile-apps/"},{"categories":["笔记"],"content":"tcpdump tcpdump是一个命令行工具,可以用来抓取网络数据包。假如在没有图形界面的服务器上,可以使用它来抓取数据包。 在macOS上,可以使用brew安装tcpdump: brew install tcpdump 使用tcpdump抓包,比如抓取12345端口的数据包并保存为pcap文件: tcpdump port 12345 -w capture.pcap ","date":"2023-04-10","objectID":"/zh-cn/capture-packets-for-mobile-apps/:2:0","tags":["抓包","iPhone","macOS","命令行工具"],"title":"手机App抓包","uri":"/zh-cn/capture-packets-for-mobile-apps/"},{"categories":["笔记"],"content":"Charles Charles是一个HTTP代理服务器,可以用来抓取HTTP和HTTPS的数据包,和Fiddler类似。 在macOS上,也使用brew安装Charles: brew install --cask charles ","date":"2023-04-10","objectID":"/zh-cn/capture-packets-for-mobile-apps/:3:0","tags":["抓包","iPhone","macOS","命令行工具"],"title":"手机App抓包","uri":"/zh-cn/capture-packets-for-mobile-apps/"},{"categories":["笔记"],"content":"手机App抓包 对于MacBook,如果已经连接了Wi-Fi,就不能开启无线热点了。所以需要用Charles来建立一个代理服务器,然后手机连接到这个代理服务器上。主要步骤如下: macOS设备和iPhone都连接到第三个设备开启的移动热点,确保处于同一个局域网内。 在macOS设备中启动Charles,设置代理服务,默认端口为8888。 在iPhone的无线网络设置中,将代理服务器设置为macOS设备的IP地址,端口为8888。 iPhone在浏览器中访问chls.pro/ssl,下载并安装证书。 iPhone在General -\u003e About -\u003e Certificate Trust Settings中,将Charles的证书设置为信任。 iPhone在General -\u003e VPN \u0026 Device Management中安装Charles的描述文件。 由于Charles只能抓取HTTP和HTTPS的数据包,所以这里在macOS设备中启动Wireshark,选择Wi-Fi接口抓取所有协议的数据包。 在iPhone中打开需要抓包的App,进行相关操作。 Wireshark停止抓包,之前设置的代理服务器端口是8888,所以可以通过tcp.port == 8888过滤无关的数据包,将过滤后的包保存为pcap文件。 ","date":"2023-04-10","objectID":"/zh-cn/capture-packets-for-mobile-apps/:4:0","tags":["抓包","iPhone","macOS","命令行工具"],"title":"手机App抓包","uri":"/zh-cn/capture-packets-for-mobile-apps/"},{"categories":["笔记"],"content":"境外的购物网站很多都不支持中国银联的银行卡,而中国银行长城跨境通借记卡是一个可以在线申请、没有申请门槛也没有年费的卡。 信息 我主要在跨境通VISA/万事达借记卡介绍与网上支付体验这篇博客上了解到了这个卡,感谢作者的分享。 跨境通卡有许多种类,但是申请的流程都是一样的,我申请的是万事达世界卡,这个卡的卡面是莫奈的日出印象,很漂亮。我主要介绍我自己办理的过程,其他详细的信息可以参考上面的博客。 ","date":"2023-03-23","objectID":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/:0:0","tags":["境外支付"],"title":"网上申请中国银行万事达借记卡","uri":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/"},{"categories":["笔记"],"content":"网上申请 中国银行上海分行万事达世界卡申请 https://cloud.bankofchina.com/sh/api/net/common/url/adr?id=kuajinggomastercard 在手机上打开以上链接,根据要求提交资料,邮寄地址必须精确到门牌号,开户行可以任选。 技巧 我在这一步遇到了一个问题,我填自己的手机号死活收不到验证码。我用中国移动和多号办理了一个副号,然后用这个副号就可以收到验证码了。我发现发送验证码的是106980095566这个号码,不是中国银行的客服热线95566。106980095566这个号码是可以发送TD退订的,我猜测我以前应该是退订了这个号码的短信服务,所以收不到验证码。 提交申请之后可以在上面的链接中查询进度,如果申请失败了也会收到短信提醒。我第一次申请就是写了学校的地址,没有精确到门牌号,所以申请失败了。 如果申请通过,大概两个星期可以收到通过EMS邮寄的银行卡。 ","date":"2023-03-23","objectID":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/:1:0","tags":["境外支付"],"title":"网上申请中国银行万事达借记卡","uri":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/"},{"categories":["笔记"],"content":"线下激活 收到银行卡之后到任意一个中国银行网点激活,需要带上身份证和银行卡。 在智能柜台就可以自助激活,默认的密码是身份证倒数第六位到倒数第二位。激活时可以修改绑定的手机号码,激活之后会把卡片关联到手机银行。 ","date":"2023-03-23","objectID":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/:2:0","tags":["境外支付"],"title":"网上申请中国银行万事达借记卡","uri":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/"},{"categories":["笔记"],"content":"激活之后 激活之后要给银行卡转入外汇,外汇需要通过中国银行I类卡购买。 另外,必须在手机银行中开通网上支付功能: 在“限额设置 -\u003e 限额设置”中调高限额 开通“限额设置 -\u003e 小额/凭签名免密(POS消费)” 开通“限额设置 -\u003e 磁条交易限额设置” 开通“支付设置 -\u003e 电子支付-手机支付” 开通“支付设置 -\u003e 电子支付-网上支付” 开通“支付设置 -\u003e 跨行支付 -\u003e 在线支付” 开通“支付设置 -\u003e 跨行支付 -\u003e 跨行代扣” 开通“支付设置 -\u003e 跨行支付 -\u003e 跨行订购” ","date":"2023-03-23","objectID":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/:3:0","tags":["境外支付"],"title":"网上申请中国银行万事达借记卡","uri":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/"},{"categories":["笔记"],"content":"用卡注意事项 消费或ATM取现支持直接使用美元、欧元、日元、港币等19种外币,无需货币转换。免收货币转换费、跨境手续费等消费手续费。每月免收首笔境外ATM取现和余额查询手续费。 外汇和外钞都可以用来消费和支付,使用时不会产生任何转换费。 若借记卡开卡后6个月内没有发生任何动账交易,停止非柜面业务。 如果长时间不用卡,卡片余额必须不为0。 绑卡或者日常消费时,美元账户余额须不少于2美元。 开户行是上海市分行,与实体卡片有关的业务(如丢失补卡、到期换卡等)需要去上海地区网点办理。 在境内转账外币只能转账给本人账户和直系亲属账户,本人的非中国银行账户、直系亲属的账户之间的外币转账需要到柜台办理。 消费时不会立即扣款,而是冻结特定比例的资金,等待银行入账后再解冻资金扣款,入账时间一般是两至三天。美元消费冻结100%、非美元消费冻结102%。 关注“中国银行微银行”公众号,绑定跨境通卡,可以开启动账消息提醒。但是只有入账交易通知,没有冻结通知。可以开通短信交易提醒,每月2元,需要用中国银行I类卡支付。 外币账户的扣款顺序为:交易币种钞户 -\u003e 交易币种汇户 -\u003e 美元钞户 -\u003e 美元汇户,只能使用一个外币账户全额支付,不能从多个账户扣款。 无卡交易仅需卡号、有效期、背面签名区后三位数字,不需要交易密码,因此三个信息务必保密。 不检验帐单地址,不支持AVS系统验证。 ","date":"2023-03-23","objectID":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/:4:0","tags":["境外支付"],"title":"网上申请中国银行万事达借记卡","uri":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/"},{"categories":["笔记"],"content":"使用Touch ID来验证sudo命令,这样就不用每次都输入密码了。 在Terminal中输入以下命令,之后重启Terminal即可。 sudo sed -i \".bak\" '2s/^/auth sufficient pam_tid.so\\'$'\\n/g' /etc/pam.d/sudo 这个命令首先备份/etc/pam.d/sudo为/etc/pam.d/sudo.bak,然后在第二行插入auth sufficient pam_tid.so。 如果恢复默认设置,可以使用以下命令: sudo mv /etc/pam.d/sudo.bak /etc/pam.d/sudo ","date":"2023-03-22","objectID":"/zh-cn/authorize-sudo-commands-with-touch-id/:0:0","tags":["macOS","命令行工具"],"title":"用Touch ID授权sudo命令","uri":"/zh-cn/authorize-sudo-commands-with-touch-id/"},{"categories":["笔记"],"content":" 摘要 ChatGPT的API正式发布了,可以在Python中使用了。 ChatGPT API 简介 https://openai.com/blog/introducing-chatgpt-and-whisper-apis 注册OpenAI账号之后,在https://platform.openai.com/account/api-keys中创建一个API Key。在https://platform.openai.com/account/usage中可以看到,账号中有$18的免费额度,4月1日过期。 这次发布的ChatGPT模型gpt-3.5-turbo与ChatGPT产品中使用的模型相同。另外,还发布了gpt-3.5-turbo-0301,这个模型至少在6月1日之前是被支持的。 完整的API使用指导可以在这里找到: ChatGPT API 使用指导 https://platform.openai.com/docs/guides/chat 简单来说,要在Python中使用ChatGPT API,需要安装openai这个Python包。 # 如果没有安装openai,可以使用下面的命令安装 pip install openai # 如果之前安装了openai,使用下面的命令更新 pip install openai --upgrade 之后,import openai,然后使用openai.Completion.create函数来调用API即可。 下面是我写的一个简单的Python脚本,可以与ChatGPT进行多轮对话。 import os import openai # 这里要写上你自己的API Key os.environ[\"OPENAI_API_KEY\"] = \"sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\" openai.api_key = os.getenv(\"OPENAI_API_KEY\") messages = [ {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, ] # 这个函数用来调用API def get_response(messages): completion = openai.ChatCompletion.create( model=\"gpt-3.5-turbo\", messages=messages, ) return completion.choices[0].message.content # type: ignore while True: try: print(\"type 'quit' to exit, type 'new' to begin a new conversation\") user_content = input(\"You: \") if user_content == \"quit\": break elif user_content == \"new\": messages = [ {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, ] print(\"new conversation started\\n\") continue else: messages.append({\"role\": \"user\", \"content\": user_content}) response = get_response(messages) print(\"Assistant:\", response + \"\\n\") # 这里把Assistant的回复也加入到messages中,联系上下文 messages.append({\"role\": \"assistant\", \"content\": response}) except Exception as e: print(e) 运行之后是这样子的, 示例 type ‘quit’ to exit, type ’new’ to begin a new conversation You: What is the biggest animal in the world? Assistant: The biggest animal in the world is the blue whale. It can grow up to 100 feet long and weigh as much as 200 tons. type ‘quit’ to exit, type ’new’ to begin a new conversation You: Please write a poem about blue whales. Assistant: Majestic and mighty, The blue whale swims through the sea, Largest creature on earth, Behold its great beauty. A vast and gentle giant, Graceful in every move, Plunge deep into the ocean, Embrace the whale and groove. With a heart that’s enormous, And lungs as large as a car, Sing to the depths of the ocean, Your melodic, haunting bar. A creature so magnificent, Awe inspiring, and grand, Nowhere else found on earth, A true wonder of the land. Let us protect this great whale, So that it may flourish and thrive, For a world without the blue whale, Is a world less truly alive. type ‘quit’ to exit, type ’new’ to begin a new conversation You: new new conversation started type ‘quit’ to exit, type ’new’ to begin a new conversation You: 世界上最大的动物是什么? Assistant: 世界上最大的动物是蓝鲸。它们可以长达30米长,重达173吨,是地球上已知最大的动物。 type ‘quit’ to exit, type ’new’ to begin a new conversation You: 请写一首关于蓝鲸的诗。 Assistant: 在深深的海洋里 有一种生物,比海洋还大 它游荡于大海之中 它的名字叫做蓝鲸 蓝鲸身长三十米 重达一百七十三吨 它们是地球上最大的动物 不同寻常的存在 它们的歌声遥远而美丽 在海洋里有时听得见 它们善良而又神秘 是这片蔚蓝海洋之主 蓝鲸,你的身影 在海洋中,如此崇高 你的力量与恩宠 在人间,永世留存 type ‘quit’ to exit, type ’new’ to begin a new conversation You: quit ","date":"2023-03-03","objectID":"/zh-cn/using-the-chatgpt-api-in-python/:0:0","tags":["ChatGPT","Python"],"title":"在Python中使用ChatGPT API","uri":"/zh-cn/using-the-chatgpt-api-in-python/"},{"categories":["笔记"],"content":"在iOS和iPadOS上,可以在设置中开启私有WiFi地址来随机化MAC地址。在macOS上没有这个选项,但是我们可以通过命令行来实现这一点。 我在Github上找到了SpoofMAC,它是一个Python脚本,不仅适用于macOS,也可以在Windows和Linux上使用。它可以随机化MAC地址,也可以将MAC地址设置为任何值。 SpoofMAC https://github.com/feross/spoofmac 安装SpoofMAC很简单,只需要pip install SpoofMAC。 ","date":"2023-03-02","objectID":"/zh-cn/randomize-mac-address-for-macos/:0:0","tags":["macOS","Python","命令行工具"],"title":"随机化macOS的MAC地址","uri":"/zh-cn/randomize-mac-address-for-macos/"},{"categories":["笔记"],"content":"使用方法 下面是在macOS上使用SpoofMAC修改MAC地址的示例。 技巧 要直接在终端中运行spoof-mac,需要将bin添加到PATH中。如果你使用的是zsh,你可以在~/.zshrc中添加,例如export PATH=$PATH:~/Library/Python/3.9/bin。 首先,列出所有可用的设备 spoof-mac list 将会得到类似下面的输出 示例 - “Ethernet” on device “en0” with MAC address 70:56:51:BE:B3:00 - “Wi-Fi” on device “en1” with MAC address 70:56:51:BE:B3:01 - “Bluetooth PAN” on device “en1” 然后,随机化MAC地址 sudo spoof-mac randomize en1 # 或者 sudo spoof-mac randomize wifi 要复原MAC地址,只需运行 sudo spoof-mac reset en1 # 或者 sudo spoof-mac reset wifi ","date":"2023-03-02","objectID":"/zh-cn/randomize-mac-address-for-macos/:1:0","tags":["macOS","Python","命令行工具"],"title":"随机化macOS的MAC地址","uri":"/zh-cn/randomize-mac-address-for-macos/"},{"categories":["笔记"],"content":"pwgen可以在命令行中生成随机又安全密码! pwgen https://pwgen.sourceforge.io/ 直接使用Homebrew安装:brew install pwgen。 用法也很简单,比如pwgen -sy 50就是生成50个字符的密码,包含大小写字母、数字和特殊字符。更多用法可以使用pwgen -h查看: 注意 Usage: pwgen [ OPTIONS ] [ pw_length ] [ num_pw ] Options supported by pwgen: -c or –capitalize Include at least one capital letter in the password -A or –no-capitalize Don’t include capital letters in the password -n or –numerals Include at least one number in the password -0 or –no-numerals Don’t include numbers in the password -y or –symbols Include at least one special symbol in the password -r or –remove-chars= Remove characters from the set of characters to generate passwords -s or –secure Generate completely random passwords -B or –ambiguous Don’t include ambiguous characters in the password -h or –help Print a help message -H or –sha1=path/to/file[#seed] Use sha1 hash of given file as a (not so) random generator -C Print the generated passwords in columns -1 Don’t print the generated passwords in columns -v or –no-vowels Do not use any vowels so as to avoid accidental nasty words ","date":"2023-02-28","objectID":"/zh-cn/pwgen-random-password-generator/:0:0","tags":["命令行工具"],"title":"pwgen: 随机密码生成器","uri":"/zh-cn/pwgen-random-password-generator/"},{"categories":["笔记"],"content":"自从2021年建立我的网站以来,我一直都在用LoveIt这个Hugo主题,没太大变化。这一次,我迁移到了FixIt主题,不仅修复了LoveIt中的一些问题,也带来了更多新功能和优化,顺便也把评论系统从Valine迁移到了Waline。 FixIt https://fixit.lruihao.cn/ 由于FixIt是基于LoveIt的,所以迁移到Fixit是比较容易的。经过一番折腾,除了样式上的变化,我的网站主要的改变如下: 启用Twemoji 评论系统从Valine迁移到Waline,加入了图片和表情包、文章反应等功能 菜单栏加入了Font Awesome图标 加入了Github corner 更换了Mapbox地图样式 加入赞赏功能 加入PWA支持 加入网站已创建时间显示 加入不蒜子访问统计 加入了网站字数统计 标签改为词云显示 加入盘古之白 加入页面水印 加入阅读进度条 加入页面加载进度条 现在FixIt还在持续、积极地更新,我也会继续跟进,不断改进我的网站。 ","date":"2023-02-27","objectID":"/zh-cn/my-website-has-a-new-theme/:0:0","tags":["我的网站","Hugo"],"title":"我的网站换上了新主题","uri":"/zh-cn/my-website-has-a-new-theme/"},{"categories":["笔记"],"content":"macOS自带的终端很好用,但是感觉少了一些东西,所以我就把它强化一下。网上有好多人都推荐使用Oh My Zsh,但是不知道为什么,我在使用Oh My Zsh的时候经常会出现一些问题,所以这一次我没有使用它。 ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:0:0","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"美化 我用了starship来美化终端,它是一个轻量、迅速、跨平台的命令行主题。 starship https://starship.rs/zh-CN/ 在安装starship之前,需要安装Nerd Font字体,比如Fira Code Nerd Font。 可以使用Homebrew安装,然后在终端设置中启用Fira Code Nerd Font字体。 brew tap homebrew/cask-fonts brew install --cask font-fira-code-nerd-font 之后,使用Homebrew来安装starship:brew install starship。在~/.zshrc的最后添加eval \"$(starship init zsh)\",然后执行source ~/.zshrc。重新打开终端,就可以看到效果了。 更多的自定义配置可以参考指南。 ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:1:0","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"扩展 ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:0","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"1. zsh-fast-syntax-highlighting 这个插件可以高亮命令行输入的内容,让你的终端更加美观。 zsh-fast-syntax-highlighting https://github.com/zdharma-continuum/fast-syntax-highlighting brew install zsh-fast-syntax-highlighting 信息 To activate the syntax highlighting, add the following at the end of your .zshrc: source $HOMEBREW_PREFIX/opt/zsh-fast-syntax-highlighting/share/zsh-fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:1","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"2. zsh-autosuggestions 这个插件可以根据你输入的内容,给出自动补全的建议。 zsh-autosuggestions https://github.com/zsh-users/zsh-autosuggestions brew install zsh-autosuggestions 信息 To activate the autosuggestions, add the following at the end of your .zshrc: source $HOMEBREW_PREFIX/share/zsh-autosuggestions/zsh-autosuggestions.zsh You will also need to restart your terminal for this change to take effect. ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:2","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"3. zsh-autocomplete 这个插件同样用于自动补全。 zsh-autocomplete https://github.com/marlonrichert/zsh-autocomplete brew install zsh-autocomplete 信息 Add at or near the top of your .zshrc file (before any calls to compdef): source $HOMEBREW_PREFIX/share/zsh-autocomplete/zsh-autocomplete.plugin.zsh Remove any calls to compinit from your .zshrc file. If you’re using Ubuntu, add to your .zshenv file: skip_global_compinit=1 Then restart your shell. ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:3","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"4. zsh-autopair 这个插件可以自动配对括号、引号等。 zsh-autopair https://github.com/hlissner/zsh-autopair brew install zsh-autopair 信息 To activate autopair, add the following at the end of your .zshrc: source $HOMEBREW_PREFIX/share/zsh-autopair/autopair.zsh You will also need to restart your terminal for this change to take effect. ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:4","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"5. z 这个插件可以快速跳转到你最常访问的目录。 z https://github.com/rupa/z brew install z 信息 For Bash or Zsh, put something like this in your $HOME/.bashrc or $HOME/.zshrc: . $HOMEBREW_PREFIX/etc/profile.d/z.sh 另外,还可以在.zshrc中加入setopt autocd, 这样就可以直接输入目录名来切换到该目录了。 ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:5","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"之前我一直把网站的图片放在七牛云的存储空间里,虽然七牛云还不错,但是https协议下的流量需要收费。所以,我就用jsDelivr和Githubc仓库搭建了一个免费的图床。 ","date":"2023-02-25","objectID":"/zh-cn/build-a-image-hosting-service-with-jsdelivr-and-github-repository/:0:0","tags":["Github","我的网站","命令行工具"],"title":"用jsDelivr和Github仓库搭建图床","uri":"/zh-cn/build-a-image-hosting-service-with-jsdelivr-and-github-repository/"},{"categories":["笔记"],"content":"方法很简单 创建一个公开的Github仓库 上传图片到仓库 得到图片的链接,比如https://cdn.jsdelivr.net/gh/user/repository/image.jpeg, user是你的Github用户名,repository是你的仓库名,image.jpeg是你上传的图片名 而且,这样还可以配合上一篇介绍的ImageMagick,可以写一个简单的脚本,自动压缩图片并上传到Github仓库,然后得到图片的链接。 ","date":"2023-02-25","objectID":"/zh-cn/build-a-image-hosting-service-with-jsdelivr-and-github-repository/:1:0","tags":["Github","我的网站","命令行工具"],"title":"用jsDelivr和Github仓库搭建图床","uri":"/zh-cn/build-a-image-hosting-service-with-jsdelivr-and-github-repository/"},{"categories":["笔记"],"content":"我找到了ImageMagick,它是一个强大的图像处理工具,可以在命令行中使用。不仅可以用于压缩图像,而且可以用于其他很多事情。 ImageMagick https://imagemagick.org/ 可以通过Homebrew安装ImageMagick:brew install imagemagick。 使用ImageMagick可以在命令行中压缩图像。例如,我有一个图像image.png,我想要压缩它,我可以使用以下命令: convert image.png -quality 80% image.png 而且,可以在压缩的同时转换图像的格式。如果我想要压缩图像并转换为JPEG格式,我可以使用以下命令: convert image.png -quality 80% image.jpg ImageMagick还有很多其他的功能,可以参照官方文档慢慢探索。 ","date":"2023-02-24","objectID":"/zh-cn/use-imagemagick-to-compress-the-image-in-the-command-line/:0:0","tags":["命令行工具"],"title":"使用ImageMagick在命令行中压缩图像","uri":"/zh-cn/use-imagemagick-to-compress-the-image-in-the-command-line/"},{"categories":["笔记"],"content":"由于我需要同时使用中文和英文输入法,经常在中英之间切换,有的时候打开了Terminal一输入却是中文。所以我找到了一个叫做 KeyboardHolder 的工具,它可以帮助我们自动切换输入法。 KeyboardHolder https://keyboardholder.leavesc.com/zh-cn/ 也可以直接用 Homebrew 安装:brew install --cask keyboardholder。 它可以设置每个app启动或者从前台切换到后台之后的输入法,比如可以设置Terminal启动之后是英文输入法。 另外,它还可以在鼠标的位置显示输入法切换的提示,这样就不需要转移焦点到菜单栏上检查输入法状态了。 信息 这个功能在macOS 14中已经内置了。 ","date":"2023-02-23","objectID":"/zh-cn/keyboardholder-automatically-switch-input-methods/:0:0","tags":["macOS"],"title":"KeyboardHolder: 自动切换输入法","uri":"/zh-cn/keyboardholder-automatically-switch-input-methods/"},{"categories":["笔记"],"content":"我在通知设置里忽然发现了这个Kerberos,这是什么? 我问了Bing,它说: 引用 您好,这是Bing。Kerberos是一种身份验证系统,可以让您在网络上安全地访问各种服务。Mac中的Kerberos是基于MIT Kerberos实现的,支持Kerberos v5和v4协议、GSSAPI、图形化认证界面和票据缓存。您可以使用命令行或者票据查看器应用来管理您的Kerberos票据。 https://uit.stanford.edu/service/ess/mac/docs/kerberos_macOS https://web.mit.edu/macdev/www/kerberos.html https://support.apple.com/zh-cn/guide/deployment/depe6a1cda64/web https://support.apple.com/en-gb/guide/deployment/depe6a1cda64/web 看来这个Kerberos是包含在macOS中的,它就位于/System/Library/CoreServices/Applications/Ticket Viewer.app,并不是恶意程序。 ","date":"2023-02-22","objectID":"/zh-cn/what-is-kerberos-in-mac/:0:0","tags":["macOS","Bing"],"title":"Mac中的Kerberos是什么?","uri":"/zh-cn/what-is-kerberos-in-mac/"},{"categories":["笔记"],"content":"通过调整Launchpad每一行和每一列的图标的数量,就可以调整图标的大小。 ","date":"2023-02-21","objectID":"/zh-cn/modify-the-icons-size-in-macos-launchpad/:0:0","tags":["macOS"],"title":"修改macOS Launchpad的图标大小","uri":"/zh-cn/modify-the-icons-size-in-macos-launchpad/"},{"categories":["笔记"],"content":"方法 在Terminal中执行以下命令: # 例如设置为8列 defaults write com.apple.dock springboard-columns -int 8 # 例如设置为6行 defaults write com.apple.dock springboard-rows -int 6 # 重置Launchpad defaults write com.apple.dock ResetLaunchPad -bool TRUE # 重启Dock killall Dock 恢复默认设置: defaults write com.apple.dock springboard-rows Default defaults write com.apple.dock springboard-columns Default defaults write com.apple.dock ResetLaunchPad -bool TRUE killall Dock ","date":"2023-02-21","objectID":"/zh-cn/modify-the-icons-size-in-macos-launchpad/:1:0","tags":["macOS"],"title":"修改macOS Launchpad的图标大小","uri":"/zh-cn/modify-the-icons-size-in-macos-launchpad/"},{"categories":["笔记"],"content":"忽然发现我的Mac上竟然有2个Edge Dev,分别是111.0.1660.13和111.0.1660.12,而且这2个都能正常启动。我希望保留最新版本的,把旧版的卸载掉。 ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:0:0","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"方法 ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:1:0","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"1 以Dev版本为例,切换目录到以下位置 cd /Applications/Microsoft\\ Edge\\ Dev.app/Contents/Frameworks/Microsoft\\ Edge\\ Framework.framework/Versions 也可以在访达中按下control + shift + G,输入要前往的位置 ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:1:1","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"2 执行ls -l,可以看到类似的输出 示例 drwxrwxr-x 14 user admin 448 Feb 11 11:32 111.0.1660.12 drwxrwxr-x 14 user admin 448 Feb 17 08:54 111.0.1660.13 lrwxrwxr-x 1 user admin 13 Feb 17 08:54 Current -\u003e 111.0.1660.13 或者在访达中点击Current,确认指向的版本 ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:1:2","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"3 使用rm -rf删除其他旧版本的,或者也可以在访达中删除 ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:1:3","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"4 最后一步,这一步同样也可以在访达中进行 cd ~/Library/Application\\ Support/Microsoft rm -rf EdgeUpdater ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:1:4","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":" 信息 Depay的注册和下载链接:https://depay.depay.one/web-app/register-h5?invitCode=606096\u0026lang=zh-cn,推荐码:606096。 我找到了Depay老板在v2ex上发的主题,本文的内容主要根据这个主题以及我自己的体验。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:0:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"Depay可以做什么 通过Depay可以直接用USDT充值,兑换成美元,然后用VISA和mastercard消费。 可以绑定支付宝、微信支付、美团外卖、拼多多、Paypal(国区、美区、港区)、天猫国际版等 支持Stripe商户、Google Play、Youtube Premium 、Paypal商户、美区App Store和支持非3DS卡的电商网站 支持免KYC开卡,实现完全匿名付款 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:1:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"注册和下载 信息 Depay的注册和下载链接:https://depay.depay.one/web-app/register-h5?invitCode=606096\u0026lang=zh-cn,推荐码:606096。 或者用手机扫描下方海报上的二维码: 安卓直接下载APK安装;iOS可以在非中国区下载,也可以下载测试版。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:2:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"申请虚拟卡 进入Depay App后,点击申请卡,一开始可以选择标准卡和Lite卡,Lite卡不需要KYC。现在一共有5种卡(Lite、标准、高级、白金、黑金),区别主要在于开卡费、月费和充值手续费不同,标准卡的开卡费是0,具体的区别可以看官网。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:3:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"充币、兑换美元、充值和激活 Depay目前支持充USDT(TRC20),一次至少5USDT。充币之后可以将USDT实时兑换成美元。 技巧 激活虚拟卡需要往卡里充值美元,充值会有一定比例的手续费,标准卡的手续费每次最少1美元,所以不要频繁地小额充值。 激活之后就可以查看卡号和CVV安全码了。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:4:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"黑金卡 目前只要邀请20个人开卡,可以找管理员升级黑金卡。黑金卡没有月费,充值手续费也比较低。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:5:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"Depay是否安全? 警告 Depay是一个刚成立的英国小公司,不放心的话最好不要充太多的钱,够用就行。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:6:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"客服 官网:https://depay.one/ 邮箱:support@depay.one Telegram群:https://t.me/depay_visa Twitter:https://twitter.com/Depay_CN ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:7:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"自从2月11日加入了waitlist,今天终于收到邮件,我可以使用新Bing了。 Bug 迫不及待地打开了Edge Dev,进入CHAT,但是我很快就发现无法在输入框里正常地输入所有的字符。我又在Safari上试了试,发现完全正常,所以很可能是Edge Dev存在一些问题。 之后和新Bing进行了几轮对话,感觉它似乎有点缺少对话的积极性,经常会让我换个话题。而且,没几分钟就出现了“This has been lovely, but you’ve reached your daily limit. Chat again tomorrow?”的提示。 不得不说,新Bing一个很有用的功能是它可以从我们正在阅读的网页和文件中获取信息。我测试了一下,我用Edge Dev打开了一个本地的PDF文件,点击Discover按钮进行Chat,新Bing可以总结这个文件中的要点。另外,它也可以在Discover中很方便地生成一些文字。 根据我的体验,我认为新Bing还是很不错的,非常期待之后的正式版本。 ","date":"2023-02-18","objectID":"/zh-cn/you-re-in-welcome-to-the-new-bing/:0:0","tags":["Bing","ChatGPT","浏览器"],"title":"新Bing体验","uri":"/zh-cn/you-re-in-welcome-to-the-new-bing/"},{"categories":["日记"],"content":"美味的奶油水果蛋糕! 在去年两个蛋糕的基础上,这一次主要加入了奶油和水果,还放了几个奥利奥,味道更有层次感了。唯一的缺点是蛋糕胚不够香甜松软,吃着有点像馒头😂。 ","date":"2023-02-15","objectID":"/zh-cn/creamy-fruit-cake-an-upgraded-version/:0:0","tags":["蛋糕"],"title":"奶油水果蛋糕——升级版🍰","uri":"/zh-cn/creamy-fruit-cake-an-upgraded-version/"},{"categories":["笔记"],"content":"Visited Lite是一个自定义已访问链接的颜色的userscript,而Color Links是具有相似功能的浏览器扩展。 前几天微软公司推出了结合GPT技术的新版Bing和Edge浏览器,我看了网上对它们的介绍,感觉真的很不错。而且去年我也第一时间体验了ChatGPT,所以这一次我非常期待新版Bing和Edge,申请加入了waitlist。 问题 在使用Bing的过程中,我忽然发现了一个问题,在Bing的搜索结果中,已访问的链接和未访问的链接都是紫色的,这样就很难区分哪些链接是已访问的,哪些链接是未访问的。而我之前一直使用Google,未访问的链接是蓝色的,访问过的链接是紫色的。我在Bing的设置中并没有找到相关的设置项,不知道问题出在了哪里,所以我想寻找一些userscript或者浏览器扩展来解决这个问题。 ","date":"2023-02-13","objectID":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/:0:0","tags":["Bing","ChatGPT","浏览器","Userscripts","Chrome扩展"],"title":"Visited Lite \u0026 Color Links: 自定义已访问链接的颜色","uri":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/"},{"categories":["笔记"],"content":"Visited Lite 于是我找到了Visited Lite,它可以自定义所有网站的已访问链接的颜色,而不仅仅是Bing的。我在Edge的Tampermonkey扩展中安装了这个userscript,Visited Lite用醒目的颜色标记了所有已访问的链接。不过有的网页可能并不需要这个功能,可以在Tampermonkey扩展中排除它们。 ","date":"2023-02-13","objectID":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/:1:0","tags":["Bing","ChatGPT","浏览器","Userscripts","Chrome扩展"],"title":"Visited Lite \u0026 Color Links: 自定义已访问链接的颜色","uri":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/"},{"categories":["笔记"],"content":"Color Links 之后,我又在chrome web store中找到了Color Links。与Visited Lite的不同主要在于,Color Links需要为每一个网站手动开启标记颜色的功能。 ","date":"2023-02-13","objectID":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/:2:0","tags":["Bing","ChatGPT","浏览器","Userscripts","Chrome扩展"],"title":"Visited Lite \u0026 Color Links: 自定义已访问链接的颜色","uri":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/"},{"categories":["笔记"],"content":" 失败 昨天用了一下texliveonfly宏包,直接出现了env: python: No Such File or Directory。 我试着执行了一下python,结果弹出了一个Xcode Command Line Tools的提示,说要下载一些东西,然后它下载了Python3.9,而我之前已经有了Python3.8🙃。 我试着用ln建立软连接,但是没有用。 成功 我想既然texliveonfly是用Python写的,我可以直接编辑它。于是我找到了/Library/TeX/texbin/texliveonfly,然后将这个文件第一行的#!/usr/bin/env python改成了#!/usr/bin/env python3,这样就解决了。 ","date":"2023-01-23","objectID":"/zh-cn/texliveonfly-env-python-no-such-file-or-directory/:0:0","tags":["LaTeX","Python","macOS"],"title":"texliveonfly, env: python: No Such File or Directory","uri":"/zh-cn/texliveonfly-env-python-no-such-file-or-directory/"},{"categories":["笔记"],"content":"LeetCode 66.Plus One,一道简单的题。主要是想练习一下Java,好长时间没写Java了。 我的思路是从后往前遍历,如果当前位是9,那么就进位,如果不是9,那么就加1,然后返回结果。如果最后一位是9,那么就需要在最前面加一个1,这个时候就需要新建一个数组,然后把原来的数组复制过去。 class Solution { public int[] plusOne(int[] digits) { int end = digits.length - 1; int[] result = new int[end + 1]; boolean carry = false; result[end] = digits[end] + 1; if (result[end] == 10) { result[end] = 0; carry = true; } for (int i = end - 1; i \u003e= 0; --i) { result[i] = digits[i]; if (carry) { result[i] += 1; if (result[i] == 10) { result[i] = 0; carry = true; } else { carry = false; } } } if (carry) { int[] tmp = result; result = new int[end + 2]; result[0] = 1; for (int i = 1; i \u003c end + 2; ++i) { result[i] = tmp[i - 1]; } } return result; } } ","date":"2023-01-22","objectID":"/zh-cn/leetcode-66/:0:0","tags":["算法","Java","LeetCode"],"title":"LeetCode 66","uri":"/zh-cn/leetcode-66/"},{"categories":["笔记"],"content":"今天我爸爸开车送我到一个地方,我下车之后走了3分钟,忽然发现我的手机不见了…… 我赶紧返回原路找我的手机,但是没有找到。最后和路边的交警同志借了手机给我爸爸打了一个电话,才确认我的手机落在了车里。 虽然在Find My中已经设置了离开iPhone时在Apple Watch上发出通知,但是似乎这个功能需要在一个比较远的距离才能生效。 所以我就找到了Phone Buddy: Phone Buddy https://apps.apple.com/us/app/phone-buddy-phone-lost-alert/id1451559391 售价$4.99,我用支付宝购买美区App Store礼品卡的方法充值购买了这个App。 注意 下载Phone Buddy之后,在Apple Watch上开启Lost Phone Alert,当Apple Watch断开了和iPhone之间的蓝牙连接时就会在Apple Watch上发出警报。并且还可以有基于距离的Distance Alert,当Apple Watch和iPhone之间的蓝牙信号强度随着距离的增加衰减到设定的阈值以下时也可以发出警报,这样可以在完全断开蓝牙连接之前多一次警报。同样的,还可以设置在Apple Watch断开连接后在iPhone上发出警报,可以防止丢失或遗忘Apple Watch。 唯一不足的是,这个App会缩短Apple Watch的续航时间,不过比起丢失了iPhone,这个代价是可以接受的。 ","date":"2023-01-18","objectID":"/zh-cn/use-phone-buddy-on-apple-watch-to-prevent-forgotten-iphone/:0:0","tags":["Apple Watch","iPhone"],"title":"在Apple Watch上使用Phone Buddy防止忘带iPhone","uri":"/zh-cn/use-phone-buddy-on-apple-watch-to-prevent-forgotten-iphone/"},{"categories":["日记"],"content":"在国科大的第一个学期很快就过去了,感觉这个学期的经历很丰富。 我于2022年8月17日到达了北京市怀柔区怀北镇,当天下午我先去参观了一下雁栖湖 。雁栖湖是一个很大的湖,湖边有很多树🌳,湖上有很多船🛶,湖边有很多人。湖边的山上还有一条不知道通向哪里的步道,我在这条路上走了很久,感觉很好,可惜由于施工道路中断了🚧,后来我才知道这条路和国科大的观景台是连通的。我在湖边的山上看到了很多鸟🐦,它们在湖上飞在湖边的树上叫。 雁栖湖 在雁栖湖旁边村里的农家乐住了一晚上后,我第二天一早就前往了国科大。虽然那天下了一整天雨🌧️,我的衣服和鞋子都湿透了,但是刚到学校,感觉一切都是那么新鲜,心情还是很不错的🙂。 国科大雁栖湖校区西区荷花池 夕阳 山上的长城 伴随着两天一次的核酸,这个学期就这样开始了。国科大的课程的质量和难度确实要比北方工大的高,感觉收获也要更多一些。除了上课,我也经常在学校里骑着自行车🚲转一转,看看校园的景色。因为学校背靠着大山和雁栖湖,所以学校的生态环境很不错,经常有小动物🐱出没,据说还有野猪🐗和蛇🐍这样的猛兽。 秋天的山 黄叶 阳光下的树 山楂树 雁栖湖北路 不得不说,国科大在山上种了好多果树,秋天丰收之后,我们吃到了不少免费的水果。 梨 10月15日一大早,我们整个宿舍突然被通知要就地隔离了,还给我们每个人送过来丰盛的早餐和一大桶水。还没吃完,又接到通知,隔离结束了,真的是莫名其妙😅。 早餐 到了11月底,学校变得不是那么平静。由于进入冬季奥密克戎疫情又变得严重,当时北京许多高校都开始安排学生返乡。刚开始国科大还是要求学生必须在校完成所有考试,后来在11月29日终于允许学生返乡。一时间各种小道消息在学校传播:有人说学校里有一名核酸检测呈阳性的学生,所有学生都不能回家了,可能都要隔离在宿舍里;有人说出校之后进入北京市区,在火车站等一些地方会有人搜查手机……有点人心惶惶的感觉。 由于我家所在的城市正在封城,不知道什么时候才结束,所以我决定继续留在学校。据说如果校园内出现了疫情,可能食堂就没办法正常做饭了,我就赶紧囤了一些食物。那时好多快递都中断了,京东快递也变得很慢。 在那几天,大部分学生都离开学校回家了,学校安静了下来。在12月5日前后,防疫政策突然出现了重大变化,终于结束了两天一次的核酸检测。但是这时学校开始出现了感染者,我也准备了2盒复方氨酚烷胺胶囊。 12月19日早晨起床后,我感觉我的嗓子变干了还有点疼,还有很多鼻涕,我应该是感染了。当天晚上,我的运动手环一直警告我的心脏🫀跳得很快,在120BMP左右,我静静坐着可以听到心跳的声音。我非常害怕,躺到了床上,浑身发热,心率还是降不下来。伴随着我的心跳声,后来我终于睡着了。第二天早上查看记录,心率慢慢降到了90BMP左右,这很不正常。 我也不知道这是怎么了,自2019年出现新冠病毒以来,我一直不知道新冠病毒会对心脏造成影响。我在网上搜索了一下,也有很多人遇到了和我相同的情况,据说这是病毒性心肌炎。于是我赶紧下单了辅酶$Q_{10}$胶囊。 12月22日,我去领取了一个抗原检测试剂,我确实感染新冠病毒🦠了。 抗原检测呈阳性 过了一周,我的症状逐渐消失了,只是还是有一些咳嗽,而且心率还是偏快。12月27日,我又领取了一份抗原检测试剂,这一次是阴性。 又过了一个多星期,我完成了所有的考试,我的心率还是不正常,我决定去怀柔医院检查一下。我做了心电图、心脏彩超、胸部CT扫描以及多项血液检测,检测结果并没有出现什么异常,医生说我的情况应该是新冠后遗症而不是心肌炎,需要通过一个较长的时间来慢慢恢复。 现在已经是2023了,只希望能够尽快恢复疫情前的生活🙏。 ","date":"2023-01-17","objectID":"/zh-cn/first-semester-at-ucas/:0:0","tags":["转悠","UCAS"],"title":"在国科大的第一个学期","uri":"/zh-cn/first-semester-at-ucas/"},{"categories":["笔记"],"content":"在macOS中,如果在~执行cd documents是可以切换到Documents目录的,但是无法用Tab补全。 解决的方法是在~/.zshrc中添加如下代码: autoload -Uz compinit \u0026\u0026 compinit zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' 重新打开终端就可以见到效果了。 ","date":"2022-12-09","objectID":"/zh-cn/zsh-tab-completion-with-case-insensitivity/:0:0","tags":["命令行工具","macOS"],"title":"zsh: Tab补全大小写不敏感","uri":"/zh-cn/zsh-tab-completion-with-case-insensitivity/"},{"categories":["笔记"],"content":"只要5分钟,把微信公众号变成机器人🤖。 之前注册了一个微信公众号,但是一直闲置着,于是我就想把它变成机器人,发挥一点点作用。 ","date":"2022-11-16","objectID":"/zh-cn/turn-idle-wechat-official-account-into-a-robot/:0:0","tags":["微信"],"title":"把闲置微信公众号变成机器人","uri":"/zh-cn/turn-idle-wechat-official-account-into-a-robot/"},{"categories":["笔记"],"content":"方法 用微信扫码登录微信对话开放平台 在机器人创建页面设置机器人的名称,完成机器人创建 根据需要开启机器人的“预置技能”,比如英语翻译、天气、股票、新闻、笑话等 在“应用绑定”中绑定微信公众号 在“上线发布”中发布 是不是很简单呢? ","date":"2022-11-16","objectID":"/zh-cn/turn-idle-wechat-official-account-into-a-robot/:1:0","tags":["微信"],"title":"把闲置微信公众号变成机器人","uri":"/zh-cn/turn-idle-wechat-official-account-into-a-robot/"},{"categories":["笔记"],"content":" 技巧 由于笔记本电脑使用锂电池,长期连接电源使用会导致电量始终处于一个较高的百分比,这样会缩短电池的寿命。因此,让电量保持在20%至80%之间能够延缓电池的衰减。 对于MacBook,我找到了一个软件可以解决这个问题—— AlDente https://github.com/davidwernhart/AlDente-Charge-Limiter 可以在Github中直接下载,也可以使用Homebrew,brew install --cask aldente。 启动AlDente后这个软件出现在菜单栏中,可以很简单地控制MacBook的最大充电百分比。之后就可以观察到已经连接电源,但是电池没有在充电。 ","date":"2022-10-11","objectID":"/zh-cn/aldente-limit-macbook-maximum-charging-percentage/:0:0","tags":["macOS"],"title":"AlDente:限制MacBook最大充电百分比","uri":"/zh-cn/aldente-limit-macbook-maximum-charging-percentage/"},{"categories":["笔记"],"content":"总有一些软件的图标和macOS的不适应,iconsur可以为它们生成圆角矩形的图标,美化我们的macOS。 iconsur的Github主页: iconsur https://github.com/rikumi/iconsur 可以在Releases中下载。也可以用Homebrew:brew install iconsur,或者是npm:npm install -g iconsur。 iconsur在App Store中为软件寻找最相似的iOS app,把这个软件的图标替换成iOS app的图标。例如: sudo iconsur set /Applications/Microsoft\\ Word.app/ 另外,iconsur也可以为软件在本地生成图标。例如: sudo iconsur set /Applications/Visual\\ Studio\\ Code.app/ -l 其他用法可以参照Github或是执行iconsur help。 ","date":"2022-09-17","objectID":"/zh-cn/iconsur-generate-rounded-rectangle-icons-for-macos-third-party-software/:0:0","tags":["macOS","命令行工具"],"title":"iconsur:为macOS第三方软件生成圆角矩形图标","uri":"/zh-cn/iconsur-generate-rounded-rectangle-icons-for-macos-third-party-software/"},{"categories":["日记"],"content":"经过了半个多月的训练,顺利拿到驾照!感谢每一位教练的耐心指导! 驾照 我还在驾校转了转,驾校建在一个山头上,视野很开阔。 太阳 驾校竟然还养了几只小马。 小马 鹅和鸭子 ","date":"2022-08-13","objectID":"/zh-cn/i-got-my-driving-license/:0:0","tags":["转悠"],"title":"拿到驾照了🚘","uri":"/zh-cn/i-got-my-driving-license/"},{"categories":["项目"],"content":"NCUT-Pot是我的毕业设计,是一个蜜罐。 这个蜜罐支持Telnet和SSH两种协议,模拟Linux系统,将黑客的数据存储在SQL数据库中。此外,它还通过短信和电子邮件向用户发送警报。用户可以自定义蜜罐的命令和目录。 信息 关于NCUT-Pot的更多细节请访问https://github.com/kayak4665664/FF-Pot(现已改名为FF-Pot)。 ","date":"2022-07-14","objectID":"/zh-cn/ncut-pot/:0:0","tags":["毕业设计","NCUT","Github"],"title":"NCUT-Pot","uri":"/zh-cn/ncut-pot/"},{"categories":["日记"],"content":"自从毕设结束了,我就天天盼着录取通知书,终于等到了! 录取通知书 哈哈,校园卡也到了。虽然我非常期待国科大的新学期,不过8月18日就得去报到,我又要去驾校学车,感觉我的假期还没有开始就要结束了🥹 学位证 毕业证 我的毕业证和学位证也回来了,怀念在北方工大那些快乐的日子。 ","date":"2022-07-13","objectID":"/zh-cn/august-18-a-new-beginning/:0:0","tags":["NCUT","UCAS"],"title":"8月18日,新的开始","uri":"/zh-cn/august-18-a-new-beginning/"},{"categories":["日记"],"content":"毕业设计终于要进入尾声了,6月9日下午最终答辩! 现在我已经完成了毕业设计的大部分工作,所以这两个星期过得还是比较轻松的。但是我现在被隔离了,每天只能呆在屋子里🙃,今天是第4天了。 5月27日中午,我和往常一样去食堂吃了午餐,刚回到宿舍,突然就收到了学校要求毕业生尽快离校的通知。我马上就意识到,这将是我在北方工业大学最后的几天了。 离校通知 我冷静了一下,立刻开始计划离校前必须做的事情。首先要考虑的就是我的行李,还好学校承诺是可以免费邮寄的,不然邮寄那么多东西的费用我是有点负担不起的。然而,我并没有用来打包的纸箱子。我问了问辅导员,他只说晚些时候会发放。我感觉他的回答太模糊了,我决定自己先去买几个纸箱子。我去学校快递点找到了那里的老板,他告诉我,我们学院之前找他拿了一百多个纸箱子。我估计了一下,一个学生应该只能领取到1个纸箱子。所以,我和老板买了4个大纸箱子,花了45元。 有了纸箱子,我就回宿舍打包行李了。同时,我还得和我家所在的社区报备。我和社区的工作人员联系了一下,她告诉我,我将会被集中隔离7天,再居家隔离7天。我感觉这并不合理,我在学校期间接受了几十次核酸检测,从来都是阴性的,而且学校一直是封闭的,校外的人进不来,校内的人出不去,我认为我不应该被集中隔离7天。而且据我所知,有一些地方对于从北京返回的学生也是不需要集中隔离的。我向她解释了一下,但是没有用。好在集中隔离是免费的,否则又得花不少钱了。那几天,我看到有新闻说有些大学生返乡后被集中隔离,一天要500元。 打包完行李后,我感觉有点热,我发现我的头发有点长了。一想到我马上还要隔离半个月,我就去理发店把头发剪短了。 晚上,辅导员终于通知可以去领纸箱了,我领到1个纸箱和1个麻袋。再加上我买的4个大纸箱,刚刚好。 5月28日上午,我去超市买了一只记号笔,我得在箱子上标记我的邮寄地址。我走进宿舍楼,和我比较熟的一个宿管阿姨告诉我,现在可以开始到快递点邮寄行李了,让我赶紧去吧。考虑到我要把4个纸箱和1个麻袋从宿舍搬到快递点,单靠两只手是不太容易的,所以我到快递点和老板借了一个平板车。我回到宿舍把这5件东西都标记了我的信息,全放到平板车上去了,一下子都运到了快递点。 由于学校要求毕业生离校的通知比较仓促,快递点老板坦白说他们也不知道怎么处理这么多人的行李,而整个快递点只有2个人。当我推着平板车过去时,我看到快递点外面已经堆了不少箱子了。我有点担心这么多箱子最后会被搞混,所以我请求老板先给我的行李贴上快递单,这样我也方便查快递。等我处理好行李,已经12点多了,到了食堂,煮了一大盘饺子。不得不说,食堂的饺子真的太好吃了,里面肉是真的多。 饺子 晚上,我查到我的快递已经发出去了,感觉效率还是很高的。 5月29日下午,快递点老板突然给我打电话。我担心的事情发生了,老板说他们打错了快递单,把别人的一箱行李邮寄到我的地址去了,我的一箱还在他那里😱。我赶紧又跑到了快递点,我的一个箱子果然还躺在货架子上。 5月30日,这一天没有什么特别的事情,都已经处理好了。 5月31日,闹钟还没响我就已经醒了,这是我在学校的最后一天。起床吃早餐。之后,开始打包铺盖,收拾行李,我得带足生活用品,晚上就要开始隔离了。我把铺盖打包进了学院发的小纸箱里,刚好能装进去。我抱着箱子到了快递点,门开着却没有人。等了半小时老板终于来了。 中午,到食堂吃午餐,这是我在学校的最后一顿饭。 我回到了宿舍,躺在了床垫上。这个床垫太大不能邮寄,就留在这里了。 下午快3点时,我整理好了行李箱,关上了宿舍的窗户,拉下电闸,最后看了宿舍一眼,锁上了门。我下楼找到宿管阿姨,退了钥匙。 就这样,我就离开了学校,可能永远不会回去了。 NCUT 上面这张照片是31日的。30日下午我就看见有人在摆弄这几个牌子,不过当时上面还是2021😂。 出了学校,我坐上了地铁去火车站。 晚上8点,火车到站了。很快,开始核查旅客的出发地,我从北京出发,需要被送到隔离酒店。 我填写了一个文件后,我的身份证就被扣押了。他们说会还给我的。我不知道他们是什么人,我认为他们这种行为是违反《中华人民共和国居民身份证法》的。之后就是漫长的等待,活生生站了2个多小时,没有人来处理。总的来说,这是一段不愉快的经历。 晚上10点多,终于有人来接应了,终于把身份证还给我了。之后进行了一次核酸检测。 一行人坐上了车,11点左右终于到达了隔离酒店。又是漫长的等待,我已经很困了,浑身疲劳。再一次核酸检测后,我终于进入了房间。整理好之后,已经将近6月1日的1点了。 有一说一,隔离酒店的环境还是不错的,吃饭喝水也能保证,这4天来我过得还可以。 还有3天集中隔离就要结束了,开始7天的居家隔离,其中6月9日我将进行毕设的答辩。 时间过得太快了,我在3月15日回到学校时,北京还在下雪。一转眼,我突然又回家了。我的4年大学生活马上也要结束了,我会永远记得在北方工业大学的4年。 ","date":"2022-06-04","objectID":"/zh-cn/next-week-i-will-have-my-graduation-project-defense/:0:0","tags":["毕业设计","NCUT"],"title":"下周毕设答辩","uri":"/zh-cn/next-week-i-will-have-my-graduation-project-defense/"},{"categories":["笔记"],"content":"今天知道了一种直接用支付宝购买美区App Store礼品卡的方法,以后不用再去淘宝和闲鱼上买了! ","date":"2022-05-21","objectID":"/zh-cn/buy-us-app-store-gift-cards-with-alipay/:0:0","tags":["境外支付"],"title":"用支付宝购买美区App Store礼品卡","uri":"/zh-cn/buy-us-app-store-gift-cards-with-alipay/"},{"categories":["笔记"],"content":"方法 打开支付宝 首页左上角切换定位到旧金山 搜索“出境”,在搜索结果中选择“出境” 选择“折扣礼卡” 滑到页面最下方,点击“更多大牌折扣礼卡” 搜索“App Store” 输入正确的邮箱账号 输入要购买的数值,至少$2,“Purchase card” ","date":"2022-05-21","objectID":"/zh-cn/buy-us-app-store-gift-cards-with-alipay/:1:0","tags":["境外支付"],"title":"用支付宝购买美区App Store礼品卡","uri":"/zh-cn/buy-us-app-store-gift-cards-with-alipay/"},{"categories":["日记"],"content":"全世界无产者,联合起来! 共同捍卫劳动者的权利,为一个更公平更美好的世界而奋斗。 ","date":"2022-04-30","objectID":"/zh-cn/international-workers-day/:0:0","tags":[],"title":"庆祝五一国际劳动节","uri":"/zh-cn/international-workers-day/"},{"categories":["日记"],"content":"今天通过腾讯会议参加了开题答辩。 原计划下午一点半开始,不知道为啥等到了两点😶。今天下午这一场一共有24名学生,3位评委老师。我排在第12号,等到了四点终于轮到我了。总体还是比较顺利的,不过有一位老师正好是研究计算机网络的,而我的课题涉及到了不少网络的东西,被抓着问了几个问题。 答辩之后,老师没说可以退出,正好继续待在会议里面看别人答辩。一位保研到计算所的未透露名字的同学,他的毕设是和华为公司合作的,他说他的毕设成果要打败他导师之前的工作,他立志也要投一篇顶会👍。 这样优秀的同学激励我去做好我自己的工作,继续努力吧👍。 ","date":"2022-03-09","objectID":"/zh-cn/todays-thesis-proposal/:0:0","tags":["毕业设计","NCUT"],"title":"今日开题答辩","uri":"/zh-cn/todays-thesis-proposal/"},{"categories":["日记"],"content":"感觉面粉放少了,没上次的好吃,还不错吧。 ","date":"2022-03-04","objectID":"/zh-cn/made-a-cake-again/:0:0","tags":["蛋糕"],"title":"又做了个蛋糕🍰","uri":"/zh-cn/made-a-cake-again/"},{"categories":["笔记"],"content":"https://cdn.jsdelivr.net/gh/kayak4665664/My-images 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例: 输入:height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1] 输出:6 解释:上面是由数组 [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 刚开始想用stack做,不过感觉不太好。然后我就直接上下一层一层算,但是Time Limit Exceeded了: class Solution { public: int trap(vector\u003cint\u003e\u0026 height) { int ans = 0; unordered_map\u003cint, vector\u003cint\u003e\u003e index; for (int i = 0; i \u003c height.size(); ++i) { for (int j = 1; j \u003c= height[i]; ++j) index[j].push_back(i); } for (auto p : index) { auto v = p.second; for (int i = 1; i \u003c v.size(); ++i) ans += v[i] - v[i - 1] - 1; } return ans; } }; 看了看参考答案,主要思路是左右围起来并且求水平面高度: class Solution { public: int trap(vector\u003cint\u003e\u0026 height) { int ans = 0, l = 0, r = height.size() - 1, level = 0; while (l \u003c r) { int lower = (height[l] \u003e height[r] ? height[r--] : height[l++]); level = max(lower, level); ans += level - lower; } return ans; } }; 这道题解法应该挺多的。 ","date":"2022-02-18","objectID":"/zh-cn/leetcode-42/:0:0","tags":["算法","C++","LeetCode"],"title":"LeetCode 42","uri":"/zh-cn/leetcode-42/"},{"categories":["日记"],"content":"前几天去平遥古城转了转,整个古城基本上保存了明清时期的原貌。站在城墙上眺望,非常壮观。小吃很多,我最喜欢平遥牛肉和碗托! ","date":"2022-02-13","objectID":"/zh-cn/pingyao-ancient-city/:0:0","tags":["转悠"],"title":"平遥古城","uri":"/zh-cn/pingyao-ancient-city/"},{"categories":["笔记"],"content":"一个双向链表的C++模版。 #include \u003ciostream\u003e using namespace std; struct ListNode { int val; ListNode *next, *prior; ListNode() : val(0), next(nullptr), prior(nullptr) {} ListNode(int v) : val(v), next(nullptr), prior(nullptr) {} ListNode(int v, ListNode *next, ListNode *prior) : val(v), next(next), prior(prior) {} }; ListNode *insert(ListNode *p, int val) { ListNode *n = new ListNode; n-\u003eval = val; n-\u003enext = p-\u003enext; p-\u003enext = n; n-\u003eprior = p; if (n-\u003enext != nullptr) n-\u003enext-\u003eprior = n; return n; } void erase(ListNode *p) { p-\u003eprior-\u003enext = p-\u003enext; if (p-\u003enext != nullptr) p-\u003enext-\u003eprior = p-\u003eprior; delete p; } void print(ListNode *p) { if (p != nullptr) { cout \u003c\u003c p-\u003eval; p = p-\u003enext; } while (p != nullptr) { cout \u003c\u003c \" -\u003e \" \u003c\u003c p-\u003eval; p = p-\u003enext; } cout \u003c\u003c endl; } int main() { ListNode *front = new ListNode(1); ListNode *n = insert(insert(insert(front, 2), 4)-\u003eprior, 3); print(front); // 1 -\u003e 2 -\u003e 3 -\u003e 4 erase(n); print(front); // 1 -\u003e 2 -\u003e 4 return 0; } LeetCode 21. Merge Two Sorted Lists class Solution { public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { if (list1 == nullptr \u0026\u0026 list2 == nullptr) return nullptr; else if (list1 == nullptr) return list2; else if (list2 == nullptr) return list1; else { ListNode *front, *p, *p1, *p2; if (list1-\u003eval \u003c= list2-\u003eval) { front = list1; p1 = list1-\u003enext; p2 = list2; } else { front = list2; p1 = list1; p2 = list2-\u003enext; } p = front; while (p1 != nullptr \u0026\u0026 p2 != nullptr) { if (p1-\u003eval \u003c= p2-\u003eval) { p-\u003enext = p1; p1 = p1-\u003enext; } else { p-\u003enext = p2; p2 = p2-\u003enext; } p = p-\u003enext; } if (p1 == nullptr) p-\u003enext = p2; else p-\u003enext = p1; return front; } } }; LeetCode 23. Merge k Sorted Lists 直接用这个方法导致Time Limit Exceeded, class Solution { public: ListNode *mergeKLists(vector\u003cListNode *\u003e \u0026lists) { int flag = 0, min = 0x3f3f3f; ListNode *front, *p, *p1; unordered_map\u003cListNode *, ListNode *\u003e ptr; vector\u003cListNode *\u003e ps; for (auto list : lists) { if (list != nullptr) { flag = 1; ptr[list] = list; if (list-\u003eval \u003c min) { min = list-\u003eval; front = list; } } } if (!lists.size() || !flag) return nullptr; else { ptr[front] = ptr[front]-\u003enext; p = front; while (true) { flag = 0, min = 0x3f3f3f; for (auto list : lists) { if (ptr[list] != nullptr) { flag = 1; if (ptr[list]-\u003eval \u003c min) { min = ptr[list]-\u003eval; p1 = list; } } } if (!flag) break; p-\u003enext = ptr[p1]; p = p-\u003enext; ptr[p1] = ptr[p1]-\u003enext; } return front; } } }; 用优先队列就可以通过了。 class Solution { public: ListNode *mergeKLists(vector\u003cListNode *\u003e \u0026lists) { ListNode *front, *p; auto cmp = [](ListNode *a, ListNode *b) { return a-\u003eval \u003e= b-\u003eval; }; // ptr.top() is minimal. priority_queue\u003cListNode *, vector\u003cListNode *\u003e, decltype(cmp)\u003e ptr(cmp); for (auto list : lists) { if (list != nullptr) ptr.push(list); } if (!lists.size() || ptr.empty()) return nullptr; else { front = ptr.top(); ptr.pop(); if (front-\u003enext != nullptr) ptr.push(front-\u003enext); p = front; while (!ptr.empty()) { p-\u003enext = ptr.top(); ptr.pop(); p = p-\u003enext; if (p-\u003enext != nullptr) ptr.push(p-\u003enext); } return front; } } }; ","date":"2022-01-31","objectID":"/zh-cn/linked-list/:0:0","tags":["链表","优先队列","数据结构","C++","LeetCode"],"title":"链表","uri":"/zh-cn/linked-list/"},{"categories":["笔记"],"content":"这是二分查找算法的一个C++模版,以及C++标准模版库\u003calgorithm\u003e头文件中二分查找函数std::lower_bound和std::upper_bound的简单应用。 #include \u003calgorithm\u003e #include \u003ciostream\u003e using namespace std; int nums[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int binary_search(int left, int right, int key) { int pos = -1, mid; while (left \u003c= right) { mid = left + (right - left) / 2; if (key \u003e nums[mid]) left = mid + 1; else if (key \u003c nums[mid]) right = mid - 1; else { pos = mid; break; } } return pos; } int main() { cout \u003c\u003c binary_search(0, 9, 3) \u003c\u003c endl; // 2 cout \u003c\u003c lower_bound(nums, nums + 10, 3) - nums \u003c\u003c endl; // 2, \u003e= 3 cout \u003c\u003c upper_bound(nums, nums + 10, 3) - nums \u003c\u003c endl; // 3, \u003e 3 return 0; } 用这个模版做了一道LeetCode的34. Find First and Last Position of Element in Sorted Array。 class Solution { public: vector\u003cint\u003e searchRange(vector\u003cint\u003e\u0026 nums, int target) { if (!nums.size()) return vector\u003cint\u003e{-1, -1}; else { int pos = binary_search(nums, 0, nums.size() - 1, target); if (pos == -1) return vector\u003cint\u003e{-1, -1}; else { int left = pos - 1, right = pos + 1, size = nums.size(); while (left \u003e= 0 \u0026\u0026 nums[left] == target) --left; while (right \u003c size \u0026\u0026 nums[right] == target) ++right; return vector\u003cint\u003e{left + 1, right - 1}; } } } int binary_search(vector\u003cint\u003e nums, int left, int right, int key) { int pos = -1, mid; while (left \u003c= right) { mid = left + (right - left) / 2; if (key \u003e nums[mid]) left = mid + 1; else if (key \u003c nums[mid]) right = mid - 1; else { pos = mid; break; } } return pos; } }; ","date":"2022-01-29","objectID":"/zh-cn/binary-search/:0:0","tags":["查找","算法","C++","LeetCode"],"title":"二分查找","uri":"/zh-cn/binary-search/"},{"categories":["日记"],"content":"真好吃! ","date":"2022-01-18","objectID":"/zh-cn/made-a-cake/:0:0","tags":["蛋糕"],"title":"做了个蛋糕🍰","uri":"/zh-cn/made-a-cake/"},{"categories":["日记"],"content":"今天出来走了走,拍了一些照片。蓝蓝的天,感觉真不错! 人民英雄纪念碑(北面) 人民英雄纪念碑(南面) 毛主席纪念堂 人民大会堂 新华门 ","date":"2021-12-27","objectID":"/zh-cn/i-went-to-tiananmen-today/:0:0","tags":["转悠"],"title":"今天到天安门走了走","uri":"/zh-cn/i-went-to-tiananmen-today/"},{"categories":["笔记"],"content":"目前本站已经成型,进入日常维护阶段,现在来回顾一下它是如何建立的。网上已经有各种教程,而本文主要是我自己的经历,不会涉及那些重复的细节。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:0:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"开始 上上周看到有人用Github作免费网盘,我以前还见过有人专门建了repository来记笔记、写博客,我忽然也想有个写点东西记录自己的地方。我就查了一下如何用Github写博客,我才知道了Github Pages。简单来说它可以免费自动托管静态网页,用它做一个自己的博客是绰绰有余的。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:1:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"准备 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:2:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"域名 Github Pages是免费的,不过它的网址都长username.github.io这样,感觉不够个性化。好在它是支持自定义域名的,我决定买一个。网站还没有建起来,但我还是先买了。我听说国内买域名需要实名审核,并且审核需要好几天。我一边等待审核通过,一边建网站,这样更省时间。最后我买了kayak4665664.com。 技巧 有的域名首年注册时看起来便宜,但以后续费比.com域名还要贵。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:2:1","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"username.github.io 新建了一个repository,进行Pages设置。Github Pages使用Jekyll将纯文本转化为静态网站,所以在设置过程中它会让你选择你的Jekyll主题。我还认真地比较了一下那几个主题,选了我觉得最好看的一个。其实后面很快我就发现,这些主题过于简单,不满足我的需求。之后用git克隆repository到了本地。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:2:2","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"设计 我看了一些其他人的网站,初步确定我的网站要有评论、访问统计、站内搜索这几个功能。另外还要加入百度和谷歌分析,并且让它们收录我的网站。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:2:3","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"工具 除了Jekyll,还有很多将纯文本转化为静态网站和博客的工具,比如我现在用的Hugo。由于Github Pages默认使用Jekyll,我就选择了Jekyll。 Jekyll基于Ruby,可以用gem来安装。我使用的macOS自带一个Ruby,我就直接执行gem install jekyll bundler开始安装Jekyll、Bundler以及它们的依赖。安装一半,出现fatal error: 'ruby/config.h' file not found。谷歌了一下有人说是自带的Ruby版本太低,还有人说是Xcode CommandLineTools的问题。我直接用Homebrew安装了一个新的Ruby。安装之后设置了终端的环境变量,重新执行gem install jekyll bundler,这次安装好了。 警告 我还查了一下怎么清理之前gem install jekyll bundler时的缓存和已安装的包,结果没有找到。我只好手动卸载了那些已安装的包、删除了缓存所在的目录,感觉根本没清理干净。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:2:4","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"Jekyll ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:3:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"上手 在工作目录执行bundle exec jekyll serve,出现cannot load such file -- webrick (LoadError)。谷歌了一下,用bundle add webrick解决。 在本地预览了一下感觉没有问题,准备push到Github上用手机测试。但是出现了问题,push不上去。谷歌了一下没找到,百度了一下发现可能是proxy的问题,取消git设置的代理后解决。 用手机看了一下,网页是自动适配移动端的。这时候发现这个主题太简陋了,甚至没有分页的功能。刚开始我还准备自己实现出来,但又想想那么多功能都得一个个实现,工作量巨大,我还是找一个功能比较完整的主题吧。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:3:1","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"主题 网上有不少Jekyll主题,我最后下载了YAT。它支持不少功能,可以用Disqus和Gitment来评论。 下载之后,想要执行bundle exec jekyll serve预览一下,报错Could not find gem 'jekyll-spaceship (~\u003e 0.2)'。我通过在gem安装jekyll-spaceship时设置版本为0.2来解决。在这里我还发现安装过程卡住了,但没有报错。用Activity Monitor看到Ruby的Rcvd Bytes是一直缓慢增加的,应该是国内网络的问题。谷歌了一下,在Ruby China找到了换源的方法,换源之后成功安装。 再次执行bundle exec jekyll serve,这次可以预览新主题了。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:3:2","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"个性化 根据自己的需求来对主题进行个性化修改,如标题、图片等。我本来想用Gitment,但我发现它不能登录Github账号,看了一下它的Issues应该是停止服务了。所以只能用Disqus,我注册了Disqus账号,开启了评论功能。此外我还用了不蒜子进行网站访问量统计,只需两行代码。 之后我开始增加一些内容。在预览内容的过程中渐渐发现了一些问题,这个主题它的字体偏小,不论在浅色还是深色模式下文字与背景的对比较低,总之我感觉读起来费眼睛。然而无法在配置文件中对字体进行设置,我只能直接去挨个修改.scss文件,比较麻烦。而它的翻译功能,调用了谷歌的网页翻译接口,在国内网络下几乎无法使用,导致网页变得卡顿,我直接将源代码中翻译相关的部分删除了。除此之外,Disqus在国内网络下无法登录账号,测试了一下只能使用访客匿名评论,这也是一个缺点。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:3:3","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"放弃 个性化之后,我感觉没有问题了。这时忽然想到YAT主题还支持PlantUML、Mermaid、Mathjax、Vedio、Audio等,我应该再测试一下。我直接用作者的markdown文件进行测试,结果发现这些东西都没有正常显示出来。 我还以为是我把源代码改坏了,我直接克隆了一份作者的repository。经测试发现同样不行,看来不是我修改代码的问题。但是问题在哪我也一直没有找到,考虑到这个主题还存在其他的缺点,我选择放弃它。 我又开始找主题,这一次更加仔细。最后找到了LoveIt主题,也就是我现在用的。 这是一个基于Hugo的主题,所以Ruby就没用了,我把它卸载了。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:3:4","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"Hugo ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:4:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"上手 先用Homebrew安装Hugo,LoveIt文档中推荐安装extended版本的Hugo,而Homebrew安装的Hugo就是extended版本的。 Hugo的目录结构和Jekyll的还是不太一样,用了一些时间才熟悉了。LoveIt的配置项非常多,也是需要先看一看文档的。 大概配置了一下,执行hugo serve -e production --disableFastRender进行预览。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:4:1","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"个性化 之后就是个性化地设置,还有: 注册LeanCloud以及Valine用于评论和访问统计 利用https://realfavicongenerator.net生成网站图标 注册Gravartar头像 注册Algolia用于站内搜索 使用node.js执行npm install atomic-algolia安装atomic-algolia,用于自动化上传索引文件至Algolia 注册Mapbox 在这中间我还发现一个问题,本地预览的时候不能显示自定义的404模版,谷歌了一下发现: 信息 hugo server will not automatically load your custom 404.html file, but you can test the appearance of your custom “not found” page by navigating your browser to /404.html. ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:4:2","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"扩展 网站差不多建起来了。执行hugo,就会出现/public目录,把/public和自己的repository同步,就可以把网页托管到Github Pages。之后再用atomic-algolia上传生成的索引文件至Algolia。经过这两个步骤就完成了一次网站的部署。 另外,我又建了一个私有的repository,用于同步/public之外的源代码,所以每次部署都需要多同步一次。为了自动化这三个过程,我写了一个Shell脚本,一步到位。 这时候,我的域名终于通过了实名审核。我开始进行一些扩展: 在Github上设置CNAME 将repository导入Vercel,这样每次更新repository,都会自动部署到Vercel。据说百度不会收录Github Pages托管的网站,而部署到Vercel之后可以被收录 在Vercel中设置自定义域名 加入百度统计和谷歌Analytics 向百度搜索资源平台和谷歌Search Console提交sitemap,在必应Webmaster Tools中直接导入谷歌Search Console中已经提交的sitemap ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:4:3","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"最后 未来我还打算加入一点谷歌广告,这也是大部分网站都有的功能。 总的来说,这次的收获还是很多的! ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:5:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["日记"],"content":"谷歌收录了我的网站!目前我也向百度和必应提交了sitemap,坐等收录。 现在我的网站已经逐渐走上了正轨,所以我准备下周写一篇文章来回顾一下我的网站是如何建立的。 ","date":"2021-12-19","objectID":"/zh-cn/google-has-indexed-my-website/:0:0","tags":["我的网站"],"title":"谷歌收录了我的网站","uri":"/zh-cn/google-has-indexed-my-website/"},{"categories":["日记"],"content":"这周学校开始了毕设工作,现在我已经确定了题目,正式开始了我的毕业设计。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:0:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":["日记"],"content":"选题 题目之前已经有了,组里的一个导师给我定的一个物联网安全方向的题目。我觉得这个题目还挺合适的,一方面可以了解一些物联网的知识,另一方面也完成了我的毕设,算是一箭双雕。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:1:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":["日记"],"content":"开会 开完毕设动员会之后,和我的指导老师见了面。他给我们几个开了个小会,讲了一堆东西。其实也没什么,主要就是建了一个企业微信群,我的指导老师成了“寨主”。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:2:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":["日记"],"content":"上报 虽说题目已经有了,但我还是得好好考虑一下,毕竟毕设不是那么随便的。我的指导老师在群里也发了一些参考的题目,都是比较经典的。而那个题目对我来说还是很新颖的,我之前从没做过这个方向。综合来看,我还是更偏向这个物联网的题目,而且组里的导师也非常希望我去做这个题目。所以我向我的指导老师上报了。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:3:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":["日记"],"content":"讨论 指导老师如是说: 题目写的不完整, 写一个完整的。 好的,我把我的题目描述得更加完整,等着听老师的意见。消息已读了,但是一直没有回复。真的是莫名其妙啊,不会是他忘记了吧?第二天我发消息再问问他的意见,突然收到了一条59秒的语音。 指导老师如是说: …你那根本不叫题目,你那叫口语,那哪是题目?而且你这个所做的东西吗,说心里话这个搜索性太大了,没看到具体内容我都不好说…那么你这个所做的吧,可大可小。这个对你的要求,我不知道…那么小吗,就是非常简单的就不是太难;如果是要大吗,那是有一定难度的好不好?那么你写那么多,你那哪是一个题目?你那是口语!你口语叫我怎么给你定?你要定下来,难道叫我给你定个口语能做题目吗?你自己都写不出来一个题目叫我来定?给你定一个口语这合适吗?好吧?你自己想好了以后完了再讨论还有基础,否则话没话可说! 我直接就懵了,他说我的不叫题目。先不论到底是不是题目,他觉得我的不算题目,他有意见、有问题,他可以直接告诉我的吧?我可以去修改和完善啊,一直不回复我能知道他是怎么想的吗? 我长这么大第一次遇见这种情况,我不知道这对我来说意味着什么。我把这个事情也告诉了组里的导师。 她回复的第一句话是: 为啥? 我也把我指导老师的语音给她看,她帮我确定了一个标题。这里我忽然发现可能有一个误解,我指导老师说的“题目”到底是指“标题”还是“课题”?我查阅了《现代汉语规范词典》,“题目”确实是有多个意思的。看他说我的“题目”是“口语”,看起来他说的题目指的是“标题”了。 如果是这样的话,他为啥一开始不说清楚他说的是一个标题呢? 好吧,他说我自己都写不出来一个题目,没有讨论的基础。那我就把定好的题目发给了他,希望能有进一步的讨论。但是,他还是一直没话可说。 这时我感觉,什么“标题”还是“课题”可能并不是关键。我想到他在群里说“从这一届开始,教务处准备启用毕业设计管理系统”,“都通过系统进行”,“留有痕迹”。“再者”,“进行工程教育认证”,“各位指导老师严把题目质量关”。我感觉到他应该是对这个题目的专业水平和工作量不太好把关。毕竟他不是研究物联网的,往届应该也没有类似的题目,他一直不好下结论,所以一直没话可说。 我把我的想法告诉了组里的导师,她建议我给他讲得再详细一些。因此,我写了一个有点像开题报告的文档,写清楚了具体的要做的每一项任务,也初步计划了每一项任务的时间分配。我发给了我的指导老师,并且向他提出如果有问题希望他可以直接说出他的意见。 终于,我的指导老师开始和我讨论了。 指导老师如是说: 你提交吧。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:4:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":["日记"],"content":"最后 不管怎样,题目定下来了,现在开始做毕设了。 信息 毕设已经完成了,请看这一篇博客:NCUT-Pot,项目也已经开源。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:5:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":null,"content":"kayak4665664 嘿,很高兴认识你,你找到了我的博客! 我是kayak4665664,中国科学院大学学生。 ","date":"2021-12-13","objectID":"/zh-cn/about/:1:0","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"帮助 ","date":"2021-12-13","objectID":"/zh-cn/about/:2:0","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"1. 如何订阅博客? 首先你需要安装RSS阅读器,然后点击,将RSS链接导入到你的阅读器中。 如果你不想安装RSS阅读器,也可以: 添加书签 添加到主屏幕 ","date":"2021-12-13","objectID":"/zh-cn/about/:2:1","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"2. 如何在本站评论? 输入评论,点击提交即可。你还可以输入你的昵称、邮箱和网址。如果你输入了Gravtar邮箱,你的头像可以显示出来。 ","date":"2021-12-13","objectID":"/zh-cn/about/:2:2","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"许可协议 本站所有内容采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 ","date":"2021-12-13","objectID":"/zh-cn/about/:3:0","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"您可以自由地: 共享 — 在任何媒介以任何形式复制、发行本作品 演绎 — 修改、转换或以本作品为基础进行创作 只要你遵守许可协议条款,许可人就无法收回你的这些权利。 ","date":"2021-12-13","objectID":"/zh-cn/about/:3:1","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"惟须遵守下列条件: 署名 — 您必须给出适当的署名,提供指向本许可协议的链接,同时标明是否(对原始作品)作了修改。您可以用任何合理的方式来署名,但是不得以任何方式暗示许可人为您或您的使用背书。 非商业性使用 — 您不得将本作品用于商业目的。 相同方式共享 — 如果您再混合、转换或者基于本作品进行创作,您必须基于与原先许可协议相同的许可协议分发您贡献的作品。 没有附加限制 — 您不得适用法律术语或者技术措施从而限制其他人做许可协议允许的事情。 ","date":"2021-12-13","objectID":"/zh-cn/about/:3:2","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"声明: 您不必因为公共领域的作品要素而遵守许可协议,或者您的使用被可适用的例外或限制所允许。 不提供担保。许可协议可能不会给与您意图使用的所必须的所有许可。例如,其他权利比如形象权、隐私权或人格权可能限制您如何使用作品。 ","date":"2021-12-13","objectID":"/zh-cn/about/:3:3","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":["日记"],"content":"世界你好! ","date":"2021-12-12","objectID":"/zh-cn/hello-world/:1:0","tags":["我的网站"],"title":"世界你好!","uri":"/zh-cn/hello-world/"},{"categories":null,"content":"Offline - kayak4665664","date":"0001-01-01","objectID":"/zh-cn/offline/","tags":null,"title":"","uri":"/zh-cn/offline/"}]
\ No newline at end of file
+[{"categories":["项目"],"content":" Node-Depend-View https://github.com/kayak4665664/Node-Depend-View 我在学习前端和Node.js开发的过程中完成了这个小项目,它可以将一个项目的依赖关系以图形的形式展示出来,我还将它发布到了npm上,具体还请看上面的链接。感觉用TypeScript做全栈开发还是很有意思的,希望在新的一年里可以先找到一份实习工作!好了,不多说了,加油!💪 ","date":"2024-01-04","objectID":"/zh-cn/node-depend-view/:0:0","tags":["TypeScript","Node.js","命令行工具","前端","全栈","算法","Github"],"title":"Node-Depend-View","uri":"/zh-cn/node-depend-view/"},{"categories":["笔记"],"content":"LeetCode Linked List ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:0","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"707. Design Linked List class MyLinkedList { val: number | undefined; next: MyLinkedList | undefined; prior: MyLinkedList | undefined; constructor () { this.val = undefined; this.next = undefined; this.prior = undefined; } get ( index: number ): number { if ( index == 0 ) return this.val != undefined ? this.val : -1; else if ( !this.next ) return -1; else { let ptr = this.next, i = 1; while ( i \u003c index \u0026\u0026 ptr.next ) { ptr = ptr.next; ++i; } if ( i == index ) return ptr.val != undefined ? ptr.val : -1; else return -1; } } addAtHead ( val: number ): void { if ( this.val == undefined ) this.val = val; else { const next = new MyLinkedList(); next.val = this.val; next.next = this.next; if ( next.next ) next.next.prior = next; next.prior = this; this.val = val; this.next = next; this.prior = undefined; } } addAtTail ( val: number ): void { if ( this.val == undefined ) this.val = val; else { const tail = new MyLinkedList(); tail.val = val; let ptr = this.next; if ( !ptr ) { this.next = tail; tail.prior = this; } else { while ( ptr.next ) ptr = ptr.next; ptr.next = tail; tail.prior = ptr; } } } addAtIndex ( index: number, val: number ): void { if ( index == 0 ) this.addAtHead( val ); else { if ( !this.next ) { if ( index == 1 \u0026\u0026 this.val != undefined ) this.addAtTail( val ); else return; } else { let i = 1, ptr = this.next; while ( i \u003c index \u0026\u0026 ptr.next ) { ++i; ptr = ptr.next; } if ( i == index ) { const prior = new MyLinkedList(); prior.val = val; if ( ptr.prior ) { ptr.prior.next = prior; prior.prior = ptr.prior; } prior.next = ptr; ptr.prior = prior; } else if ( i + 1 == index ) { const tail = new MyLinkedList(); tail.val = val; ptr.next = tail; tail.prior = ptr; } } } } deleteAtIndex ( index: number ): void { if ( index == 0 ) { if ( this.next ) { this.val = this.next.val; this.next = this.next.next; if ( this.next ) this.next.prior = this; } else this.val = undefined; } else if ( !this.next ) return; else { let i = 1, ptr = this.next; while ( i \u003c index \u0026\u0026 ptr.next ) { ++i; ptr = ptr.next; } if ( i == index \u0026\u0026 ptr.prior ) { if ( ptr.next ) { ptr.prior.next = ptr.next; ptr.next.prior = ptr.prior; } else ptr.prior.next = undefined; } } } } /** * Your MyLinkedList object will be instantiated and called as such: * var obj = new MyLinkedList() * var param_1 = obj.get(index) * obj.addAtHead(val) * obj.addAtTail(val) * obj.addAtIndex(index,val) * obj.deleteAtIndex(index) */ ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:1","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"141. Linked List Cycle /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function hasCycle ( head: ListNode | null ): boolean { const m: Map\u003cListNode, boolean\u003e = new Map(); let ptr = head, res = false; while ( ptr !== null ) { if ( !m.has( ptr ) ) { m.set( ptr, true ); ptr = ptr.next; } else { res = true; break; } } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:2","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"142. Linked List Cycle II /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function detectCycle ( head: ListNode | null ): ListNode | null { const m: Map\u003cListNode, boolean\u003e = new Map(); let ptr = head, res: ListNode | null = null; while ( ptr !== null ) { if ( !m.has( ptr ) ) { m.set( ptr, true ); ptr = ptr.next; } else { res = ptr; break; } } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:3","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"160. Intersection of Two Linked Lists /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function getIntersectionNode ( headA: ListNode | null, headB: ListNode | null ): ListNode | null { let m: Map\u003cListNode, boolean\u003e = new Map(), ptrA = headA, ptrB = headB, res: ListNode | null = null; while ( ptrA !== null ) { m.set( ptrA, true ); ptrA = ptrA.next; } while ( ptrB !== null ) { if ( !m.has( ptrB ) ) { m.set( ptrB, true ); ptrB = ptrB.next; } else { res = ptrB; break; } } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:4","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"19. Remove Nth Node From End of List /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function removeNthFromEnd ( head: ListNode | null, n: number ): ListNode | null { let ptr = head, res: ListNode | null, list: ListNode[] = []; while ( ptr !== null ) { list.push( ptr ); ptr = ptr.next; } let len = list.length; if ( n == len \u0026\u0026 head ) res = head.next; else { let prior = list[ len - n - 1 ], next = n == 1 ? null : list[ len - n + 1 ]; prior.next = next; res = head; } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:5","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"206. Reverse Linked List /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function reverseList ( head: ListNode | null ): ListNode | null { let res: ListNode | null = null, list: ListNode[] = [], ptr = head; while ( ptr !== null ) { list.push( ptr ); ptr = ptr.next; } let len = list.length; res = list[ len - 1 ] === undefined ? null : list[ len - 1 ]; for ( let i = len - 1; i \u003e 0; --i ) { let prior = list[ i - 1 ], node = list[ i ]; node.next = prior; } if ( len \u003e 0 ) list[ 0 ].next = null; return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:6","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"203. Remove Linked List Elements /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function removeElements ( head: ListNode | null, val: number ): ListNode | null { let res: ListNode | null = null, list: ListNode[] = [], ptr = head; while ( ptr !== null ) { if ( ptr.val != val ) list.push( ptr ); ptr = ptr.next; } let len = list.length; if ( len \u003e 0 ) res = list[ 0 ]; for ( let i = 0; i \u003c len - 1; ++i ) list[ i ].next = list[ i + 1 ]; if ( len \u003e 0 ) list[ len - 1 ].next = null; return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:7","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"328. Odd Even Linked List /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function oddEvenList ( head: ListNode | null ): ListNode | null { let odd = head, ptr = head, oddTail: ListNode | null = head, even: ListNode | null = null, i = 1, evenTail: ListNode | null = null; while ( ptr !== null ) { if ( i % 2 != 0 ) { if ( i \u003e 1 \u0026\u0026 oddTail ) { oddTail.next = ptr; oddTail = ptr; } } else { if ( i == 2 ) { even = ptr; evenTail = ptr; } else { if ( evenTail ) { evenTail.next = ptr; evenTail = ptr; } } } ptr = ptr.next; ++i; } if ( oddTail ) oddTail.next = even; if ( evenTail ) evenTail.next = null; return odd; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:8","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"234. Palindrome Linked List /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function isPalindrome ( head: ListNode | null ): boolean { let list: number[] = [], ptr = head, res = true; while ( ptr !== null ) { list.push( ptr.val ); ptr = ptr.next; } let left = 0, right = list.length - 1; while (left \u003c= right) { if (list[right] != list[left]) { res = false; break; } ++left; --right; } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:9","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"21. Merge Two Sorted Lists /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { if (list1 == nullptr \u0026\u0026 list2 == nullptr) return nullptr; else if (list1 == nullptr) return list2; else if (list2 == nullptr) return list1; else { ListNode *front, *p, *p1, *p2; if (list1-\u003eval \u003c= list2-\u003eval) { front = list1; p1 = list1-\u003enext; p2 = list2; } else { front = list2; p1 = list1; p2 = list2-\u003enext; } p = front; while (p1 != nullptr \u0026\u0026 p2 != nullptr) { if (p1-\u003eval \u003c= p2-\u003eval) { p-\u003enext = p1; p1 = p1-\u003enext; } else { p-\u003enext = p2; p2 = p2-\u003enext; } p = p-\u003enext; } if (p1 == nullptr) p-\u003enext = p2; else p-\u003enext = p1; return front; } } }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:10","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"2. Add Two Numbers /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function addTwoNumbers ( l1: ListNode | null, l2: ListNode | null ): ListNode | null { let ptr1 = l1, ptr2 = l2; while ( ptr2 !== null || ptr1 !== null ) { if ( ptr2 !== null \u0026\u0026 ptr1 !== null ) { ptr1.val += ptr2.val; if ( ptr1.val \u003e 9 ) { if ( ptr1.next ) { ptr1.next.val += 1; ptr1.val -= 10; } else { let next = new ListNode( 1 ); ptr1.val -= 10; ptr1.next = next; } } if ( ptr2.next \u0026\u0026 ptr1.next === null ) ptr1.next = new ListNode( 0 ); ptr1 = ptr1.next; ptr2 = ptr2.next; } else if ( ptr2 === null \u0026\u0026 ptr1 ) { if ( ptr1.val \u003e 9 ) { if ( ptr1.next ) { ptr1.next.val += 1; ptr1.val -= 10; if ( ptr1.next.val \u003c 10 ) break; ptr1 = ptr1.next; } else { let next = new ListNode( 1 ); ptr1.val -= 10; ptr1.next = next; } } else break; } } return l1; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:11","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"430. Flatten a Multilevel Doubly Linked List /** * Definition for node. * class Node { * val: number * prev: Node | null * next: Node | null * child: Node | null * constructor(val?: number, prev? : Node, next? : Node, child? : Node) { * this.val = (val===undefined ? 0 : val); * this.prev = (prev===undefined ? null : prev); * this.next = (next===undefined ? null : next); * this.child = (child===undefined ? null : child); * } * } */ function flatten ( head: Node | null ): Node | null { let ptr = head; while ( ptr !== null ) { if ( ptr.child ) { let next = ptr.next; let child = flatten( ptr.child ); ptr.child = null; if ( child ) { ptr.next = child; child.prev = ptr; while ( ptr.next ) ptr = ptr.next; ptr.next = next; if ( next ) next.prev = ptr; } } ptr = ptr.next; } return head; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:12","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"138. Copy List with Random Pointer /** * Definition for Node. * class Node { * val: number * next: Node | null * random: Node | null * constructor(val?: number, next?: Node, random?: Node) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * this.random = (random===undefined ? null : random) * } * } */ function copyRandomList ( head: Node | null ): Node | null { let res: Node | null = null, list: Node[] = [], map: Map\u003cNode, number\u003e = new Map(), ptr = head, i = 0; while ( ptr !== null ) { let node = new Node( ptr.val ); list.push( node ); map.set( ptr, i ); ++i; ptr = ptr.next; } ptr = head; i = 0; while ( ptr !== null ) { if ( list[ i ] ) { list[ i + 1 ] ? list[ i ].next = list[ i + 1 ] : null; if ( ptr.random ) { let index = map.get( ptr.random ); index !== undefined ? list[ i ].random = list[ index ] : null; } else list[ i ].random = null; } ++i; ptr = ptr.next; } res = list[ 0 ]; return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:13","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"61. Rotate List /** * Definition for singly-linked list. * class ListNode { * val: number * next: ListNode | null * constructor(val?: number, next?: ListNode | null) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } * } */ function rotateRight ( head: ListNode | null, k: number ): ListNode | null { if ( k == 0 ) return head; let map: Map\u003cnumber, ListNode\u003e = new Map(), ptr = head, i = 0, res: ListNode | null = null; while ( ptr ) { map.set( i, ptr ); ptr = ptr.next; ++i; } if ( i \u003c 2 || k % i == 0 ) return head; k = i - k % i; if ( k == 0 ) res = head; else { let node = map.get( k ); node ? res = node : res = null; if ( res ) { ptr = res; while ( ptr.next ) ptr = ptr.next; ptr.next = head; ptr = head; while ( ptr \u0026\u0026 ptr.next !== res ) ptr = ptr.next; if ( ptr ) ptr.next = null; } } return res; }; ","date":"2023-10-18","objectID":"/zh-cn/leetcode-linked-list-solutions/:0:14","tags":["LeetCode","TypeScript","C++","链表","数据结构","算法"],"title":"Leetcode Linked List 题解","uri":"/zh-cn/leetcode-linked-list-solutions/"},{"categories":["笔记"],"content":"最近需要在iPhone上模拟定位,研究了一下,终于发现了一个简单有效的方法。 我在网上找到了好几种办法,在不越狱iPhone的情况下。第一种是使用AnyGo,这个软件是有效的,但是需要付费。第二种是用一个具有root权限的安卓手机,在上面安装这个OTGLocation,之后把iPhone连接到这个安卓手机上。其他方法还有借助Xcode、爱思助手,或者是外接设备,甚至还可以模拟卫星信号欺骗手机。 我觉得这些办法都太麻烦了,在https://shawnhuangyh.com/post/ios-17-location-simulation/这里找到一个简单有效的办法,主要使用了pymobiledevice3。 ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:0","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"1. 在macOS上安装pymobiledevice3: python3 -m pip install -U pymobiledevice3 ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:1","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"2. 在iPhone中开启开发者模式,位于Settings -\u003e Privacy \u0026 Security -\u003e Developer Mode。 ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:2","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"3. 将iPhone连接到macOS上,在macOS上执行: sudo python3 -m pymobiledevice3 remote start-quic-tunnel 将会打印类似以下内容: Interface: utun6 RSD Address: fd7b:e5b:6f53::1 RSD Port: 64337 Use the follow connection option: --rsd fd7b:e5b:6f53::1 64337 RSD Address和RSD Port在第5步要用到。 ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:3","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"4. 确保iPhone此时还没有锁屏,在macOS上执行: sudo pymobiledevice3 mounter auto-mount ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:4","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"5. 继续在macOS中执行: pymobiledevice3 developer dvt simulate-location set --rsd \u003cRSD Address\u003e \u003cRSD Port\u003e -- \u003clatitude\u003e \u003clongtitude\u003e 将\u003c\u003e中的内容替换为自己的内容,分别为第3步中的RSD Address和RSD Port,以及要模拟的纬度和经度。此时在iPhone上查看,定位应该已经变成了模拟的位置。在停止模拟后,iPhone的定位会自动恢复正常。 ","date":"2023-10-13","objectID":"/zh-cn/simulate-locations-for-ios17/:0:5","tags":["iPhone","macOS","Python","命令行工具"],"title":"iOS17模拟定位","uri":"/zh-cn/simulate-locations-for-ios17/"},{"categories":["笔记"],"content":"Leetcode Arrays 101 ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:0","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"485. Max Consecutive Ones const findMaxConsecutiveOnes = (nums: number[]): number =\u003e { let res = 0, len = 0, end = nums.length; for (let i = 0; i \u003c end; ++i) { if (nums[i] == 1) ++len; else { res = Math.max(res, len); len = 0; } } res = Math.max(res, len); return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:1","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"1295. Find Numbers with Even Number of Digits const findMaxConsecutiveOnes = (nums: number[]): number =\u003e { let res = 0, len = 0, end = nums.length; for (let i = 0; i \u003c end; ++i) { if (nums[i] == 1) ++len; else { res = Math.max(res, len); len = 0; } } res = Math.max(res, len); return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:2","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"977. Squares of a Sorted Array function sortedSquares(nums: number[]): number[] { nums = nums.map(num =\u003e num * num); nums.sort((a, b) =\u003e a - b); return nums; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:3","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"1089. Duplicate Zeros /** Do not return anything, modify arr in-place instead. */ function duplicateZeros ( arr: number[] ): void { let i = 0, len = arr.length; while ( i \u003c len ) { if ( arr[ i ] != 0 ) ++i; else { arr.splice( i, 0, 0 ); arr.pop(); i += 2; } } }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:4","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"88. Merge Sorted Array /** Do not return anything, modify nums1 in-place instead. */ function merge ( nums1: number[], m: number, nums2: number[], n: number ): void { let i = 0, end = m; for ( let num of nums2 ) { while ( i \u003c end \u0026\u0026 nums1[ i ] \u003c num ) ++i; nums1.splice( i, 0, num ); nums1.pop(); ++end; } }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:5","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"27. Remove Element function removeElement ( nums: number[], val: number ): number { let res = 0, i = 0; while ( i \u003c nums.length ) { if ( nums[ i ] != val ) { ++res; ++i; } else nums.splice( i, 1 ); } return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:6","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"26. Remove Duplicates from Sorted Array function removeDuplicates(nums: number[]): number { const set: Set\u003cnumber\u003e = new Set(); let i = 0; while (i \u003c nums.length) { if (set.has(nums[i])) nums.splice(i, 1); else { set.add(nums[i]); ++i; } } return nums.length; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:7","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"1346. Check If N and Its Double Exist function checkIfExist(arr: number[]): boolean { let res = false; const set: Set\u003cnumber\u003e = new Set(arr); const zeros = arr.filter(num =\u003e num == 0); const len = zeros.length; for (let s of set) { if (set.has(2 * s)) { if (s == 0 \u0026\u0026 len \u003c 2) continue; res = true; break; } } return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:8","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"941. Valid Mountain Array function validMountainArray(arr: number[]): boolean { let res = true, inc = true, len = arr.length; if (len \u003c 3 || arr[0] \u003e= arr[1] ) return false; for (let i = 0; i \u003c len; ++i) { if (inc \u0026\u0026 (arr[i] \u003c arr[i - 1])) inc = false; if (arr[i] == arr[i - 1] || (!inc \u0026\u0026 (arr[i] \u003e= arr[i - 1]))) { res = false; break; } } if (inc) res = false; return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:9","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"1299. Replace Elements with Greatest Element on Right Side function replaceElements(arr: number[]): number[] { let res: number[] = [], len = arr.length; for (let i = 0; i \u003c len - 1; ++i) { let max = Math.max(...arr.slice(i + 1, len)); res.push(max); } res.push(-1); return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:10","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"26. Remove Duplicates from Sorted Array function removeDuplicates(nums: number[]): number { const set: Set\u003cnumber\u003e = new Set(); let i = 0; while (i \u003c nums.length) { if (set.has(nums[i])) nums.splice(i, 1); else { set.add(nums[i]); ++i; } } return nums.length; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:11","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"283. Move Zeroes /** Do not return anything, modify nums in-place instead. */ function moveZeroes ( nums: number[] ): void { let i = 0, j = 1, len = nums.length; while ( i \u003c len \u0026\u0026 j \u003c len ) { if ( nums[ i ] == 0 \u0026\u0026 nums[ j ] != 0 ) { let temp = nums[ i ]; nums[ i ] = nums[ j ]; nums[ j ] = temp; } if ( nums[ i ] != 0 ) ++i; if ( j \u003c i ) j = i; else if ( nums[ j ] == 0 ) ++j } }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:12","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"905. Sort Array By Parity function sortArrayByParity(nums: number[]): number[] { let res: number[] = []; res = nums.sort((a, b) =\u003e { if (a % 2 == 0 \u0026\u0026 b % 2 != 0) return -1; else if (a % 2 != 0 \u0026\u0026 b % 2 == 0) return 1; else return 0; }); return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:13","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"27. Remove Element function removeElement ( nums: number[], val: number ): number { let res = 0, i = 0; while ( i \u003c nums.length ) { if ( nums[ i ] != val ) { ++res; ++i; } else nums.splice( i, 1 ); } return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:14","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"1051. Height Checker function heightChecker(heights: number[]): number { let res = 0, len = heights.length; const temp = [...heights]; heights.sort((a, b) =\u003e a - b); for (let i = 0; i \u003c len; ++i) { if (temp[i] != heights[i]) ++res; } return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:15","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"414. Third Maximum Number function thirdMax ( nums: number[] ): number { let a = -Infinity, b = -Infinity, c = -Infinity; for ( let n of nums ) { if ( n \u003e a || n \u003e b \u0026\u0026 n \u003c a || n \u003e c \u0026\u0026 n \u003c b ) c = n; if ( c \u003e b ) { let t = c; c = b; b = t; } if ( b \u003e a ) { let t = b; b = a; a = t; } } if ( c != -Infinity ) return c; else return a; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:16","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"448. Find All Numbers Disappeared in an Array function findDisappearedNumbers(nums: number[]): number[] { const len = nums.length, s: Set\u003cnumber\u003e = new Set(nums), res: number[] = []; for (let i = 1; i \u003c= len; ++i) { if (!s.has(i)) res.push(i); } return res; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:17","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["笔记"],"content":"977. Squares of a Sorted Array function sortedSquares(nums: number[]): number[] { nums = nums.map(num =\u003e num * num); nums.sort((a, b) =\u003e a - b); return nums; }; ","date":"2023-10-10","objectID":"/zh-cn/leetcode-arrays-101-solutions/:0:18","tags":["LeetCode","数组","数据结构","算法","TypeScript"],"title":"Leetcode Arrays 101 题解","uri":"/zh-cn/leetcode-arrays-101-solutions/"},{"categories":["日记"],"content":" 希望下周能到50小时🌲 ","date":"2023-10-01","objectID":"/zh-cn/focus-statistics-40-2023/:0:0","tags":["专注统计"],"title":"专注统计 (2023 40周)","uri":"/zh-cn/focus-statistics-40-2023/"},{"categories":["笔记"],"content":"今天发现了一个有可以限制Apple Silicon Macbook电池充电的命令行工具,名字叫做battery。 battery https://github.com/actuallymentor/battery 之前我一直在用AlDente,与它相比,battery的优点是可以直接在命令行中使用,而且完全免费,而AlDente如果不付费就只能使用最基础的功能,而且它的图标还一直在菜单栏占用了一个位置。 只需一行命令即可安装: curl -s https://raw.githubusercontent.com/actuallymentor/battery/main/setup.sh | bash 安装完成后,可以使用battery help查看帮助信息,就是这么简单。 ","date":"2023-09-23","objectID":"/zh-cn/battery-battery-charge-limiter-for-apple-silicon-macbook-devices/:0:0","tags":["macOS","命令行工具"],"title":"battery: 限制Apple Silicon Macbook的电池充电","uri":"/zh-cn/battery-battery-charge-limiter-for-apple-silicon-macbook-devices/"},{"categories":["项目"],"content":"前天忽然发现Chrome Devtools里的字体家族不能直接修改,查了一下发现可以写一个扩展来解决这个问题。 Devtools-Font https://github.com/kayak4665664/Devtools-Font 我主要参考了https://gist.github.com/vbsessa/e337d0add70a71861b8c580d5e16996e,但是按照这个教程“Sources”中的字体没有变化,我在这个基础上做了一些修改。最后我把字体改成了FiraCode Nerd Font,不得不说这个字体真的好看,还有连笔效果。 ","date":"2023-08-26","objectID":"/zh-cn/devtools-font/:0:0","tags":["浏览器","Chrome扩展","前端"],"title":"Devtools-Font","uri":"/zh-cn/devtools-font/"},{"categories":["日记"],"content":"我们于7月12日从雁栖湖校区搬到了北京城里,这里放一些我在雁栖湖校区最后几天拍的照片。 彩虹 两头驴 乌鸦 蜂 山上的彩灯 路灯 鸭子 电线上的鸟 金鱼 鸬鹚 鸬鹚 鸬鹚 山上的雾 下雨之后 ","date":"2023-07-16","objectID":"/zh-cn/last-days-at-yanqi-lake-campus/:0:0","tags":["UCAS","转悠"],"title":"在雁栖湖校区最后的几天","uri":"/zh-cn/last-days-at-yanqi-lake-campus/"},{"categories":["笔记"],"content":"我在完成Springboot-Demo的过程中,遇到了一个获取资源文件的问题。 刚开始,我使用Maven将项目打包成了jar包,然后运行,程序报错找不到json文件了。经过排查,我发现问题出在了我获取json文件的方式上,我使用了相对路径,但是在运行jar包时,相对路径是相对于jar包所在的目录,而不是相对于源代码目录,这样就找不到json文件了。 解决的方法是使用ClassLoader类的getResourceAsStream方法,它可以根据给定的路径名返回一个InputStream对象,然后就可以使用这个对象来读取资源文件的内容。比如: //假如存在一个Main类,获取类加载器对象 ClassLoader classLoader = Main.class.getClassLoader(); //根据资源文件名获取输入流对象 InputStream inputStream = classLoader.getResourceAsStream(\"test.log\"); ","date":"2023-06-11","objectID":"/zh-cn/get-resource-files-through-classloader/:0:0","tags":["Java"],"title":"通过类加载器获取资源文件","uri":"/zh-cn/get-resource-files-through-classloader/"},{"categories":["项目"],"content":"这个学期我选了一门Java编程课,最后要完成一个项目,就是Springboot-Demo。 Springboot-Demo https://github.com/kayak4665664/Springboot-Demo 这个程序的功能就是从json文件中读取数据,再显示到页面上。除了Springboot框架,前端还是我常用的Layui和Highcharts。 我选这门Java课主要就是想练习一下Java的Web开发。我记得我大三的时候有一门软件工程实践课,有一个实验就是要做一个Web应用。当时我第一次接触Web开发,本来想用Java和Springboot来完成,我在网上找了教程,感觉有点看不明白。然后我又了解了一下python的Django框架,发现比较容易理解,最后我就用Django做了那个实验。这次我用Springboot,感觉和Django其实也差不多。 ","date":"2023-06-11","objectID":"/zh-cn/springboot-demo/:0:0","tags":["Java"],"title":"Springboot-Demo","uri":"/zh-cn/springboot-demo/"},{"categories":["日记"],"content":"以前的眼镜是上大学之前配的,已经有点看不清了。正好我在北京,听说潘家园(北京眼镜城)的眼镜特别便宜,我就去了。 之前忘了在哪看到了变色眼镜,可以根据紫外线强度变色,我决定这次就配一副变色眼镜。我在网上查了一下,大家都说蔡司和依视路的镜片比较好,我比较了一番,最后决定买一副蔡司焕色视界X镜片。我的度数应该在800度以内,所以可以选择折射率1.6的镜片。 我看到有攻略说网上配眼镜比较便宜,先去验光,再到实体店试戴镜框,记下镜框型号,然后再到网上购买镜框,再把镜框和验光单发给卖镜片的商家,加工好之后再邮寄过来。我觉得这个方法环节太多,而且我尤其不喜欢等快递,所以我还是决定去潘家园看看。网上都说潘家园的水很深,我在知乎和小红书上看到了好多攻略,看得云里雾里的,我后来感觉这些多半都是软广告,不如不看。我觉得只要不比网上的价格高,镜片是正品,镜框合适,就可以了。 另外还有一点,大家都说不要在潘家园的眼镜店里验光,结果不太准确。最好去北京同仁验光配镜中心,但是需要提前预约,我预约的时候已经约满了。我就预约了去宝岛眼镜验光,宝岛眼镜是全国连锁的,也是比较专业的。 国科大雁栖湖校区离北京城区太远了,好在学校每天都有来回的班车。周六比较空闲,我预定了周六早上7点的班车。我第一次坐班车去城里,没想到周六进城的人这么多,我赶到车站时已经坐满了一辆车,我上了第二辆车也只剩下四、五个座位了。不到一个小时就到了奥运村下车点,自从2月开学以来还是第一次进城。 我马上又坐上了地铁,先去宝岛眼镜验光。下了地铁慢慢走过去刚好9点,店里一个顾客都没有。免费注册了一个会员,“精致验光”服务可以优惠10元到50元。之后开始验光,大概用了3种仪器,用了十几分钟。验光师告诉我结果,左右眼都是600多度,都有100度左右的散光。还好,和我上大学之前的差不多。戴上插片眼镜试了试,感觉不错。宝岛眼镜的验光结果可以直接在微信公众号里查看,这一点是很方便的。验光师还说,如果常看近处最好不要戴矫正到1.0的眼镜,0.8、0.9的就可以了。根据验光结果,我确实需要配一副变色眼镜。 从宝岛眼镜出来直奔公交车站,赶往潘家园。到站大概是10点,和网上说的一样,一下车就有不少拉客配眼镜的人。在过街天桥上,对面就是北京眼镜城。一进大门,全是眼镜店,网上都说楼层越高的眼镜店越便宜,我就直接上楼了。在三楼四楼全转了一圈,不知道该进谁家。我看到了几家网红店,里面的顾客确实要比一般的店多一些。 我下到了二楼,这次我决定,哪家店招揽我我就进哪家。进了第一家,我直接和老板说我要焕色视界X镜片。老板拿出了一个蔡司产品手册,开始翻找,找了半天没有找到,我一看他的产品手册是去年的,焕色视界X是新出的,应该确实不在里面。第二家也是一样的情况,我又看了几家,也都没有我要的镜片。我怀疑是不是都没有,我决定再看几家,如果还没有就回去在网上买。 又进了一家店,这家店的老板是一位南方口音的阿姨。她说她的产品手册是今年的,应该可以找到。翻了翻册子,果然找到了。我问她多少钱,她拿出了计算器,用一个折扣系数乘以产品手册上的定价。潘家园的眼镜店一般都可以打定价的3至4折,每家店的老板都有一个长得差不多的计算器。她给出了一个价格,但是要比网上的高不少。开始和她讨价还价,最后我拿出了京东购物车里的镜片价格给她看,终于把价格压了下来,镜片和镜框1000元全包了。之后开始选镜框,拿出了十几个挨个试,大概选出了几个。我又和她再确认镜片的型号规格,这时候我发现刚才看错了,刚才看的是一个其他型号的,不太一样。她又说我要的型号1000元拿不下来,可是我刚才给她看京东购物车里的我要的型号的镜片1000元可以拿下。总之又是一阵讨价还价,我觉得这是在浪费时间,我和她说不行的话我再去其他店看看吧。她看我要走她就松口了,她赶紧让我给她验光单,但是这个时候我真的有点不想在她家配眼镜了。我问她什么时候可以拿到眼镜,她说定制镜片至少要等5到7天,我还以为在实体店可以当场带走。我又问她普通镜片可不可以当场带走,她告诉我等1个小时就可以了,她极力推荐我购买普通镜片。看得出来,她对变色镜片不太熟悉。总的来说,我觉得这家店的体验不太好,我决定还是去其他店看看。但是这位老板还是非常热情地让我购买普通镜片,我看了看表,11点多了,我只好借口肚子饿了要吃午饭先走一步。 我又上了三楼,和二楼差不多,产品手册上都没有我要的镜片,好几家店的老板都给一个人打电话,估计是蔡司镜片代理,都说我要的镜片没有现片,必须找厂家调货。我又随便进了一家店,这家店的老板是一个年轻人,说话比较爽快。我看他对变色镜片好像比较熟悉,他给我镜片定价的3折大概1100元,我拿出手机给他看京东购物车里镜片的价格,我还告诉他刚才我看了一家可以1000元镜片镜框全拿下。他很快就说可以,比我想象得快。之后开始挑选镜框,大概选出了几个。我又和他确认了镜片的型号规格和价格,没有问题。他也说定制镜片需要5至7天才能拿到,我在变色镜片和普通镜片之间犹豫,我借口肚子饿了要吃午饭再考虑考虑。 我又上了四楼,情况差不多,而且给的价格都比较高。我决定就去三楼那家店。我逛了半个小时,回到了那家店。我又挑选了几个镜框,又和老板确认了镜片的型号规格和价格。我付了钱,加了老板的微信,眼镜制作好后他会通知我。我下到了一楼,这时候刚过12点。我之前买了下午4点半从北京北站到怀柔北站的火车票,我看时间比较富余,我想改签到下午2点半的车次。但是人满了不能改签。我开始思考我如何打发中间的几个小时,我决定先去吃饭。 在北京吃饭太贵了,在路边小店随便吃一碗面条就得20元,里面还没有肉。我沿着马路一路向北,发现了一家麦当劳。比起其他饭店,我觉得麦当劳还是不错的,价格可以接受,可以吃到货真价实的肉,味道也可以,不用担心食品安全,尤其是那个随心配套餐,13.9元可以买一个双层吉士汉堡和菠萝派,虽然比以前涨价了。我在麦当劳里找了个位置坐下,继续考虑吃完饭去哪。我决定从这里骑车到北京北站,可以看看沿途的街景,打发时间。 从麦当劳出来,找了一辆哈啰单车,我之前买了月卡,两个小时之内免费。从东三环到长安街再到北二环,用了一个半小时。到了北站还剩几十分钟,去旁边凯德MALL随便逛了逛,然后上了火车,回到了学校。 过了一周,我的眼镜制作好了。我又约好了周六早上7点的班车,买了下午两点半的火车票。 和上次一样,不到8点就到了奥运村下车点。时间还早,我先去奥林匹克公园转了转,里面人很少。 之后上了地铁前往潘家园,大概9点多到达。上了三楼我发现我找不到那家店在哪了,绕了一圈才找到了。我拿到了眼镜,检查了一下,查验了镜片的真伪,没有发现什么问题。我走出大楼,眼镜果然变色了,感觉真不错。 我早上6点吃了早饭,已经饿了。我又走到了那家麦当劳,但是刚过10点,还在卖早餐,我找位置坐下休息了半个小时。 吃完饭,我开始朝着北京北站的方向闲逛,一会坐地铁一会步行。 到了北站还有几十分钟,我去旁边的凯德MALL逛了逛,逛到了小米之家,看了看小米最新的产品。之后坐上了火车,回到了学校。 总的来说,潘家园的水确实很深,有很多坑,不过在价格上有优势。假如不差钱的话,其实去宝岛眼镜这种大型连锁店是一个更好的选择,服务更好更省心。这次配的眼镜还是比较符合我的预期,比较满意。 ","date":"2023-04-26","objectID":"/zh-cn/go-to-panjiayuan-to-get-glasses/:0:0","tags":["转悠"],"title":"去潘家园配眼镜","uri":"/zh-cn/go-to-panjiayuan-to-get-glasses/"},{"categories":["项目"],"content":"上一篇文章介绍了如何抓包,这篇文章介绍编写程序解析抓包文件。 信息 本文涉及的源代码在GitHub仓库: Pcap-Parser https://github.com/kayak4665664/Pcap-Parser Pcap文件中包含了网络数据包的信息,包括源IP地址、目的IP地址、源端口、目的端口、传输层协议、应用层协议等。因此,程序的思路就是从数据链路层开始解析,直到应用层,解析出每一层的协议类型和协议数据。在实现上可以参考Wireshark的解析结果。 对于C/C++,可以使用\u003cpcap.h\u003e处理Pcap文件。之后,使用\u003cnet/ethernet.h\u003e、\u003cnetinet/ip.h\u003e、\u003cnetinet/tcp.h\u003e定义的以太网头部、IP头部、TCP头部结构体解析数据链路层、网络层、传输层。另外,IP头部和TCP头部都有options,这个字段结构体中没有。 应用层的协议种类比较多,需要针对每一种协议编写程序。我的程序支持解析HTTP和TLS协议。 HTTP是明文协议,数据字段之间是用\\r\\n分隔的,另外需要考虑一个HTTP消息分成了好多个packet,对相关packet重组之后才能解析出正确的结果。而TLS是加密协议,比较复杂,要按照协议的结构进行解析,也要考虑重组的情况。 以上只是一些简单的思路,实际上还有许多复杂的情况没有覆盖。 ","date":"2023-04-11","objectID":"/zh-cn/pcap-parser/:0:0","tags":["C++","Github","算法","抓包","命令行工具"],"title":"Pcap-Parser","uri":"/zh-cn/pcap-parser/"},{"categories":["笔记"],"content":"使用Charles、Wireshark和tcpdump对手机App抓包。 信息 我在macOS上对iPhone进行抓包,但是对于其他系统和设备,方法和原理也是类似的。 ","date":"2023-04-10","objectID":"/zh-cn/capture-packets-for-mobile-apps/:0:0","tags":["抓包","iPhone","macOS","命令行工具"],"title":"手机App抓包","uri":"/zh-cn/capture-packets-for-mobile-apps/"},{"categories":["笔记"],"content":"Wireshark Wireshark是一个开源的网络分析工具,可以用来抓取网络数据包。它可以在macOS、Windows和Linux上运行。 在macOS上,可以使用brew安装Wireshark: brew install --cask wireshark 使用Wireshark抓包也很简单,比如选择Wi-Fi接口就可以抓无线网卡的数据包。 ","date":"2023-04-10","objectID":"/zh-cn/capture-packets-for-mobile-apps/:1:0","tags":["抓包","iPhone","macOS","命令行工具"],"title":"手机App抓包","uri":"/zh-cn/capture-packets-for-mobile-apps/"},{"categories":["笔记"],"content":"tcpdump tcpdump是一个命令行工具,可以用来抓取网络数据包。假如在没有图形界面的服务器上,可以使用它来抓取数据包。 在macOS上,可以使用brew安装tcpdump: brew install tcpdump 使用tcpdump抓包,比如抓取12345端口的数据包并保存为pcap文件: tcpdump port 12345 -w capture.pcap ","date":"2023-04-10","objectID":"/zh-cn/capture-packets-for-mobile-apps/:2:0","tags":["抓包","iPhone","macOS","命令行工具"],"title":"手机App抓包","uri":"/zh-cn/capture-packets-for-mobile-apps/"},{"categories":["笔记"],"content":"Charles Charles是一个HTTP代理服务器,可以用来抓取HTTP和HTTPS的数据包,和Fiddler类似。 在macOS上,也使用brew安装Charles: brew install --cask charles ","date":"2023-04-10","objectID":"/zh-cn/capture-packets-for-mobile-apps/:3:0","tags":["抓包","iPhone","macOS","命令行工具"],"title":"手机App抓包","uri":"/zh-cn/capture-packets-for-mobile-apps/"},{"categories":["笔记"],"content":"手机App抓包 对于MacBook,如果已经连接了Wi-Fi,就不能开启无线热点了。所以需要用Charles来建立一个代理服务器,然后手机连接到这个代理服务器上。主要步骤如下: macOS设备和iPhone都连接到第三个设备开启的移动热点,确保处于同一个局域网内。 在macOS设备中启动Charles,设置代理服务,默认端口为8888。 在iPhone的无线网络设置中,将代理服务器设置为macOS设备的IP地址,端口为8888。 iPhone在浏览器中访问chls.pro/ssl,下载并安装证书。 iPhone在General -\u003e About -\u003e Certificate Trust Settings中,将Charles的证书设置为信任。 iPhone在General -\u003e VPN \u0026 Device Management中安装Charles的描述文件。 由于Charles只能抓取HTTP和HTTPS的数据包,所以这里在macOS设备中启动Wireshark,选择Wi-Fi接口抓取所有协议的数据包。 在iPhone中打开需要抓包的App,进行相关操作。 Wireshark停止抓包,之前设置的代理服务器端口是8888,所以可以通过tcp.port == 8888过滤无关的数据包,将过滤后的包保存为pcap文件。 ","date":"2023-04-10","objectID":"/zh-cn/capture-packets-for-mobile-apps/:4:0","tags":["抓包","iPhone","macOS","命令行工具"],"title":"手机App抓包","uri":"/zh-cn/capture-packets-for-mobile-apps/"},{"categories":["笔记"],"content":"境外的购物网站很多都不支持中国银联的银行卡,而中国银行长城跨境通借记卡是一个可以在线申请、没有申请门槛也没有年费的卡。 信息 我主要在跨境通VISA/万事达借记卡介绍与网上支付体验这篇博客上了解到了这个卡,感谢作者的分享。 跨境通卡有许多种类,但是申请的流程都是一样的,我申请的是万事达世界卡,这个卡的卡面是莫奈的日出印象,很漂亮。我主要介绍我自己办理的过程,其他详细的信息可以参考上面的博客。 ","date":"2023-03-23","objectID":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/:0:0","tags":["境外支付"],"title":"网上申请中国银行万事达借记卡","uri":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/"},{"categories":["笔记"],"content":"网上申请 中国银行上海分行万事达世界卡申请 https://cloud.bankofchina.com/sh/api/net/common/url/adr?id=kuajinggomastercard 在手机上打开以上链接,根据要求提交资料,邮寄地址必须精确到门牌号,开户行可以任选。 技巧 我在这一步遇到了一个问题,我填自己的手机号死活收不到验证码。我用中国移动和多号办理了一个副号,然后用这个副号就可以收到验证码了。我发现发送验证码的是106980095566这个号码,不是中国银行的客服热线95566。106980095566这个号码是可以发送TD退订的,我猜测我以前应该是退订了这个号码的短信服务,所以收不到验证码。 提交申请之后可以在上面的链接中查询进度,如果申请失败了也会收到短信提醒。我第一次申请就是写了学校的地址,没有精确到门牌号,所以申请失败了。 如果申请通过,大概两个星期可以收到通过EMS邮寄的银行卡。 ","date":"2023-03-23","objectID":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/:1:0","tags":["境外支付"],"title":"网上申请中国银行万事达借记卡","uri":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/"},{"categories":["笔记"],"content":"线下激活 收到银行卡之后到任意一个中国银行网点激活,需要带上身份证和银行卡。 在智能柜台就可以自助激活,默认的密码是身份证倒数第六位到倒数第二位。激活时可以修改绑定的手机号码,激活之后会把卡片关联到手机银行。 ","date":"2023-03-23","objectID":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/:2:0","tags":["境外支付"],"title":"网上申请中国银行万事达借记卡","uri":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/"},{"categories":["笔记"],"content":"激活之后 激活之后要给银行卡转入外汇,外汇需要通过中国银行I类卡购买。 另外,必须在手机银行中开通网上支付功能: 在“限额设置 -\u003e 限额设置”中调高限额 开通“限额设置 -\u003e 小额/凭签名免密(POS消费)” 开通“限额设置 -\u003e 磁条交易限额设置” 开通“支付设置 -\u003e 电子支付-手机支付” 开通“支付设置 -\u003e 电子支付-网上支付” 开通“支付设置 -\u003e 跨行支付 -\u003e 在线支付” 开通“支付设置 -\u003e 跨行支付 -\u003e 跨行代扣” 开通“支付设置 -\u003e 跨行支付 -\u003e 跨行订购” ","date":"2023-03-23","objectID":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/:3:0","tags":["境外支付"],"title":"网上申请中国银行万事达借记卡","uri":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/"},{"categories":["笔记"],"content":"用卡注意事项 消费或ATM取现支持直接使用美元、欧元、日元、港币等19种外币,无需货币转换。免收货币转换费、跨境手续费等消费手续费。每月免收首笔境外ATM取现和余额查询手续费。 外汇和外钞都可以用来消费和支付,使用时不会产生任何转换费。 若借记卡开卡后6个月内没有发生任何动账交易,停止非柜面业务。 如果长时间不用卡,卡片余额必须不为0。 绑卡或者日常消费时,美元账户余额须不少于2美元。 开户行是上海市分行,与实体卡片有关的业务(如丢失补卡、到期换卡等)需要去上海地区网点办理。 在境内转账外币只能转账给本人账户和直系亲属账户,本人的非中国银行账户、直系亲属的账户之间的外币转账需要到柜台办理。 消费时不会立即扣款,而是冻结特定比例的资金,等待银行入账后再解冻资金扣款,入账时间一般是两至三天。美元消费冻结100%、非美元消费冻结102%。 关注“中国银行微银行”公众号,绑定跨境通卡,可以开启动账消息提醒。但是只有入账交易通知,没有冻结通知。可以开通短信交易提醒,每月2元,需要用中国银行I类卡支付。 外币账户的扣款顺序为:交易币种钞户 -\u003e 交易币种汇户 -\u003e 美元钞户 -\u003e 美元汇户,只能使用一个外币账户全额支付,不能从多个账户扣款。 无卡交易仅需卡号、有效期、背面签名区后三位数字,不需要交易密码,因此三个信息务必保密。 不检验帐单地址,不支持AVS系统验证。 ","date":"2023-03-23","objectID":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/:4:0","tags":["境外支付"],"title":"网上申请中国银行万事达借记卡","uri":"/zh-cn/apply-for-bank-of-china-mastercard-debit-card-online/"},{"categories":["笔记"],"content":"使用Touch ID来验证sudo命令,这样就不用每次都输入密码了。 在Terminal中输入以下命令,之后重启Terminal即可。 sudo sed -i \".bak\" '2s/^/auth sufficient pam_tid.so\\'$'\\n/g' /etc/pam.d/sudo 这个命令首先备份/etc/pam.d/sudo为/etc/pam.d/sudo.bak,然后在第二行插入auth sufficient pam_tid.so。 如果恢复默认设置,可以使用以下命令: sudo mv /etc/pam.d/sudo.bak /etc/pam.d/sudo ","date":"2023-03-22","objectID":"/zh-cn/authorize-sudo-commands-with-touch-id/:0:0","tags":["macOS","命令行工具"],"title":"用Touch ID授权sudo命令","uri":"/zh-cn/authorize-sudo-commands-with-touch-id/"},{"categories":["笔记"],"content":"ChatGPT的API正式发布了,可以在Python中使用了。 ChatGPT API 简介 https://openai.com/blog/introducing-chatgpt-and-whisper-apis 注册OpenAI账号之后,在https://platform.openai.com/account/api-keys中创建一个API Key。在https://platform.openai.com/account/usage中可以看到,账号中有$18的免费额度,4月1日过期。 这次发布的ChatGPT模型gpt-3.5-turbo与ChatGPT产品中使用的模型相同。另外,还发布了gpt-3.5-turbo-0301,这个模型至少在6月1日之前是被支持的。 完整的API使用指导可以在这里找到: ChatGPT API 使用指导 https://platform.openai.com/docs/guides/chat 简单来说,要在Python中使用ChatGPT API,需要安装openai这个Python包。 # 如果没有安装openai,可以使用下面的命令安装 pip install openai # 如果之前安装了openai,使用下面的命令更新 pip install openai --upgrade 之后,import openai,然后使用openai.Completion.create函数来调用API即可。 下面是我写的一个简单的Python脚本,可以与ChatGPT进行多轮对话。 import os import openai # 这里要写上你自己的API Key os.environ[\"OPENAI_API_KEY\"] = \"sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\" openai.api_key = os.getenv(\"OPENAI_API_KEY\") messages = [ {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, ] # 这个函数用来调用API def get_response(messages): completion = openai.ChatCompletion.create( model=\"gpt-3.5-turbo\", messages=messages, ) return completion.choices[0].message.content # type: ignore while True: try: print(\"type 'quit' to exit, type 'new' to begin a new conversation\") user_content = input(\"You: \") if user_content == \"quit\": break elif user_content == \"new\": messages = [ {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, ] print(\"new conversation started\\n\") continue else: messages.append({\"role\": \"user\", \"content\": user_content}) response = get_response(messages) print(\"Assistant:\", response + \"\\n\") # 这里把Assistant的回复也加入到messages中,联系上下文 messages.append({\"role\": \"assistant\", \"content\": response}) except Exception as e: print(e) 运行之后是这样子的, 示例 type ‘quit’ to exit, type ’new’ to begin a new conversation You: What is the biggest animal in the world? Assistant: The biggest animal in the world is the blue whale. It can grow up to 100 feet long and weigh as much as 200 tons. type ‘quit’ to exit, type ’new’ to begin a new conversation You: Please write a poem about blue whales. Assistant: Majestic and mighty, The blue whale swims through the sea, Largest creature on earth, Behold its great beauty. A vast and gentle giant, Graceful in every move, Plunge deep into the ocean, Embrace the whale and groove. With a heart that’s enormous, And lungs as large as a car, Sing to the depths of the ocean, Your melodic, haunting bar. A creature so magnificent, Awe inspiring, and grand, Nowhere else found on earth, A true wonder of the land. Let us protect this great whale, So that it may flourish and thrive, For a world without the blue whale, Is a world less truly alive. type ‘quit’ to exit, type ’new’ to begin a new conversation You: new new conversation started type ‘quit’ to exit, type ’new’ to begin a new conversation You: 世界上最大的动物是什么? Assistant: 世界上最大的动物是蓝鲸。它们可以长达30米长,重达173吨,是地球上已知最大的动物。 type ‘quit’ to exit, type ’new’ to begin a new conversation You: 请写一首关于蓝鲸的诗。 Assistant: 在深深的海洋里 有一种生物,比海洋还大 它游荡于大海之中 它的名字叫做蓝鲸 蓝鲸身长三十米 重达一百七十三吨 它们是地球上最大的动物 不同寻常的存在 它们的歌声遥远而美丽 在海洋里有时听得见 它们善良而又神秘 是这片蔚蓝海洋之主 蓝鲸,你的身影 在海洋中,如此崇高 你的力量与恩宠 在人间,永世留存 type ‘quit’ to exit, type ’new’ to begin a new conversation You: quit ","date":"2023-03-03","objectID":"/zh-cn/using-the-chatgpt-api-in-python/:0:0","tags":["ChatGPT","Python"],"title":"在Python中使用ChatGPT API","uri":"/zh-cn/using-the-chatgpt-api-in-python/"},{"categories":["笔记"],"content":"在iOS和iPadOS上,可以在设置中开启私有WiFi地址来随机化MAC地址。在macOS上没有这个选项,但是我们可以通过命令行来实现这一点。 我在Github上找到了SpoofMAC,它是一个Python脚本,不仅适用于macOS,也可以在Windows和Linux上使用。它可以随机化MAC地址,也可以将MAC地址设置为任何值。 SpoofMAC https://github.com/feross/spoofmac 安装SpoofMAC很简单,只需要pip install SpoofMAC。 ","date":"2023-03-02","objectID":"/zh-cn/randomize-mac-address-for-macos/:0:0","tags":["macOS","Python","命令行工具"],"title":"随机化macOS的MAC地址","uri":"/zh-cn/randomize-mac-address-for-macos/"},{"categories":["笔记"],"content":"使用方法 下面是在macOS上使用SpoofMAC修改MAC地址的示例。 技巧 要直接在终端中运行spoof-mac,需要将bin添加到PATH中。如果你使用的是zsh,你可以在~/.zshrc中添加,例如export PATH=$PATH:~/Library/Python/3.9/bin。 首先,列出所有可用的设备 spoof-mac list 将会得到类似下面的输出 示例 - “Ethernet” on device “en0” with MAC address 70:56:51:BE:B3:00 - “Wi-Fi” on device “en1” with MAC address 70:56:51:BE:B3:01 - “Bluetooth PAN” on device “en1” 然后,随机化MAC地址 sudo spoof-mac randomize en1 # 或者 sudo spoof-mac randomize wifi 要复原MAC地址,只需运行 sudo spoof-mac reset en1 # 或者 sudo spoof-mac reset wifi ","date":"2023-03-02","objectID":"/zh-cn/randomize-mac-address-for-macos/:1:0","tags":["macOS","Python","命令行工具"],"title":"随机化macOS的MAC地址","uri":"/zh-cn/randomize-mac-address-for-macos/"},{"categories":["笔记"],"content":"pwgen可以在命令行中生成随机又安全密码! pwgen https://pwgen.sourceforge.io/ 直接使用Homebrew安装:brew install pwgen。 用法也很简单,比如pwgen -sy 50就是生成50个字符的密码,包含大小写字母、数字和特殊字符。更多用法可以使用pwgen -h查看: 注意 Usage: pwgen [ OPTIONS ] [ pw_length ] [ num_pw ] Options supported by pwgen: -c or –capitalize Include at least one capital letter in the password -A or –no-capitalize Don’t include capital letters in the password -n or –numerals Include at least one number in the password -0 or –no-numerals Don’t include numbers in the password -y or –symbols Include at least one special symbol in the password -r or –remove-chars= Remove characters from the set of characters to generate passwords -s or –secure Generate completely random passwords -B or –ambiguous Don’t include ambiguous characters in the password -h or –help Print a help message -H or –sha1=path/to/file[#seed] Use sha1 hash of given file as a (not so) random generator -C Print the generated passwords in columns -1 Don’t print the generated passwords in columns -v or –no-vowels Do not use any vowels so as to avoid accidental nasty words ","date":"2023-02-28","objectID":"/zh-cn/pwgen-random-password-generator/:0:0","tags":["命令行工具"],"title":"pwgen: 随机密码生成器","uri":"/zh-cn/pwgen-random-password-generator/"},{"categories":["笔记"],"content":"自从2021年建立我的网站以来,我一直都在用LoveIt这个Hugo主题,没太大变化。这一次,我迁移到了FixIt主题,不仅修复了LoveIt中的一些问题,也带来了更多新功能和优化,顺便也把评论系统从Valine迁移到了Waline。 FixIt https://fixit.lruihao.cn/ 由于FixIt是基于LoveIt的,所以迁移到Fixit是比较容易的。经过一番折腾,除了样式上的变化,我的网站主要的改变如下: 启用Twemoji 评论系统从Valine迁移到Waline,加入了图片和表情包、文章反应等功能 菜单栏加入了Font Awesome图标 加入了Github corner 更换了Mapbox地图样式 加入赞赏功能 加入PWA支持 加入网站已创建时间显示 加入不蒜子访问统计 加入了网站字数统计 标签改为词云显示 加入盘古之白 加入页面水印 加入阅读进度条 加入页面加载进度条 现在FixIt还在持续、积极地更新,我也会继续跟进,不断改进我的网站。 ","date":"2023-02-27","objectID":"/zh-cn/my-website-has-a-new-theme/:0:0","tags":["我的网站","Hugo"],"title":"我的网站换上了新主题","uri":"/zh-cn/my-website-has-a-new-theme/"},{"categories":["笔记"],"content":"macOS自带的终端很好用,但是感觉少了一些东西,所以我就把它强化一下。网上有好多人都推荐使用Oh My Zsh,但是不知道为什么,我在使用Oh My Zsh的时候经常会出现一些问题,所以这一次我没有使用它。 ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:0:0","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"美化 我用了starship来美化终端,它是一个轻量、迅速、跨平台的命令行主题。 starship https://starship.rs/zh-CN/ 在安装starship之前,需要安装Nerd Font字体,比如Fira Code Nerd Font。 可以使用Homebrew安装,然后在终端设置中启用Fira Code Nerd Font字体。 brew tap homebrew/cask-fonts brew install --cask font-fira-code-nerd-font 之后,使用Homebrew来安装starship:brew install starship。在~/.zshrc的最后添加eval \"$(starship init zsh)\",然后执行source ~/.zshrc。重新打开终端,就可以看到效果了。 更多的自定义配置可以参考指南。 ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:1:0","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"扩展 ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:0","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"1. zsh-fast-syntax-highlighting 这个插件可以高亮命令行输入的内容,让你的终端更加美观。 zsh-fast-syntax-highlighting https://github.com/zdharma-continuum/fast-syntax-highlighting brew install zsh-fast-syntax-highlighting 信息 To activate the syntax highlighting, add the following at the end of your .zshrc: source $HOMEBREW_PREFIX/opt/zsh-fast-syntax-highlighting/share/zsh-fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:1","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"2. zsh-autosuggestions 这个插件可以根据你输入的内容,给出自动补全的建议。 zsh-autosuggestions https://github.com/zsh-users/zsh-autosuggestions brew install zsh-autosuggestions 信息 To activate the autosuggestions, add the following at the end of your .zshrc: source $HOMEBREW_PREFIX/share/zsh-autosuggestions/zsh-autosuggestions.zsh You will also need to restart your terminal for this change to take effect. ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:2","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"3. zsh-autocomplete 这个插件同样用于自动补全。 zsh-autocomplete https://github.com/marlonrichert/zsh-autocomplete brew install zsh-autocomplete 信息 Add at or near the top of your .zshrc file (before any calls to compdef): source $HOMEBREW_PREFIX/share/zsh-autocomplete/zsh-autocomplete.plugin.zsh Remove any calls to compinit from your .zshrc file. If you’re using Ubuntu, add to your .zshenv file: skip_global_compinit=1 Then restart your shell. ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:3","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"4. zsh-autopair 这个插件可以自动配对括号、引号等。 zsh-autopair https://github.com/hlissner/zsh-autopair brew install zsh-autopair 信息 To activate autopair, add the following at the end of your .zshrc: source $HOMEBREW_PREFIX/share/zsh-autopair/autopair.zsh You will also need to restart your terminal for this change to take effect. ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:4","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"5. z 这个插件可以快速跳转到你最常访问的目录。 z https://github.com/rupa/z brew install z 信息 For Bash or Zsh, put something like this in your $HOME/.bashrc or $HOME/.zshrc: . $HOMEBREW_PREFIX/etc/profile.d/z.sh 另外,还可以在.zshrc中加入setopt autocd, 这样就可以直接输入目录名来切换到该目录了。 ","date":"2023-02-26","objectID":"/zh-cn/strengthen-macos-terminal/:2:5","tags":["macOS","命令行工具"],"title":"强化macOS终端","uri":"/zh-cn/strengthen-macos-terminal/"},{"categories":["笔记"],"content":"之前我一直把网站的图片放在七牛云的存储空间里,虽然七牛云还不错,但是https协议下的流量需要收费。所以,我就用jsDelivr和Githubc仓库搭建了一个免费的图床。 ","date":"2023-02-25","objectID":"/zh-cn/build-a-image-hosting-service-with-jsdelivr-and-github-repository/:0:0","tags":["Github","我的网站","命令行工具"],"title":"用jsDelivr和Github仓库搭建图床","uri":"/zh-cn/build-a-image-hosting-service-with-jsdelivr-and-github-repository/"},{"categories":["笔记"],"content":"方法很简单 创建一个公开的Github仓库 上传图片到仓库 得到图片的链接,比如https://cdn.jsdelivr.net/gh/user/repository/image.jpeg, user是你的Github用户名,repository是你的仓库名,image.jpeg是你上传的图片名 而且,这样还可以配合上一篇介绍的ImageMagick,可以写一个简单的脚本,自动压缩图片并上传到Github仓库,然后得到图片的链接。 ","date":"2023-02-25","objectID":"/zh-cn/build-a-image-hosting-service-with-jsdelivr-and-github-repository/:1:0","tags":["Github","我的网站","命令行工具"],"title":"用jsDelivr和Github仓库搭建图床","uri":"/zh-cn/build-a-image-hosting-service-with-jsdelivr-and-github-repository/"},{"categories":["笔记"],"content":"我找到了ImageMagick,它是一个强大的图像处理工具,可以在命令行中使用。不仅可以用于压缩图像,而且可以用于其他很多事情。 ImageMagick https://imagemagick.org/ 可以通过Homebrew安装ImageMagick:brew install imagemagick。 使用ImageMagick可以在命令行中压缩图像。例如,我有一个图像image.png,我想要压缩它,我可以使用以下命令: convert image.png -quality 80% image.png 而且,可以在压缩的同时转换图像的格式。如果我想要压缩图像并转换为JPEG格式,我可以使用以下命令: convert image.png -quality 80% image.jpg ImageMagick还有很多其他的功能,可以参照官方文档慢慢探索。 ","date":"2023-02-24","objectID":"/zh-cn/use-imagemagick-to-compress-the-image-in-the-command-line/:0:0","tags":["命令行工具"],"title":"使用ImageMagick在命令行中压缩图像","uri":"/zh-cn/use-imagemagick-to-compress-the-image-in-the-command-line/"},{"categories":["笔记"],"content":"由于我需要同时使用中文和英文输入法,经常在中英之间切换,有的时候打开了Terminal一输入却是中文。所以我找到了一个叫做 KeyboardHolder 的工具,它可以帮助我们自动切换输入法。 KeyboardHolder https://keyboardholder.leavesc.com/zh-cn/ 也可以直接用 Homebrew 安装:brew install --cask keyboardholder。 它可以设置每个app启动或者从前台切换到后台之后的输入法,比如可以设置Terminal启动之后是英文输入法。 另外,它还可以在鼠标的位置显示输入法切换的提示,这样就不需要转移焦点到菜单栏上检查输入法状态了。 信息 这个功能在macOS 14中已经内置了。 ","date":"2023-02-23","objectID":"/zh-cn/keyboardholder-automatically-switch-input-methods/:0:0","tags":["macOS"],"title":"KeyboardHolder: 自动切换输入法","uri":"/zh-cn/keyboardholder-automatically-switch-input-methods/"},{"categories":["笔记"],"content":"我在通知设置里忽然发现了这个Kerberos,这是什么? 我问了Bing,它说: 引用 您好,这是Bing。Kerberos是一种身份验证系统,可以让您在网络上安全地访问各种服务。Mac中的Kerberos是基于MIT Kerberos实现的,支持Kerberos v5和v4协议、GSSAPI、图形化认证界面和票据缓存。您可以使用命令行或者票据查看器应用来管理您的Kerberos票据。 https://uit.stanford.edu/service/ess/mac/docs/kerberos_macOS https://web.mit.edu/macdev/www/kerberos.html https://support.apple.com/zh-cn/guide/deployment/depe6a1cda64/web https://support.apple.com/en-gb/guide/deployment/depe6a1cda64/web 看来这个Kerberos是包含在macOS中的,它就位于/System/Library/CoreServices/Applications/Ticket Viewer.app,并不是恶意程序。 ","date":"2023-02-22","objectID":"/zh-cn/what-is-kerberos-in-mac/:0:0","tags":["macOS","Bing"],"title":"Mac中的Kerberos是什么?","uri":"/zh-cn/what-is-kerberos-in-mac/"},{"categories":["笔记"],"content":"通过调整Launchpad每一行和每一列的图标的数量,就可以调整图标的大小。 ","date":"2023-02-21","objectID":"/zh-cn/modify-the-icons-size-in-macos-launchpad/:0:0","tags":["macOS"],"title":"修改macOS Launchpad的图标大小","uri":"/zh-cn/modify-the-icons-size-in-macos-launchpad/"},{"categories":["笔记"],"content":"方法 在Terminal中执行以下命令: # 例如设置为8列 defaults write com.apple.dock springboard-columns -int 8 # 例如设置为6行 defaults write com.apple.dock springboard-rows -int 6 # 重置Launchpad defaults write com.apple.dock ResetLaunchPad -bool TRUE # 重启Dock killall Dock 恢复默认设置: defaults write com.apple.dock springboard-rows Default defaults write com.apple.dock springboard-columns Default defaults write com.apple.dock ResetLaunchPad -bool TRUE killall Dock ","date":"2023-02-21","objectID":"/zh-cn/modify-the-icons-size-in-macos-launchpad/:1:0","tags":["macOS"],"title":"修改macOS Launchpad的图标大小","uri":"/zh-cn/modify-the-icons-size-in-macos-launchpad/"},{"categories":["笔记"],"content":"忽然发现我的Mac上竟然有2个Edge Dev,分别是111.0.1660.13和111.0.1660.12,而且这2个都能正常启动。我希望保留最新版本的,把旧版的卸载掉。 ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:0:0","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"方法 ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:1:0","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"1 以Dev版本为例,切换目录到以下位置 cd /Applications/Microsoft\\ Edge\\ Dev.app/Contents/Frameworks/Microsoft\\ Edge\\ Framework.framework/Versions 也可以在访达中按下control + shift + G,输入要前往的位置 ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:1:1","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"2 执行ls -l,可以看到类似的输出 示例 drwxrwxr-x 14 user admin 448 Feb 11 11:32 111.0.1660.12 drwxrwxr-x 14 user admin 448 Feb 17 08:54 111.0.1660.13 lrwxrwxr-x 1 user admin 13 Feb 17 08:54 Current -\u003e 111.0.1660.13 或者在访达中点击Current,确认指向的版本 ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:1:2","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"3 使用rm -rf删除其他旧版本的,或者也可以在访达中删除 ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:1:3","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"4 最后一步,这一步同样也可以在访达中进行 cd ~/Library/Application\\ Support/Microsoft rm -rf EdgeUpdater ","date":"2023-02-19","objectID":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/:1:4","tags":["macOS","浏览器"],"title":"Mac上出现了多个版本的Edge浏览器","uri":"/zh-cn/multiple-versions-of-edge-browser-appear-on-mac/"},{"categories":["笔记"],"content":"Depay的注册和下载链接:https://depay.depay.one/web-app/register-h5?invitCode=606096\u0026lang=zh-cn,推荐码:606096。 我找到了Depay老板在v2ex上发的主题,本文的内容主要根据这个主题以及我自己的体验。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:0:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"Depay可以做什么 通过Depay可以直接用USDT充值,兑换成美元,然后用VISA和mastercard消费。 可以绑定支付宝、微信支付、美团外卖、拼多多、Paypal(国区、美区、港区)、天猫国际版等 支持Stripe商户、Google Play、Youtube Premium 、Paypal商户、美区App Store和支持非3DS卡的电商网站 支持免KYC开卡,实现完全匿名付款 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:1:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"注册和下载 信息 Depay的注册和下载链接:https://depay.depay.one/web-app/register-h5?invitCode=606096\u0026lang=zh-cn,推荐码:606096。 或者用手机扫描下方海报上的二维码: 安卓直接下载APK安装;iOS可以在非中国区下载,也可以下载测试版。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:2:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"申请虚拟卡 进入Depay App后,点击申请卡,一开始可以选择标准卡和Lite卡,Lite卡不需要KYC。现在一共有5种卡(Lite、标准、高级、白金、黑金),区别主要在于开卡费、月费和充值手续费不同,标准卡的开卡费是0,具体的区别可以看官网。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:3:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"充币、兑换美元、充值和激活 Depay目前支持充USDT(TRC20),一次至少5USDT。充币之后可以将USDT实时兑换成美元。 技巧 激活虚拟卡需要往卡里充值美元,充值会有一定比例的手续费,标准卡的手续费每次最少1美元,所以不要频繁地小额充值。 激活之后就可以查看卡号和CVV安全码了。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:4:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"黑金卡 目前只要邀请20个人开卡,可以找管理员升级黑金卡。黑金卡没有月费,充值手续费也比较低。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:5:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"Depay是否安全? 警告 Depay是一个刚成立的英国小公司,不放心的话最好不要充太多的钱,够用就行。 ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:6:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"客服 官网:https://depay.one/ 邮箱:support@depay.one Telegram群:https://t.me/depay_visa Twitter:https://twitter.com/Depay_CN ","date":"2023-02-18","objectID":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/:7:0","tags":["境外支付"],"title":"Depay: 使用USDT消费的虚拟美元信用卡","uri":"/zh-cn/depay-a-virtual-dollar-credit-card-for-spending-with-usdt/"},{"categories":["笔记"],"content":"自从2月11日加入了waitlist,今天终于收到邮件,我可以使用新Bing了。 Bug 迫不及待地打开了Edge Dev,进入CHAT,但是我很快就发现无法在输入框里正常地输入所有的字符。我又在Safari上试了试,发现完全正常,所以很可能是Edge Dev存在一些问题。 之后和新Bing进行了几轮对话,感觉它似乎有点缺少对话的积极性,经常会让我换个话题。而且,没几分钟就出现了“This has been lovely, but you’ve reached your daily limit. Chat again tomorrow?”的提示。 不得不说,新Bing一个很有用的功能是它可以从我们正在阅读的网页和文件中获取信息。我测试了一下,我用Edge Dev打开了一个本地的PDF文件,点击Discover按钮进行Chat,新Bing可以总结这个文件中的要点。另外,它也可以在Discover中很方便地生成一些文字。 根据我的体验,我认为新Bing还是很不错的,非常期待之后的正式版本。 ","date":"2023-02-18","objectID":"/zh-cn/you-re-in-welcome-to-the-new-bing/:0:0","tags":["Bing","ChatGPT","浏览器"],"title":"新Bing体验","uri":"/zh-cn/you-re-in-welcome-to-the-new-bing/"},{"categories":["日记"],"content":"美味的奶油水果蛋糕! 在去年两个蛋糕的基础上,这一次主要加入了奶油和水果,还放了几个奥利奥,味道更有层次感了。唯一的缺点是蛋糕胚不够香甜松软,吃着有点像馒头😂。 ","date":"2023-02-15","objectID":"/zh-cn/creamy-fruit-cake-an-upgraded-version/:0:0","tags":["蛋糕"],"title":"奶油水果蛋糕——升级版🍰","uri":"/zh-cn/creamy-fruit-cake-an-upgraded-version/"},{"categories":["笔记"],"content":"Visited Lite是一个自定义已访问链接的颜色的userscript,而Color Links是具有相似功能的浏览器扩展。 前几天微软公司推出了结合GPT技术的新版Bing和Edge浏览器,我看了网上对它们的介绍,感觉真的很不错。而且去年我也第一时间体验了ChatGPT,所以这一次我非常期待新版Bing和Edge,申请加入了waitlist。 问题 在使用Bing的过程中,我忽然发现了一个问题,在Bing的搜索结果中,已访问的链接和未访问的链接都是紫色的,这样就很难区分哪些链接是已访问的,哪些链接是未访问的。而我之前一直使用Google,未访问的链接是蓝色的,访问过的链接是紫色的。我在Bing的设置中并没有找到相关的设置项,不知道问题出在了哪里,所以我想寻找一些userscript或者浏览器扩展来解决这个问题。 ","date":"2023-02-13","objectID":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/:0:0","tags":["Bing","ChatGPT","浏览器","Userscripts","Chrome扩展"],"title":"Visited Lite \u0026 Color Links: 自定义已访问链接的颜色","uri":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/"},{"categories":["笔记"],"content":"Visited Lite 于是我找到了Visited Lite,它可以自定义所有网站的已访问链接的颜色,而不仅仅是Bing的。我在Edge的Tampermonkey扩展中安装了这个userscript,Visited Lite用醒目的颜色标记了所有已访问的链接。不过有的网页可能并不需要这个功能,可以在Tampermonkey扩展中排除它们。 ","date":"2023-02-13","objectID":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/:1:0","tags":["Bing","ChatGPT","浏览器","Userscripts","Chrome扩展"],"title":"Visited Lite \u0026 Color Links: 自定义已访问链接的颜色","uri":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/"},{"categories":["笔记"],"content":"Color Links 之后,我又在chrome web store中找到了Color Links。与Visited Lite的不同主要在于,Color Links需要为每一个网站手动开启标记颜色的功能。 ","date":"2023-02-13","objectID":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/:2:0","tags":["Bing","ChatGPT","浏览器","Userscripts","Chrome扩展"],"title":"Visited Lite \u0026 Color Links: 自定义已访问链接的颜色","uri":"/zh-cn/visited-lite-script-that-mark-all-visited-links-as-custom-color/"},{"categories":["笔记"],"content":"昨天用了一下texliveonfly宏包,直接出现了env: python: No Such File or Directory。 我试着执行了一下python,结果弹出了一个Xcode Command Line Tools的提示,说要下载一些东西,然后它下载了Python3.9,而我之前已经有了Python3.8🙃。 我试着用ln建立软连接,但是没有用。 成功 我想既然texliveonfly是用Python写的,我可以直接编辑它。于是我找到了/Library/TeX/texbin/texliveonfly,然后将这个文件第一行的#!/usr/bin/env python改成了#!/usr/bin/env python3,这样就解决了。 ","date":"2023-01-23","objectID":"/zh-cn/texliveonfly-env-python-no-such-file-or-directory/:0:0","tags":["LaTeX","Python","macOS"],"title":"texliveonfly, env: python: No Such File or Directory","uri":"/zh-cn/texliveonfly-env-python-no-such-file-or-directory/"},{"categories":["笔记"],"content":"LeetCode 66.Plus One,一道简单的题。主要是想练习一下Java,好长时间没写Java了。 我的思路是从后往前遍历,如果当前位是9,那么就进位,如果不是9,那么就加1,然后返回结果。如果最后一位是9,那么就需要在最前面加一个1,这个时候就需要新建一个数组,然后把原来的数组复制过去。 class Solution { public int[] plusOne(int[] digits) { int end = digits.length - 1; int[] result = new int[end + 1]; boolean carry = false; result[end] = digits[end] + 1; if (result[end] == 10) { result[end] = 0; carry = true; } for (int i = end - 1; i \u003e= 0; --i) { result[i] = digits[i]; if (carry) { result[i] += 1; if (result[i] == 10) { result[i] = 0; carry = true; } else { carry = false; } } } if (carry) { int[] tmp = result; result = new int[end + 2]; result[0] = 1; for (int i = 1; i \u003c end + 2; ++i) { result[i] = tmp[i - 1]; } } return result; } } ","date":"2023-01-22","objectID":"/zh-cn/leetcode-66/:0:0","tags":["算法","Java","LeetCode"],"title":"LeetCode 66","uri":"/zh-cn/leetcode-66/"},{"categories":["笔记"],"content":"今天我爸爸开车送我到一个地方,我下车之后走了3分钟,忽然发现我的手机不见了…… 我赶紧返回原路找我的手机,但是没有找到。最后和路边的交警同志借了手机给我爸爸打了一个电话,才确认我的手机落在了车里。 虽然在Find My中已经设置了离开iPhone时在Apple Watch上发出通知,但是似乎这个功能需要在一个比较远的距离才能生效。 所以我就找到了Phone Buddy: Phone Buddy https://apps.apple.com/us/app/phone-buddy-phone-lost-alert/id1451559391 售价$4.99,我用支付宝购买美区App Store礼品卡的方法充值购买了这个App。 注意 下载Phone Buddy之后,在Apple Watch上开启Lost Phone Alert,当Apple Watch断开了和iPhone之间的蓝牙连接时就会在Apple Watch上发出警报。并且还可以有基于距离的Distance Alert,当Apple Watch和iPhone之间的蓝牙信号强度随着距离的增加衰减到设定的阈值以下时也可以发出警报,这样可以在完全断开蓝牙连接之前多一次警报。同样的,还可以设置在Apple Watch断开连接后在iPhone上发出警报,可以防止丢失或遗忘Apple Watch。 唯一不足的是,这个App会缩短Apple Watch的续航时间,不过比起丢失了iPhone,这个代价是可以接受的。 ","date":"2023-01-18","objectID":"/zh-cn/use-phone-buddy-on-apple-watch-to-prevent-forgotten-iphone/:0:0","tags":["Apple Watch","iPhone"],"title":"在Apple Watch上使用Phone Buddy防止忘带iPhone","uri":"/zh-cn/use-phone-buddy-on-apple-watch-to-prevent-forgotten-iphone/"},{"categories":["日记"],"content":"在国科大的第一个学期很快就过去了,感觉这个学期的经历很丰富。 我于2022年8月17日到达了北京市怀柔区怀北镇,当天下午我先去参观了一下雁栖湖 。雁栖湖是一个很大的湖,湖边有很多树🌳,湖上有很多船🛶,湖边有很多人。湖边的山上还有一条不知道通向哪里的步道,我在这条路上走了很久,感觉很好,可惜由于施工道路中断了🚧,后来我才知道这条路和国科大的观景台是连通的。我在湖边的山上看到了很多鸟🐦,它们在湖上飞在湖边的树上叫。 雁栖湖 在雁栖湖旁边村里的农家乐住了一晚上后,我第二天一早就前往了国科大。虽然那天下了一整天雨🌧️,我的衣服和鞋子都湿透了,但是刚到学校,感觉一切都是那么新鲜,心情还是很不错的🙂。 国科大雁栖湖校区西区荷花池 夕阳 山上的长城 伴随着两天一次的核酸,这个学期就这样开始了。国科大的课程的质量和难度确实要比北方工大的高,感觉收获也要更多一些。除了上课,我也经常在学校里骑着自行车🚲转一转,看看校园的景色。因为学校背靠着大山和雁栖湖,所以学校的生态环境很不错,经常有小动物🐱出没,据说还有野猪🐗和蛇🐍这样的猛兽。 秋天的山 黄叶 阳光下的树 山楂树 雁栖湖北路 不得不说,国科大在山上种了好多果树,秋天丰收之后,我们吃到了不少免费的水果。 梨 10月15日一大早,我们整个宿舍突然被通知要就地隔离了,还给我们每个人送过来丰盛的早餐和一大桶水。还没吃完,又接到通知,隔离结束了,真的是莫名其妙😅。 早餐 到了11月底,学校变得不是那么平静。由于进入冬季奥密克戎疫情又变得严重,当时北京许多高校都开始安排学生返乡。刚开始国科大还是要求学生必须在校完成所有考试,后来在11月29日终于允许学生返乡。一时间各种小道消息在学校传播:有人说学校里有一名核酸检测呈阳性的学生,所有学生都不能回家了,可能都要隔离在宿舍里;有人说出校之后进入北京市区,在火车站等一些地方会有人搜查手机……有点人心惶惶的感觉。 由于我家所在的城市正在封城,不知道什么时候才结束,所以我决定继续留在学校。据说如果校园内出现了疫情,可能食堂就没办法正常做饭了,我就赶紧囤了一些食物。那时好多快递都中断了,京东快递也变得很慢。 在那几天,大部分学生都离开学校回家了,学校安静了下来。在12月5日前后,防疫政策突然出现了重大变化,终于结束了两天一次的核酸检测。但是这时学校开始出现了感染者,我也准备了2盒复方氨酚烷胺胶囊。 12月19日早晨起床后,我感觉我的嗓子变干了还有点疼,还有很多鼻涕,我应该是感染了。当天晚上,我的运动手环一直警告我的心脏🫀跳得很快,在120BMP左右,我静静坐着可以听到心跳的声音。我非常害怕,躺到了床上,浑身发热,心率还是降不下来。伴随着我的心跳声,后来我终于睡着了。第二天早上查看记录,心率慢慢降到了90BMP左右,这很不正常。 我也不知道这是怎么了,自2019年出现新冠病毒以来,我一直不知道新冠病毒会对心脏造成影响。我在网上搜索了一下,也有很多人遇到了和我相同的情况,据说这是病毒性心肌炎。于是我赶紧下单了辅酶$Q_{10}$胶囊。 12月22日,我去领取了一个抗原检测试剂,我确实感染新冠病毒🦠了。 抗原检测呈阳性 过了一周,我的症状逐渐消失了,只是还是有一些咳嗽,而且心率还是偏快。12月27日,我又领取了一份抗原检测试剂,这一次是阴性。 又过了一个多星期,我完成了所有的考试,我的心率还是不正常,我决定去怀柔医院检查一下。我做了心电图、心脏彩超、胸部CT扫描以及多项血液检测,检测结果并没有出现什么异常,医生说我的情况应该是新冠后遗症而不是心肌炎,需要通过一个较长的时间来慢慢恢复。 现在已经是2023了,只希望能够尽快恢复疫情前的生活🙏。 ","date":"2023-01-17","objectID":"/zh-cn/first-semester-at-ucas/:0:0","tags":["转悠","UCAS"],"title":"在国科大的第一个学期","uri":"/zh-cn/first-semester-at-ucas/"},{"categories":["笔记"],"content":"在macOS中,如果在~执行cd documents是可以切换到Documents目录的,但是无法用Tab补全。 解决的方法是在~/.zshrc中添加如下代码: autoload -Uz compinit \u0026\u0026 compinit zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' 重新打开终端就可以见到效果了。 ","date":"2022-12-09","objectID":"/zh-cn/zsh-tab-completion-with-case-insensitivity/:0:0","tags":["命令行工具","macOS"],"title":"zsh: Tab补全大小写不敏感","uri":"/zh-cn/zsh-tab-completion-with-case-insensitivity/"},{"categories":["笔记"],"content":"只要5分钟,把微信公众号变成机器人🤖。 之前注册了一个微信公众号,但是一直闲置着,于是我就想把它变成机器人,发挥一点点作用。 ","date":"2022-11-16","objectID":"/zh-cn/turn-idle-wechat-official-account-into-a-robot/:0:0","tags":["微信"],"title":"把闲置微信公众号变成机器人","uri":"/zh-cn/turn-idle-wechat-official-account-into-a-robot/"},{"categories":["笔记"],"content":"方法 用微信扫码登录微信对话开放平台 在机器人创建页面设置机器人的名称,完成机器人创建 根据需要开启机器人的“预置技能”,比如英语翻译、天气、股票、新闻、笑话等 在“应用绑定”中绑定微信公众号 在“上线发布”中发布 是不是很简单呢? ","date":"2022-11-16","objectID":"/zh-cn/turn-idle-wechat-official-account-into-a-robot/:1:0","tags":["微信"],"title":"把闲置微信公众号变成机器人","uri":"/zh-cn/turn-idle-wechat-official-account-into-a-robot/"},{"categories":["笔记"],"content":"由于笔记本电脑使用锂电池,长期连接电源使用会导致电量始终处于一个较高的百分比,这样会缩短电池的寿命。因此,让电量保持在20%至80%之间能够延缓电池的衰减。 对于MacBook,我找到了一个软件可以解决这个问题—— AlDente https://github.com/davidwernhart/AlDente-Charge-Limiter 可以在Github中直接下载,也可以使用Homebrew,brew install --cask aldente。 启动AlDente后这个软件出现在菜单栏中,可以很简单地控制MacBook的最大充电百分比。之后就可以观察到已经连接电源,但是电池没有在充电。 ","date":"2022-10-11","objectID":"/zh-cn/aldente-limit-macbook-maximum-charging-percentage/:0:0","tags":["macOS"],"title":"AlDente:限制MacBook最大充电百分比","uri":"/zh-cn/aldente-limit-macbook-maximum-charging-percentage/"},{"categories":["笔记"],"content":"总有一些软件的图标和macOS的不适应,iconsur可以为它们生成圆角矩形的图标,美化我们的macOS。 iconsur的Github主页: iconsur https://github.com/rikumi/iconsur 可以在Releases中下载。也可以用Homebrew:brew install iconsur,或者是npm:npm install -g iconsur。 iconsur在App Store中为软件寻找最相似的iOS app,把这个软件的图标替换成iOS app的图标。例如: sudo iconsur set /Applications/Microsoft\\ Word.app/ 另外,iconsur也可以为软件在本地生成图标。例如: sudo iconsur set /Applications/Visual\\ Studio\\ Code.app/ -l 其他用法可以参照Github或是执行iconsur help。 ","date":"2022-09-17","objectID":"/zh-cn/iconsur-generate-rounded-rectangle-icons-for-macos-third-party-software/:0:0","tags":["macOS","命令行工具"],"title":"iconsur:为macOS第三方软件生成圆角矩形图标","uri":"/zh-cn/iconsur-generate-rounded-rectangle-icons-for-macos-third-party-software/"},{"categories":["日记"],"content":"经过了半个多月的训练,顺利拿到驾照!感谢每一位教练的耐心指导! 驾照 我还在驾校转了转,驾校建在一个山头上,视野很开阔。 太阳 驾校竟然还养了几只小马。 小马 鹅和鸭子 ","date":"2022-08-13","objectID":"/zh-cn/i-got-my-driving-license/:0:0","tags":["转悠"],"title":"拿到驾照了🚘","uri":"/zh-cn/i-got-my-driving-license/"},{"categories":["项目"],"content":"NCUT-Pot是我的毕业设计,是一个蜜罐。 这个蜜罐支持Telnet和SSH两种协议,模拟Linux系统,将黑客的数据存储在SQL数据库中。此外,它还通过短信和电子邮件向用户发送警报。用户可以自定义蜜罐的命令和目录。 信息 关于NCUT-Pot的更多细节请访问https://github.com/kayak4665664/FF-Pot(现已改名为FF-Pot)。 ","date":"2022-07-14","objectID":"/zh-cn/ncut-pot/:0:0","tags":["毕业设计","NCUT","Github"],"title":"NCUT-Pot","uri":"/zh-cn/ncut-pot/"},{"categories":["日记"],"content":"自从毕设结束了,我就天天盼着录取通知书,终于等到了! 录取通知书 哈哈,校园卡也到了。虽然我非常期待国科大的新学期,不过8月18日就得去报到,我又要去驾校学车,感觉我的假期还没有开始就要结束了🥹 学位证 毕业证 我的毕业证和学位证也回来了,怀念在北方工大那些快乐的日子。 ","date":"2022-07-13","objectID":"/zh-cn/august-18-a-new-beginning/:0:0","tags":["NCUT","UCAS"],"title":"8月18日,新的开始","uri":"/zh-cn/august-18-a-new-beginning/"},{"categories":["日记"],"content":"毕业设计终于要进入尾声了,6月9日下午最终答辩! 现在我已经完成了毕业设计的大部分工作,所以这两个星期过得还是比较轻松的。但是我现在被隔离了,每天只能呆在屋子里🙃,今天是第4天了。 5月27日中午,我和往常一样去食堂吃了午餐,刚回到宿舍,突然就收到了学校要求毕业生尽快离校的通知。我马上就意识到,这将是我在北方工业大学最后的几天了。 离校通知 我冷静了一下,立刻开始计划离校前必须做的事情。首先要考虑的就是我的行李,还好学校承诺是可以免费邮寄的,不然邮寄那么多东西的费用我是有点负担不起的。然而,我并没有用来打包的纸箱子。我问了问辅导员,他只说晚些时候会发放。我感觉他的回答太模糊了,我决定自己先去买几个纸箱子。我去学校快递点找到了那里的老板,他告诉我,我们学院之前找他拿了一百多个纸箱子。我估计了一下,一个学生应该只能领取到1个纸箱子。所以,我和老板买了4个大纸箱子,花了45元。 有了纸箱子,我就回宿舍打包行李了。同时,我还得和我家所在的社区报备。我和社区的工作人员联系了一下,她告诉我,我将会被集中隔离7天,再居家隔离7天。我感觉这并不合理,我在学校期间接受了几十次核酸检测,从来都是阴性的,而且学校一直是封闭的,校外的人进不来,校内的人出不去,我认为我不应该被集中隔离7天。而且据我所知,有一些地方对于从北京返回的学生也是不需要集中隔离的。我向她解释了一下,但是没有用。好在集中隔离是免费的,否则又得花不少钱了。那几天,我看到有新闻说有些大学生返乡后被集中隔离,一天要500元。 打包完行李后,我感觉有点热,我发现我的头发有点长了。一想到我马上还要隔离半个月,我就去理发店把头发剪短了。 晚上,辅导员终于通知可以去领纸箱了,我领到1个纸箱和1个麻袋。再加上我买的4个大纸箱,刚刚好。 5月28日上午,我去超市买了一只记号笔,我得在箱子上标记我的邮寄地址。我走进宿舍楼,和我比较熟的一个宿管阿姨告诉我,现在可以开始到快递点邮寄行李了,让我赶紧去吧。考虑到我要把4个纸箱和1个麻袋从宿舍搬到快递点,单靠两只手是不太容易的,所以我到快递点和老板借了一个平板车。我回到宿舍把这5件东西都标记了我的信息,全放到平板车上去了,一下子都运到了快递点。 由于学校要求毕业生离校的通知比较仓促,快递点老板坦白说他们也不知道怎么处理这么多人的行李,而整个快递点只有2个人。当我推着平板车过去时,我看到快递点外面已经堆了不少箱子了。我有点担心这么多箱子最后会被搞混,所以我请求老板先给我的行李贴上快递单,这样我也方便查快递。等我处理好行李,已经12点多了,到了食堂,煮了一大盘饺子。不得不说,食堂的饺子真的太好吃了,里面肉是真的多。 饺子 晚上,我查到我的快递已经发出去了,感觉效率还是很高的。 5月29日下午,快递点老板突然给我打电话。我担心的事情发生了,老板说他们打错了快递单,把别人的一箱行李邮寄到我的地址去了,我的一箱还在他那里😱。我赶紧又跑到了快递点,我的一个箱子果然还躺在货架子上。 5月30日,这一天没有什么特别的事情,都已经处理好了。 5月31日,闹钟还没响我就已经醒了,这是我在学校的最后一天。起床吃早餐。之后,开始打包铺盖,收拾行李,我得带足生活用品,晚上就要开始隔离了。我把铺盖打包进了学院发的小纸箱里,刚好能装进去。我抱着箱子到了快递点,门开着却没有人。等了半小时老板终于来了。 中午,到食堂吃午餐,这是我在学校的最后一顿饭。 我回到了宿舍,躺在了床垫上。这个床垫太大不能邮寄,就留在这里了。 下午快3点时,我整理好了行李箱,关上了宿舍的窗户,拉下电闸,最后看了宿舍一眼,锁上了门。我下楼找到宿管阿姨,退了钥匙。 就这样,我就离开了学校,可能永远不会回去了。 NCUT 上面这张照片是31日的。30日下午我就看见有人在摆弄这几个牌子,不过当时上面还是2021😂。 出了学校,我坐上了地铁去火车站。 晚上8点,火车到站了。很快,开始核查旅客的出发地,我从北京出发,需要被送到隔离酒店。 我填写了一个文件后,我的身份证就被扣押了。他们说会还给我的。我不知道他们是什么人,我认为他们这种行为是违反《中华人民共和国居民身份证法》的。之后就是漫长的等待,活生生站了2个多小时,没有人来处理。总的来说,这是一段不愉快的经历。 晚上10点多,终于有人来接应了,终于把身份证还给我了。之后进行了一次核酸检测。 一行人坐上了车,11点左右终于到达了隔离酒店。又是漫长的等待,我已经很困了,浑身疲劳。再一次核酸检测后,我终于进入了房间。整理好之后,已经将近6月1日的1点了。 有一说一,隔离酒店的环境还是不错的,吃饭喝水也能保证,这4天来我过得还可以。 还有3天集中隔离就要结束了,开始7天的居家隔离,其中6月9日我将进行毕设的答辩。 时间过得太快了,我在3月15日回到学校时,北京还在下雪。一转眼,我突然又回家了。我的4年大学生活马上也要结束了,我会永远记得在北方工业大学的4年。 ","date":"2022-06-04","objectID":"/zh-cn/next-week-i-will-have-my-graduation-project-defense/:0:0","tags":["毕业设计","NCUT"],"title":"下周毕设答辩","uri":"/zh-cn/next-week-i-will-have-my-graduation-project-defense/"},{"categories":["笔记"],"content":"今天知道了一种直接用支付宝购买美区App Store礼品卡的方法,以后不用再去淘宝和闲鱼上买了! ","date":"2022-05-21","objectID":"/zh-cn/buy-us-app-store-gift-cards-with-alipay/:0:0","tags":["境外支付"],"title":"用支付宝购买美区App Store礼品卡","uri":"/zh-cn/buy-us-app-store-gift-cards-with-alipay/"},{"categories":["笔记"],"content":"方法 打开支付宝 首页左上角切换定位到旧金山 搜索“出境”,在搜索结果中选择“出境” 选择“折扣礼卡” 滑到页面最下方,点击“更多大牌折扣礼卡” 搜索“App Store” 输入正确的邮箱账号 输入要购买的数值,至少$2,“Purchase card” ","date":"2022-05-21","objectID":"/zh-cn/buy-us-app-store-gift-cards-with-alipay/:1:0","tags":["境外支付"],"title":"用支付宝购买美区App Store礼品卡","uri":"/zh-cn/buy-us-app-store-gift-cards-with-alipay/"},{"categories":["日记"],"content":"全世界无产者,联合起来! 共同捍卫劳动者的权利,为一个更公平更美好的世界而奋斗。 ","date":"2022-04-30","objectID":"/zh-cn/international-workers-day/:0:0","tags":[],"title":"庆祝五一国际劳动节","uri":"/zh-cn/international-workers-day/"},{"categories":["日记"],"content":"今天通过腾讯会议参加了开题答辩。 原计划下午一点半开始,不知道为啥等到了两点😶。今天下午这一场一共有24名学生,3位评委老师。我排在第12号,等到了四点终于轮到我了。总体还是比较顺利的,不过有一位老师正好是研究计算机网络的,而我的课题涉及到了不少网络的东西,被抓着问了几个问题。 答辩之后,老师没说可以退出,正好继续待在会议里面看别人答辩。一位保研到计算所的未透露名字的同学,他的毕设是和华为公司合作的,他说他的毕设成果要打败他导师之前的工作,他立志也要投一篇顶会👍。 这样优秀的同学激励我去做好我自己的工作,继续努力吧👍。 ","date":"2022-03-09","objectID":"/zh-cn/todays-thesis-proposal/:0:0","tags":["毕业设计","NCUT"],"title":"今日开题答辩","uri":"/zh-cn/todays-thesis-proposal/"},{"categories":["日记"],"content":"感觉面粉放少了,没上次的好吃,还不错吧。 ","date":"2022-03-04","objectID":"/zh-cn/made-a-cake-again/:0:0","tags":["蛋糕"],"title":"又做了个蛋糕🍰","uri":"/zh-cn/made-a-cake-again/"},{"categories":["笔记"],"content":"https://cdn.jsdelivr.net/gh/kayak4665664/My-images 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例: 输入:height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1] 输出:6 解释:上面是由数组 [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 刚开始想用stack做,不过感觉不太好。然后我就直接上下一层一层算,但是Time Limit Exceeded了: class Solution { public: int trap(vector\u003cint\u003e\u0026 height) { int ans = 0; unordered_map\u003cint, vector\u003cint\u003e\u003e index; for (int i = 0; i \u003c height.size(); ++i) { for (int j = 1; j \u003c= height[i]; ++j) index[j].push_back(i); } for (auto p : index) { auto v = p.second; for (int i = 1; i \u003c v.size(); ++i) ans += v[i] - v[i - 1] - 1; } return ans; } }; 看了看参考答案,主要思路是左右围起来并且求水平面高度: class Solution { public: int trap(vector\u003cint\u003e\u0026 height) { int ans = 0, l = 0, r = height.size() - 1, level = 0; while (l \u003c r) { int lower = (height[l] \u003e height[r] ? height[r--] : height[l++]); level = max(lower, level); ans += level - lower; } return ans; } }; 这道题解法应该挺多的。 ","date":"2022-02-18","objectID":"/zh-cn/leetcode-42/:0:0","tags":["算法","C++","LeetCode"],"title":"LeetCode 42","uri":"/zh-cn/leetcode-42/"},{"categories":["日记"],"content":"前几天去平遥古城转了转,整个古城基本上保存了明清时期的原貌。站在城墙上眺望,非常壮观。小吃很多,我最喜欢平遥牛肉和碗托! ","date":"2022-02-13","objectID":"/zh-cn/pingyao-ancient-city/:0:0","tags":["转悠"],"title":"平遥古城","uri":"/zh-cn/pingyao-ancient-city/"},{"categories":["笔记"],"content":"一个双向链表的C++模版。 #include \u003ciostream\u003e using namespace std; struct ListNode { int val; ListNode *next, *prior; ListNode() : val(0), next(nullptr), prior(nullptr) {} ListNode(int v) : val(v), next(nullptr), prior(nullptr) {} ListNode(int v, ListNode *next, ListNode *prior) : val(v), next(next), prior(prior) {} }; ListNode *insert(ListNode *p, int val) { ListNode *n = new ListNode; n-\u003eval = val; n-\u003enext = p-\u003enext; p-\u003enext = n; n-\u003eprior = p; if (n-\u003enext != nullptr) n-\u003enext-\u003eprior = n; return n; } void erase(ListNode *p) { p-\u003eprior-\u003enext = p-\u003enext; if (p-\u003enext != nullptr) p-\u003enext-\u003eprior = p-\u003eprior; delete p; } void print(ListNode *p) { if (p != nullptr) { cout \u003c\u003c p-\u003eval; p = p-\u003enext; } while (p != nullptr) { cout \u003c\u003c \" -\u003e \" \u003c\u003c p-\u003eval; p = p-\u003enext; } cout \u003c\u003c endl; } int main() { ListNode *front = new ListNode(1); ListNode *n = insert(insert(insert(front, 2), 4)-\u003eprior, 3); print(front); // 1 -\u003e 2 -\u003e 3 -\u003e 4 erase(n); print(front); // 1 -\u003e 2 -\u003e 4 return 0; } LeetCode 21. Merge Two Sorted Lists class Solution { public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { if (list1 == nullptr \u0026\u0026 list2 == nullptr) return nullptr; else if (list1 == nullptr) return list2; else if (list2 == nullptr) return list1; else { ListNode *front, *p, *p1, *p2; if (list1-\u003eval \u003c= list2-\u003eval) { front = list1; p1 = list1-\u003enext; p2 = list2; } else { front = list2; p1 = list1; p2 = list2-\u003enext; } p = front; while (p1 != nullptr \u0026\u0026 p2 != nullptr) { if (p1-\u003eval \u003c= p2-\u003eval) { p-\u003enext = p1; p1 = p1-\u003enext; } else { p-\u003enext = p2; p2 = p2-\u003enext; } p = p-\u003enext; } if (p1 == nullptr) p-\u003enext = p2; else p-\u003enext = p1; return front; } } }; LeetCode 23. Merge k Sorted Lists 直接用这个方法导致Time Limit Exceeded, class Solution { public: ListNode *mergeKLists(vector\u003cListNode *\u003e \u0026lists) { int flag = 0, min = 0x3f3f3f; ListNode *front, *p, *p1; unordered_map\u003cListNode *, ListNode *\u003e ptr; vector\u003cListNode *\u003e ps; for (auto list : lists) { if (list != nullptr) { flag = 1; ptr[list] = list; if (list-\u003eval \u003c min) { min = list-\u003eval; front = list; } } } if (!lists.size() || !flag) return nullptr; else { ptr[front] = ptr[front]-\u003enext; p = front; while (true) { flag = 0, min = 0x3f3f3f; for (auto list : lists) { if (ptr[list] != nullptr) { flag = 1; if (ptr[list]-\u003eval \u003c min) { min = ptr[list]-\u003eval; p1 = list; } } } if (!flag) break; p-\u003enext = ptr[p1]; p = p-\u003enext; ptr[p1] = ptr[p1]-\u003enext; } return front; } } }; 用优先队列就可以通过了。 class Solution { public: ListNode *mergeKLists(vector\u003cListNode *\u003e \u0026lists) { ListNode *front, *p; auto cmp = [](ListNode *a, ListNode *b) { return a-\u003eval \u003e= b-\u003eval; }; // ptr.top() is minimal. priority_queue\u003cListNode *, vector\u003cListNode *\u003e, decltype(cmp)\u003e ptr(cmp); for (auto list : lists) { if (list != nullptr) ptr.push(list); } if (!lists.size() || ptr.empty()) return nullptr; else { front = ptr.top(); ptr.pop(); if (front-\u003enext != nullptr) ptr.push(front-\u003enext); p = front; while (!ptr.empty()) { p-\u003enext = ptr.top(); ptr.pop(); p = p-\u003enext; if (p-\u003enext != nullptr) ptr.push(p-\u003enext); } return front; } } }; ","date":"2022-01-31","objectID":"/zh-cn/linked-list/:0:0","tags":["链表","优先队列","数据结构","C++","LeetCode"],"title":"链表","uri":"/zh-cn/linked-list/"},{"categories":["笔记"],"content":"这是二分查找算法的一个C++模版,以及C++标准模版库\u003calgorithm\u003e头文件中二分查找函数std::lower_bound和std::upper_bound的简单应用。 #include \u003calgorithm\u003e #include \u003ciostream\u003e using namespace std; int nums[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int binary_search(int left, int right, int key) { int pos = -1, mid; while (left \u003c= right) { mid = left + (right - left) / 2; if (key \u003e nums[mid]) left = mid + 1; else if (key \u003c nums[mid]) right = mid - 1; else { pos = mid; break; } } return pos; } int main() { cout \u003c\u003c binary_search(0, 9, 3) \u003c\u003c endl; // 2 cout \u003c\u003c lower_bound(nums, nums + 10, 3) - nums \u003c\u003c endl; // 2, \u003e= 3 cout \u003c\u003c upper_bound(nums, nums + 10, 3) - nums \u003c\u003c endl; // 3, \u003e 3 return 0; } 用这个模版做了一道LeetCode的34. Find First and Last Position of Element in Sorted Array。 class Solution { public: vector\u003cint\u003e searchRange(vector\u003cint\u003e\u0026 nums, int target) { if (!nums.size()) return vector\u003cint\u003e{-1, -1}; else { int pos = binary_search(nums, 0, nums.size() - 1, target); if (pos == -1) return vector\u003cint\u003e{-1, -1}; else { int left = pos - 1, right = pos + 1, size = nums.size(); while (left \u003e= 0 \u0026\u0026 nums[left] == target) --left; while (right \u003c size \u0026\u0026 nums[right] == target) ++right; return vector\u003cint\u003e{left + 1, right - 1}; } } } int binary_search(vector\u003cint\u003e nums, int left, int right, int key) { int pos = -1, mid; while (left \u003c= right) { mid = left + (right - left) / 2; if (key \u003e nums[mid]) left = mid + 1; else if (key \u003c nums[mid]) right = mid - 1; else { pos = mid; break; } } return pos; } }; ","date":"2022-01-29","objectID":"/zh-cn/binary-search/:0:0","tags":["查找","算法","C++","LeetCode"],"title":"二分查找","uri":"/zh-cn/binary-search/"},{"categories":["日记"],"content":"真好吃! ","date":"2022-01-18","objectID":"/zh-cn/made-a-cake/:0:0","tags":["蛋糕"],"title":"做了个蛋糕🍰","uri":"/zh-cn/made-a-cake/"},{"categories":["日记"],"content":"今天出来走了走,拍了一些照片。蓝蓝的天,感觉真不错! 人民英雄纪念碑(北面) 人民英雄纪念碑(南面) 毛主席纪念堂 人民大会堂 新华门 ","date":"2021-12-27","objectID":"/zh-cn/i-went-to-tiananmen-today/:0:0","tags":["转悠"],"title":"今天到天安门走了走","uri":"/zh-cn/i-went-to-tiananmen-today/"},{"categories":["笔记"],"content":"目前本站已经成型,进入日常维护阶段,现在来回顾一下它是如何建立的。网上已经有各种教程,而本文主要是我自己的经历,不会涉及那些重复的细节。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:0:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"开始 上上周看到有人用Github作免费网盘,我以前还见过有人专门建了repository来记笔记、写博客,我忽然也想有个写点东西记录自己的地方。我就查了一下如何用Github写博客,我才知道了Github Pages。简单来说它可以免费自动托管静态网页,用它做一个自己的博客是绰绰有余的。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:1:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"准备 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:2:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"域名 Github Pages是免费的,不过它的网址都长username.github.io这样,感觉不够个性化。好在它是支持自定义域名的,我决定买一个。网站还没有建起来,但我还是先买了。我听说国内买域名需要实名审核,并且审核需要好几天。我一边等待审核通过,一边建网站,这样更省时间。最后我买了kayak4665664.com。 技巧 有的域名首年注册时看起来便宜,但以后续费比.com域名还要贵。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:2:1","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"username.github.io 新建了一个repository,进行Pages设置。Github Pages使用Jekyll将纯文本转化为静态网站,所以在设置过程中它会让你选择你的Jekyll主题。我还认真地比较了一下那几个主题,选了我觉得最好看的一个。其实后面很快我就发现,这些主题过于简单,不满足我的需求。之后用git克隆repository到了本地。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:2:2","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"设计 我看了一些其他人的网站,初步确定我的网站要有评论、访问统计、站内搜索这几个功能。另外还要加入百度和谷歌分析,并且让它们收录我的网站。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:2:3","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"工具 除了Jekyll,还有很多将纯文本转化为静态网站和博客的工具,比如我现在用的Hugo。由于Github Pages默认使用Jekyll,我就选择了Jekyll。 Jekyll基于Ruby,可以用gem来安装。我使用的macOS自带一个Ruby,我就直接执行gem install jekyll bundler开始安装Jekyll、Bundler以及它们的依赖。安装一半,出现fatal error: 'ruby/config.h' file not found。谷歌了一下有人说是自带的Ruby版本太低,还有人说是Xcode CommandLineTools的问题。我直接用Homebrew安装了一个新的Ruby。安装之后设置了终端的环境变量,重新执行gem install jekyll bundler,这次安装好了。 警告 我还查了一下怎么清理之前gem install jekyll bundler时的缓存和已安装的包,结果没有找到。我只好手动卸载了那些已安装的包、删除了缓存所在的目录,感觉根本没清理干净。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:2:4","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"Jekyll ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:3:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"上手 在工作目录执行bundle exec jekyll serve,出现cannot load such file -- webrick (LoadError)。谷歌了一下,用bundle add webrick解决。 在本地预览了一下感觉没有问题,准备push到Github上用手机测试。但是出现了问题,push不上去。谷歌了一下没找到,百度了一下发现可能是proxy的问题,取消git设置的代理后解决。 用手机看了一下,网页是自动适配移动端的。这时候发现这个主题太简陋了,甚至没有分页的功能。刚开始我还准备自己实现出来,但又想想那么多功能都得一个个实现,工作量巨大,我还是找一个功能比较完整的主题吧。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:3:1","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"主题 网上有不少Jekyll主题,我最后下载了YAT。它支持不少功能,可以用Disqus和Gitment来评论。 下载之后,想要执行bundle exec jekyll serve预览一下,报错Could not find gem 'jekyll-spaceship (~\u003e 0.2)'。我通过在gem安装jekyll-spaceship时设置版本为0.2来解决。在这里我还发现安装过程卡住了,但没有报错。用Activity Monitor看到Ruby的Rcvd Bytes是一直缓慢增加的,应该是国内网络的问题。谷歌了一下,在Ruby China找到了换源的方法,换源之后成功安装。 再次执行bundle exec jekyll serve,这次可以预览新主题了。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:3:2","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"个性化 根据自己的需求来对主题进行个性化修改,如标题、图片等。我本来想用Gitment,但我发现它不能登录Github账号,看了一下它的Issues应该是停止服务了。所以只能用Disqus,我注册了Disqus账号,开启了评论功能。此外我还用了不蒜子进行网站访问量统计,只需两行代码。 之后我开始增加一些内容。在预览内容的过程中渐渐发现了一些问题,这个主题它的字体偏小,不论在浅色还是深色模式下文字与背景的对比较低,总之我感觉读起来费眼睛。然而无法在配置文件中对字体进行设置,我只能直接去挨个修改.scss文件,比较麻烦。而它的翻译功能,调用了谷歌的网页翻译接口,在国内网络下几乎无法使用,导致网页变得卡顿,我直接将源代码中翻译相关的部分删除了。除此之外,Disqus在国内网络下无法登录账号,测试了一下只能使用访客匿名评论,这也是一个缺点。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:3:3","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"放弃 个性化之后,我感觉没有问题了。这时忽然想到YAT主题还支持PlantUML、Mermaid、Mathjax、Vedio、Audio等,我应该再测试一下。我直接用作者的markdown文件进行测试,结果发现这些东西都没有正常显示出来。 我还以为是我把源代码改坏了,我直接克隆了一份作者的repository。经测试发现同样不行,看来不是我修改代码的问题。但是问题在哪我也一直没有找到,考虑到这个主题还存在其他的缺点,我选择放弃它。 我又开始找主题,这一次更加仔细。最后找到了LoveIt主题,也就是我现在用的。 这是一个基于Hugo的主题,所以Ruby就没用了,我把它卸载了。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:3:4","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"Hugo ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:4:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"上手 先用Homebrew安装Hugo,LoveIt文档中推荐安装extended版本的Hugo,而Homebrew安装的Hugo就是extended版本的。 Hugo的目录结构和Jekyll的还是不太一样,用了一些时间才熟悉了。LoveIt的配置项非常多,也是需要先看一看文档的。 大概配置了一下,执行hugo serve -e production --disableFastRender进行预览。 ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:4:1","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"个性化 之后就是个性化地设置,还有: 注册LeanCloud以及Valine用于评论和访问统计 利用https://realfavicongenerator.net生成网站图标 注册Gravartar头像 注册Algolia用于站内搜索 使用node.js执行npm install atomic-algolia安装atomic-algolia,用于自动化上传索引文件至Algolia 注册Mapbox 在这中间我还发现一个问题,本地预览的时候不能显示自定义的404模版,谷歌了一下发现: 信息 hugo server will not automatically load your custom 404.html file, but you can test the appearance of your custom “not found” page by navigating your browser to /404.html. ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:4:2","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"扩展 网站差不多建起来了。执行hugo,就会出现/public目录,把/public和自己的repository同步,就可以把网页托管到Github Pages。之后再用atomic-algolia上传生成的索引文件至Algolia。经过这两个步骤就完成了一次网站的部署。 另外,我又建了一个私有的repository,用于同步/public之外的源代码,所以每次部署都需要多同步一次。为了自动化这三个过程,我写了一个Shell脚本,一步到位。 这时候,我的域名终于通过了实名审核。我开始进行一些扩展: 在Github上设置CNAME 将repository导入Vercel,这样每次更新repository,都会自动部署到Vercel。据说百度不会收录Github Pages托管的网站,而部署到Vercel之后可以被收录 在Vercel中设置自定义域名 加入百度统计和谷歌Analytics 向百度搜索资源平台和谷歌Search Console提交sitemap,在必应Webmaster Tools中直接导入谷歌Search Console中已经提交的sitemap ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:4:3","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["笔记"],"content":"最后 未来我还打算加入一点谷歌广告,这也是大部分网站都有的功能。 总的来说,这次的收获还是很多的! ","date":"2021-12-22","objectID":"/zh-cn/how-my-wesite-was-built/:5:0","tags":["我的网站","Github Pages","Github","Jekyll","Hugo"],"title":"我的网站是如何建立的?","uri":"/zh-cn/how-my-wesite-was-built/"},{"categories":["日记"],"content":"谷歌收录了我的网站!目前我也向百度和必应提交了sitemap,坐等收录。 现在我的网站已经逐渐走上了正轨,所以我准备下周写一篇文章来回顾一下我的网站是如何建立的。 ","date":"2021-12-19","objectID":"/zh-cn/google-has-indexed-my-website/:0:0","tags":["我的网站"],"title":"谷歌收录了我的网站","uri":"/zh-cn/google-has-indexed-my-website/"},{"categories":["日记"],"content":"这周学校开始了毕设工作,现在我已经确定了题目,正式开始了我的毕业设计。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:0:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":["日记"],"content":"选题 题目之前已经有了,组里的一个导师给我定的一个物联网安全方向的题目。我觉得这个题目还挺合适的,一方面可以了解一些物联网的知识,另一方面也完成了我的毕设,算是一箭双雕。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:1:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":["日记"],"content":"开会 开完毕设动员会之后,和我的指导老师见了面。他给我们几个开了个小会,讲了一堆东西。其实也没什么,主要就是建了一个企业微信群,我的指导老师成了“寨主”。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:2:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":["日记"],"content":"上报 虽说题目已经有了,但我还是得好好考虑一下,毕竟毕设不是那么随便的。我的指导老师在群里也发了一些参考的题目,都是比较经典的。而那个题目对我来说还是很新颖的,我之前从没做过这个方向。综合来看,我还是更偏向这个物联网的题目,而且组里的导师也非常希望我去做这个题目。所以我向我的指导老师上报了。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:3:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":["日记"],"content":"讨论 指导老师如是说: 题目写的不完整, 写一个完整的。 好的,我把我的题目描述得更加完整,等着听老师的意见。消息已读了,但是一直没有回复。真的是莫名其妙啊,不会是他忘记了吧?第二天我发消息再问问他的意见,突然收到了一条59秒的语音。 指导老师如是说: …你那根本不叫题目,你那叫口语,那哪是题目?而且你这个所做的东西吗,说心里话这个搜索性太大了,没看到具体内容我都不好说…那么你这个所做的吧,可大可小。这个对你的要求,我不知道…那么小吗,就是非常简单的就不是太难;如果是要大吗,那是有一定难度的好不好?那么你写那么多,你那哪是一个题目?你那是口语!你口语叫我怎么给你定?你要定下来,难道叫我给你定个口语能做题目吗?你自己都写不出来一个题目叫我来定?给你定一个口语这合适吗?好吧?你自己想好了以后完了再讨论还有基础,否则话没话可说! 我直接就懵了,他说我的不叫题目。先不论到底是不是题目,他觉得我的不算题目,他有意见、有问题,他可以直接告诉我的吧?我可以去修改和完善啊,一直不回复我能知道他是怎么想的吗? 我长这么大第一次遇见这种情况,我不知道这对我来说意味着什么。我把这个事情也告诉了组里的导师。 她回复的第一句话是: 为啥? 我也把我指导老师的语音给她看,她帮我确定了一个标题。这里我忽然发现可能有一个误解,我指导老师说的“题目”到底是指“标题”还是“课题”?我查阅了《现代汉语规范词典》,“题目”确实是有多个意思的。看他说我的“题目”是“口语”,看起来他说的题目指的是“标题”了。 如果是这样的话,他为啥一开始不说清楚他说的是一个标题呢? 好吧,他说我自己都写不出来一个题目,没有讨论的基础。那我就把定好的题目发给了他,希望能有进一步的讨论。但是,他还是一直没话可说。 这时我感觉,什么“标题”还是“课题”可能并不是关键。我想到他在群里说“从这一届开始,教务处准备启用毕业设计管理系统”,“都通过系统进行”,“留有痕迹”。“再者”,“进行工程教育认证”,“各位指导老师严把题目质量关”。我感觉到他应该是对这个题目的专业水平和工作量不太好把关。毕竟他不是研究物联网的,往届应该也没有类似的题目,他一直不好下结论,所以一直没话可说。 我把我的想法告诉了组里的导师,她建议我给他讲得再详细一些。因此,我写了一个有点像开题报告的文档,写清楚了具体的要做的每一项任务,也初步计划了每一项任务的时间分配。我发给了我的指导老师,并且向他提出如果有问题希望他可以直接说出他的意见。 终于,我的指导老师开始和我讨论了。 指导老师如是说: 你提交吧。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:4:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":["日记"],"content":"最后 不管怎样,题目定下来了,现在开始做毕设了。 信息 毕设已经完成了,请看这一篇博客:NCUT-Pot,项目也已经开源。 ","date":"2021-12-18","objectID":"/zh-cn/graduation-project-starts-now/:5:0","tags":["毕业设计","NCUT"],"title":"现在开始毕设了","uri":"/zh-cn/graduation-project-starts-now/"},{"categories":null,"content":"kayak4665664 嘿,很高兴认识你,你找到了我的博客! 我是kayak4665664,中国科学院大学学生。 ","date":"2021-12-13","objectID":"/zh-cn/about/:1:0","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"帮助 ","date":"2021-12-13","objectID":"/zh-cn/about/:2:0","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"1. 如何订阅博客? 首先你需要安装RSS阅读器,然后点击,将RSS链接导入到你的阅读器中。 如果你不想安装RSS阅读器,也可以: 添加书签 添加到主屏幕 ","date":"2021-12-13","objectID":"/zh-cn/about/:2:1","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"2. 如何在本站评论? 输入评论,点击提交即可。你还可以输入你的昵称、邮箱和网址。如果你输入了Gravtar邮箱,你的头像可以显示出来。 ","date":"2021-12-13","objectID":"/zh-cn/about/:2:2","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"许可协议 本站所有内容采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 ","date":"2021-12-13","objectID":"/zh-cn/about/:3:0","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"您可以自由地: 共享 — 在任何媒介以任何形式复制、发行本作品 演绎 — 修改、转换或以本作品为基础进行创作 只要你遵守许可协议条款,许可人就无法收回你的这些权利。 ","date":"2021-12-13","objectID":"/zh-cn/about/:3:1","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"惟须遵守下列条件: 署名 — 您必须给出适当的署名,提供指向本许可协议的链接,同时标明是否(对原始作品)作了修改。您可以用任何合理的方式来署名,但是不得以任何方式暗示许可人为您或您的使用背书。 非商业性使用 — 您不得将本作品用于商业目的。 相同方式共享 — 如果您再混合、转换或者基于本作品进行创作,您必须基于与原先许可协议相同的许可协议分发您贡献的作品。 没有附加限制 — 您不得适用法律术语或者技术措施从而限制其他人做许可协议允许的事情。 ","date":"2021-12-13","objectID":"/zh-cn/about/:3:2","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":null,"content":"声明: 您不必因为公共领域的作品要素而遵守许可协议,或者您的使用被可适用的例外或限制所允许。 不提供担保。许可协议可能不会给与您意图使用的所必须的所有许可。例如,其他权利比如形象权、隐私权或人格权可能限制您如何使用作品。 ","date":"2021-12-13","objectID":"/zh-cn/about/:3:3","tags":null,"title":"关于","uri":"/zh-cn/about/"},{"categories":["日记"],"content":"世界你好! ","date":"2021-12-12","objectID":"/zh-cn/hello-world/:1:0","tags":["我的网站"],"title":"世界你好!","uri":"/zh-cn/hello-world/"},{"categories":null,"content":"Offline - kayak4665664","date":"0001-01-01","objectID":"/zh-cn/offline/","tags":null,"title":"","uri":"/zh-cn/offline/"}]
\ No newline at end of file
diff --git a/zh-cn/page/3/index.html b/zh-cn/page/3/index.html
index ba838cdb..0fdcfd82 100755
--- a/zh-cn/page/3/index.html
+++ b/zh-cn/page/3/index.html
@@ -162,14 +162,7 @@