Recent Posts

櫻川 浅羽's avatar

SONY Xperia 1 Joy 擼背殼硬質保護套開箱

一直以來淺羽對保護套的追求是以沙雕好看爲主,這樣馬雲家就有很多很可愛的手機殼可選,而且想湊情侶款也容易得很。

沙雕芝麻狐全家福

這種廉價背殼對付後置指紋就是開個孔,也沒什麼可說的;但如果是 SONY 一樣的側面指紋,那麼要麼背殼取消掉一邊放棄保護,要麼指紋體驗就要受到影響了。另外很多保護套的手感本身就很有問題,所以淺羽偶爾還是有換個背殼的想法。既然要買買買,那麼當然先看看 RASTABANANA 和 Devilcase 之類的,不過因爲實在是窮困所以都沒有下手。偶然看到 Joy 擼背殼出了 Xperia 1 保護套,價格在 CNY 56 左右尚可接受,乾脆就下單了。

Joy 擼背殼是 @[email protected] 爲了證明自己是個索粉親自操刀爲 SONY Xperia 系列準備的背殼。具體到 Xperia 1 來說,它的邊框是 TPU 材質有三種顏色以適配 Xperia 1 的四種配色(就哪裏不對?);後蓋則都是硬質塑料,並且還分爲磨砂和透明兩種後蓋。紫色款一開始還沒有磨砂款,據說是因爲「不搭」,後來還是乖乖加推了。

按鍵部分是單獨可以活動的,這樣保證了明確的按鍵反饋感,但採用了撞色設計……撞色其實也很有個性,但是紫加橙和紫加綠配色方案實在是太神奇,略微超過了淺羽的就接受範圍。而且各色的按鍵還不能單買,客服又愛搭不理的也死活不願意正面回答問題。正好趕上買三支包郵的店鋪活動,所以乾脆買紫色的磨砂和透明兩款換着用,並且爲了紅色按鍵再買一支黑色磨砂殼。

到手之後就是很普通的盒子,拆開就是殼加上按鈕,按鈕需要自己裝上去。因爲側面是軟硅膠,直接把按鈕暴力插進去並且捋平開口處就可以。紫色配紅色稍微能看一些了。

機器放進去,紫色款調得還是和真機挺像的。Xperia 1 的紫色是大家公認的難拍,調色的難度恐怕也不小。不過鬱於材質,光澤感就沒有辦法模仿了,RASTABANANA 的背殼在這方面應該會好一些。

背面攝像頭開孔非常準,左右對稱看着很舒適。攝像頭的邊緣略高於背板平面,對平放幾乎沒有影響,而且可以防止掛擦;放包裏還是要自求多福。

最後,充電口開口足夠大,用原裝線纜完全沒有問題,一些奇奇怪怪的磁吸轉接口應該也不會受到影響。

就 Xperia 1 款來說,背面的磨砂手感相當好側面的硅膠也很乾爽不會有一些所謂「液態硅膠套」的黏黏乎乎的感覺或者是摸上去總有一層灰塵的感覺按鍵的反饋感清脆得甚至超越裸機,這是淺羽沒有想到的。正面的邊框高度是嚴格看起熒幕的,據說不會影響側邊手勢,但淺羽已經關掉的這個功能……不過側面滑動的觸感確實很棒。實際上它的開孔幾乎都是嚴絲合縫的非常準確,只是指紋體驗不出意外地略有影響。非要說問題的話,大概就是按鍵配色最好還是改進一下吧。

其實 Joy 擼背殼之前也推過 XZ Premium 的殼子,而且有紅色款。不過淺羽當時並沒有關注,而現在想要也已經找不到了。如果有機會真希望能湊齊一套紅色的 Xperia XZ Premium。

icebound's avatar

杂记

昨天考完试,突然有种高考完了的感觉,十点多在电脑前面坐了一会,就觉得上下眼皮打架,早早就睡了。早上7点的时候准 […]
琴音's avatar

Something Untouched # Missing//Ep.1

这是一篇受密码保护的文章,您需要提供访问密码:

櫻川 浅羽's avatar

羅技 Logitech K380 及 K600 TV 開箱與動手玩

前些時間,淺羽買了一個桌上用書架,並把筆電接到顯示器上嘗試「站立辦公摸魚」。有了架子,滑鼠用之前的 Microsoft Bluetooth 3600 湊合,但鍵盤總不能拿其他電腦的 HHKB 到處配對,於是還是花一點額外的錢入一把鍵盤,也給 iPad 和 Chromebook 等作爲備用。
櫻川 浅羽's avatar

土製雙系統 Chromebook 使用體驗與踩坑

淺羽最常用平板電腦做什麼?瀏覽網頁、看視訊、聊天和寫文和查看照片。現在一臺 iPad Air 2 就能大體上滿足淺羽的需求,那麼有完整的桌面版 Chrome 本身就解決了瀏覽網路的最大需求,而 Linux Apps 與 Android Apps 又豐富和完善了生態。加之 Chrome OS 本身對鍵盤滑鼠的良好支援,一臺可以拆卸鍵盤的 Chromebook 可能是淺羽用來替換掉 iPad 的最好選擇。
linkthis's avatar

RSShub配置记录

天下没有免费的午餐。
櫻川 浅羽's avatar

在 BlackBerry 10 OS 上透過 CardDAV 同步 Google 聯絡人

自 BlackBerry 10 OS 之後,同步 Google 賬戶的資訊變得很容易,透過系統內建的設定精靈就能直接同步郵件、聯絡人和行事曆。但近幾個月起,同步 Google 聯絡人卻會提示「同步錯誤」。起初以爲只是普通的網路錯誤,連續一段時間後實在無法繼續無視,於是經過一番搜尋,發現是 Google 更改了 CardDAV 地址導致的。

重新新增帳號也並不解決問題

既然知道原因,那麼就好解決了。根據 Gmail contacts can’t be added 一篇的提示,Google 更改了 CardDAV 地址並廢棄了舊地址,同時沒有修改 .well-known 聲明。那麼見招拆招,淺羽自己添加單獨的 CardDAV 同步即可。

  1. 由於淺羽的賬戶已經啓用了 2FA,首先需要在「我的賬戶」 – 「安全性」頁面中建立應用程式密碼;
  2. 進入 BlackBerry 10 OS 的系統設定,進入「帳號」,點擊「新增帳號」 – 「進階」 – 「CardDAV」;
  3. 在「使用者名稱」和「電子郵件地址」欄位輸入自己的電郵地址,在「密碼」欄位輸入前面創建的應用程式密碼;
  4. 在「伺服器位址」輸入 https://www.googleapis.com/carddav/v1/principals/${userEmail}/lists/default/,記得把 ${userEmail} 替換成自己的電郵地址;
  5. 點擊「完成」,等待設定就可以了。
如此設定就能成功同步了

另外,根據 Google 的說明,它家的 CardDAV 其實也只是「能用」而已……「能用」是什麼程度呢?

We have not implemented the full specification, however many clients such as Apple iOS Contacts and Apple Mac OS should interoperate correctly.

Google CardDAV API Developer’s Guide

好的吧,反正確實「能用」。

icebound's avatar

HBCPC2019题解

Solution A. Battle of Balls 球的半径为 ,为了不让球碰到障碍点,就要保证,球心到障 […]
linkthis's avatar

mpv使用记录

偷懒一时爽,查错火葬场。
icebound's avatar

HBCPC2019游记

现在是2019年5月15日凌晨,本来肝完java大作业打算睡觉,看了一眼知乎,看到又有人说【出题人不了解河北省 […]
李春光 (Chun-Guang LI)'s avatar

学术讲座通知​:From Shuffled Linear Regression to Homomorphic Sensing

题目:From Shuffled Linear Regression to Homomorphic Sensing
报告人:Dr. Manolis Tsakiris, 上海科技大学
时间:2019年5月30日14:00-15:30 (星期四)
地点:教三 308  主持人:李春光

摘要:
A recent line of research termed Shuffled Linear Regression has been exploring under great generality the recovery of signals from permuted measurements; a challenging problem in diverse fields of data science and machine learning. In its simplest form it consists of solving a linear system of equations for which the right-hand-side vector has been permuted. In the first part of this talk I will present a provably correct method based on algebraic geometry together with its associated algorithm, the latter being a first working solution to this open problem, able to handle thousands of noisy fully permuted measurements in milliseconds. In the second part of the talk I will discuss the issue of uniqueness of the solution, in a general context which I have termed Homomorphic Sensing*. Given a linear subspace and a finite set of linear transformations I will present dimension conditions of algebraic-geometric nature guaranteeing that points in the subspace are uniquely determined from their homomorphic image under some transformation in the set. As a special case, this theory explains the operational regime of Unlabeled Sensing, in which the goal is unique recovery of signals from both permuted and subsampled measurements.
*Has been accepted by ICML2019. Preprint: https://arxiv.org/abs/1901.07852

报告人简介:
Manolis Tsakiris is an electrical engineering and computer science graduate of the National Technical University of Athens, Greece. He holds an M.S. degree in signal processing from Imperial College London, UK, and a Ph.D. degree from Johns Hopkins University, USA, in theoretical machine learning, under the supervision of Prof. Rene Vidal. Since August 2017 he is an assistant professor at the School of Information Science and Technology (SIST) at ShanghaiTech University. His main research interests are subspace learning methods and related problems in algebraic geometry. For more information, please visit his homepage.

本次报告为学术前沿报告,欢迎各位老师和学生积极参加!

Gaojianli's avatar

Libuv初探

前言

作为一个Node.js玩家,libuv的鼎鼎大名可谓是如雷贯耳。在我的印象中,libuv就是个“封装了ICOP/epoll等的超级牛逼的基于事件循环的库”,换句话说,就是“我知道你很牛逼,但是我啥都不知道”。
在生活中,有很多事情不是不能做,只是需要一个契机。有了这个契机,我就能有足够的动力去完成之。而我这学期的C++专业选修课大作业便给了我这个契机:

题目三(10分)
在题目二的基础上,将游戏由本地单机,扩展为服务器多人游戏平台,使用客户端/服务器的方式,同一时间可以多人登录系统。将所有闯关者、出题者信息保存在服务器。
要求:
 必须在题目二基础上进行修改。
 使用socket进行通信。
 需要完成服务器端程序,以及客户端程序。客户端可以启动多个同时与服务器交互,要求服务器具有并发处理能力。

从入门到放弃

其实一开始,我曾经被libuv吓退过,究其原因就是那一大堆uv_开头的指针,而代码写出来大概是这个画风:
Echo-Server

Molunerfinn's avatar

用setTimeout和clearTimeout简单实现setInterval与clearInterval

这个问题其实是前一段时间舍友的一道面试题。我觉得类似用reduce实现map、用xxx实现yyy的题目其实都挺有意思,考察融会贯通的本领。不过相比之下这道题可能更有实际意义。比如我们经常会用 setTimeout 来实现倒计时。下面来说说我对这个问题的思考。

琴音's avatar

Daily 2019/5/7

这是一篇受密码保护的文章,您需要提供访问密码:

櫻川 浅羽's avatar

陽玩意 YDKB HHKB 藍芽雙模 BLE 替換主板動手玩

HHKB 作爲靜電容鍵盤的代表作之一,本身雖然有藍芽版本,但外觀神奇、無法多裝置、不能雙模,已經留下了許多遺憾。外加作爲 60% 的經典鍵位設計,雖然有 DIP 開關可以控制部分按鍵功能,但始終是不如可以自定義配列來得靈活自由。某天突然瞭解到 YDKB HHKB BLE Mod,支援 USB / 藍芽雙模式、藍芽 BLE 4.0、基於 TMK 方案的自定義配列,彷彿就是爲了解決這些問題而生;加之改裝只需要擰下螺絲替換主機板、對外觀沒有任何影響,這樣的好東西當然是買買買啦。
问少's avatar

二进制数中 1 的个数

二进制数中 1 的个数这个问题可以说是很常见的基础问题了。

最简单最慢的方法就是转换成字符串查 1 的数量。

比较快的方法是使用位运算。

举例来说,整数 35,用二进制表示就是 0000 0000 0010 0011,二进制数中有 3 个 1。
计算这个数字中的 1 的个数,使用与运算便可以快速完成。

这里有个位运算的小知识,n & (n-1) 可以消去二进制数的最右边的 1。
比如 35 & 34

1
2
3
4
0000 0000 0010 0011
0000 0000 0010 0010
-------------------
0000 0000 0010 0010

结果得到 34,接下来 34 & 33

1
2
3
4
0000 0000 0010 0010
0000 0000 0010 0001
-------------------
0000 0000 0010 0000

结果得到 32,接下来 32 & 31

1
2
3
4
0000 0000 0010 0000
0000 0000 0001 1111
-------------------
0000 0000 0000 0000

结果得到 0,计算过程便完成了。

在得到 0 之前,一共计算了 3 次,也就是说一共消去了 3 个 1。
即,给定数字 35,得出结果为 3

使用 C 语言表示以上算法:

1
2
3
4
5
6
7
8
9
int hammingWeight(uint32_t n) {
if (!n)
return 0;
uint8_t sum;
for (sum = 0; n; sum++) {
n &= (n - 1);
}
return sum;
}

櫻川 浅羽's avatar

使用 ExifTool 批量從檔案名添加 Exif 日期

淺羽的攝影工作流建立在 Adobe 全家桶上,並且固執地使用 Lightroom Classic CC。Lightroom 的自動匯出流程非常方便,可以匯出多種格式、自動重命名、添加水印並且去除照片資料;但問題在於它去除得太乾淨了,把包括拍攝日期在內的所有資料全部去除了,並且不能有選擇地保留。不過淺羽匯出的檔案名包括了拍攝時間日期,於是可以使用開源免費的 ExifTool 重新處理一下檔案。

ExifTool 是一個 Perl 庫外加 CLI 工具,可以支援多種檔案的 Exif 資料,參數靈活強大。淺羽通常會匯出 JPEG 格式檔案,名字如 SKG-20190426-164737.jpg,所以指定一下檔案名格式就可以直接處理好。

$ exiftool -d SKG-%Y%m%d-%H%M%S.jpg "-alldates<filename" "-filemodifydate<datetimeoriginal#" -ext jpg .
======== ./SKG-20190426-145918.jpg
======== ./SKG-20190426-152009.jpg
======== ./SKG-20190426-152014.jpg
======== ./SKG-20190426-152028.jpg
======== ./SKG-20190426-152035.jpg
======== ./SKG-20190426-152037.jpg
======== ./SKG-20190426-152142.jpg
======== ./SKG-20190426-152147.jpg
======== ./SKG-20190426-153154.jpg
======== ./SKG-20190426-153448.jpg
======== ./SKG-20190426-153451.jpg
======== ./SKG-20190426-163712.jpg
======== ./SKG-20190426-163957.jpg
======== ./SKG-20190426-164737.jpg
======== ./SKG-20190426-164819.jpg
======== ./SKG-20190426-165327.jpg
======== ./SKG-20190426-152014.jpg
    1 directories scanned
   17 image files updated
<-END-

由於沒有指定改名、複製動作,所以 ExifTool 會直接操作源圖片,添加 DateTimeOriginalCreateTime 字段資料。現在查看照片就有拍攝時間日期了,並且上載到 Google Photos 也能正確識別。

另外,ExifTool 的參數功能很強大,作者也認爲「如果需要配合其他工具使用,往往是因爲用家沒有仔細讀文檔」。不過,讀文檔的時間好像已經夠寫一個小 Script 了?

來自作者的溫馨小提示
icebound's avatar

HBCPC2018标程

最近好多人找我要标程。。。 贴在这里了! 链接: https://pan.baidu.com/s/1-tzOo […]
Molunerfinn's avatar

我的2019春招(暑期实习)记录

今年的春招(暑期实习)批已经过去大半了,相信不少同学已经拿到了心仪的offer了~本来打算暑假有空再写写这段经历,不过今天晚上正好有空就记录一下吧,希望能给正在或者今后要找前端实习、工作的同学一点点启发和建议。(由于我妹子在北京读书,所以实习的话我只想着申请北京的实习机会,这是本文的大前提)。

我自己是北邮研二的学生,「主修」前端。我自己的面试经历不多,从1月份到现在总共只面了3家:头条,腾讯·微信和蚂蚁金服·支付宝,很幸运都拿到了offer。其实我觉得主要还是内推对我的帮助特别大,没有内推的话我估计也很难拿offer了。所以经验第一条:能找内推尽量通过内推来获取面试资格。帮你内推的学长学姐一般会帮你查看(甚至修改)简历,有的可以直接部门直推给leader,等于省去了HR筛简历的步骤,所以能找到内推就尽量走内推而不是单纯走网申吧。

Molunerfinn's avatar

Electron-vue开发实战7——命令行调用与系统级别右键菜单的实现

前言

前段时间,我用electron-vue开发了一款跨平台(目前支持主流三大桌面操作系统)的免费开源的图床上传应用——PicGo,在开发过程中踩了不少的坑,不仅来自应用的业务逻辑本身,也来自electron本身。在开发这个应用过程中,我学了不少的东西。因为我也是从0开始学习electron,所以很多经历应该也能给初学、想学electron开发的同学们一些启发和指示。故而写一份Electron的开发实战经历,用最贴近实际工程项目开发的角度来阐述。希望能帮助到大家。

预计将会从几篇系列文章或方面来展开:

  1. electron-vue入门
  2. Main进程和Renderer进程的简单开发
  3. 引入基于Lodash的JSON database——lowdb
  4. 跨平台的一些兼容措施
  5. 通过CI发布以及更新的方式
  6. 开发插件系统——CLI部分
  7. 开发插件系统——GUI部分
  8. 命令行调用与系统级别右键菜单的实现
  9. 想到再写…

说明

PicGo是采用electron-vue开发的,所以如果你会vue,那么跟着一起来学习将会比较快。如果你的技术栈是其他的诸如reactangular,那么纯按照本教程虽然在render端(可以理解为页面)的构建可能学习到的东西不多,不过在main端(Electron的主进程)应该还是能学习到相应的知识的。

如果之前的文章没阅读的朋友可以先从之前的文章跟着看。本文主要是基于PicGo v2.1.0版本更新的重要内容做的讲述。

问少's avatar

macOS 原生输入法设置自然码

用了 macOS 一段时间了,一直使用的是搜狗输入法,因为系统自带的双拼输入法不支持自然码。

不过最近在网上看相关的双拼练习时,发现原来用过的双拼练习的作者 @BlueSky 给出了提示,macOS 其实内置隐藏了双拼的自然码方案。

只需在终端内输入以下命令即可:

1
$ defaults write com.apple.inputmethod.CoreChineseEngineFramework shuangpinLayout 5

在输入法偏好设置中会看到这样的效果:

此时即可使用自然码方案了。

附:系统为 macOS 10.14.4

icebound's avatar

洛阳游记

旅行,是一次社会性的濒死体验。 你从熟悉你的城市中抽离,从你熟悉的城市中死去。你重生在其他不同的地方,就像你的 […]
櫻川 浅羽's avatar

戴爾 DELL Business Thunderbolt Dock TB16 開箱與 Linux 上兩月使用體驗

出掉 MacBook Pro 以後,XPS 13 就成了主力上網機。它內建了 4K 熒幕,並且在 GNOME 下很流暢,所以作爲日常用機完全沒有問題;只是由於尺寸和 HiDPI 的原因,加上淺羽常年接駁熒幕和鍵盤滑鼠使用,又希望能快速地臨時拿走用一用,所以添置一個 Dock 是勢在必行了。
icebound's avatar

学习java时的小思考

写java的时候遇到一点小问题,关于方法(函数)传值还是传址的问题。 比如下面一段代码:输出结果为abc 这段 […]
's avatar

浪费npm包名

开篇废话

好长时间没有写过任何东西了,并不是因为这期间我什么都没干,天天咕咕咕,而是觉得真的和各位大佬之间的差距太大了,有事被催着干活,没事躺尸看海绵宝宝。最近跟着高先生写一个扶贫的项目,本来挺简单的项目,愣是给写出花来了,还由此诞生了一个npm包,浪费了koa2-auth的包名,实在惭愧。

大半夜的就分享一下这个事情吧

来历

碎碎念警告,如有不适请跳过

开学之前,高先生找到我,叫我接一个后端的项目,就是上学期由于出去浪而错过面试的项目。当然,这种自己找上来的,大概率不是什么好事,你不能说叫我接我就接嘛,起码我要先体验下。

在看了看代码之后,嗯~不愧是合作多次的高先生,还是熟悉的味道,就接了下来。本来已经开发完成的项目,蹭了高先生的光,过来修修补补,顺便蹭蹭志愿时长,简直不要太舒服。

由于没有什么新的产品设计上的需求了,我就转向去做做代码维护的事情,为了让自己之后的代码调整等大更新可以顺利通过,最重要的事情就是开始写单元测试。

渐渐的,单元测试覆盖了100%的正常访问情况和30%的错误拦截情况,基本就可以了,毕竟错误拦截基本上也是权限错误,这是一个前后端分离的项目,除非有人故意搞破坏想投数据,要不也不会出现权限不对的问题,毕竟小项目。

然后就是把通篇的显式定义的new Promise替换成了Mongoose自带返回的样子,大砍特砍,多亏了上面写的单元测试,也就省了高先生的代码审核了。与此同时,自动部署也被我摸清楚怎么用了,上传的代码自动测试,合并到测试/主分支上就会被推送部署到测试环境中。

然后就是我沉迷Docker的时间了,直接改源码部署为镜像部署,同时开了一个集群(没错,单机集群),4个Docker跑在上面,并发理所当然提高了。

然后引库,session缓存上Redis。Gitlab-ci自动测试简直不要太爽。

结果还是没有什么新需求,这时候就开始写花了,这篇水文的主角就登场了。

需求

高先生还是觉得现在的验权实在是太过臃肿(确实,在需要验权的时候全员switch case一个权限都跑不了),然后给我发来了样例:

当时并没有看到这里有一个server层,只看到后面那个冒号分割的东西好帅呀!好简洁!然后我就想到了之前看hapi.js好像有这么个东西,兴冲冲就跑到图书馆翻出了当时借的书,找了一遍发现并没有。略失望。然后就开始自己实现呗。照葫芦画瓢的技术还是可以的。

就算画也得有个参考吧,语法风格就定下来了,使用这种双冒号分割的方式来验权。然后有借鉴了一下路由的分级解析,就有了现在这个koa2-auth

我最终的实现效果:

1
await ctx.auth.must(`Item::${ctx.params.id}::write`);

还是有点差距的,但是跟之前的画风比,这样子很不错了(开始自夸)。

成品

我就不在这里粘README了,毕竟已经浪费了一个包名了,各位可以直接去npmjs.org网站搜索查找。

传送门:koa2-auth

关于npm包发布维护的东西还不太会,最后感谢来自高先生的友情翻译,和高先生的提携。

最后大字宣传他的博客:

高渐离の屋

琴音's avatar

Awakening#?? 2019/3/21

这是一篇受密码保护的文章,您需要提供访问密码:

icebound's avatar

英语

When I just a kid, I was fear of the outside world, esp […]
Molunerfinn's avatar

Electron-vue开发实战6——开发插件系统之GUI部分

前言

前段时间,我用electron-vue开发了一款跨平台(目前支持主流三大桌面操作系统)的免费开源的图床上传应用——PicGo,在开发过程中踩了不少的坑,不仅来自应用的业务逻辑本身,也来自electron本身。在开发这个应用过程中,我学了不少的东西。因为我也是从0开始学习electron,所以很多经历应该也能给初学、想学electron开发的同学们一些启发和指示。故而写一份Electron的开发实战经历,用最贴近实际工程项目开发的角度来阐述。希望能帮助到大家。

预计将会从几篇系列文章或方面来展开:

  1. electron-vue入门
  2. Main进程和Renderer进程的简单开发
  3. 引入基于Lodash的JSON database——lowdb
  4. 跨平台的一些兼容措施
  5. 通过CI发布以及更新的方式
  6. 开发插件系统——CLI部分
  7. 开发插件系统——GUI部分
  8. 想到再写…

说明

PicGo是采用electron-vue开发的,所以如果你会vue,那么跟着一起来学习将会比较快。如果你的技术栈是其他的诸如reactangular,那么纯按照本教程虽然在render端(可以理解为页面)的构建可能学习到的东西不多,不过在main端(Electron的主进程)应该还是能学习到相应的知识的。

如果之前的文章没阅读的朋友可以先从之前的文章跟着看。并且如果没有看过前一篇CLI插件系统构建的朋友,需要先行阅读,本文涉及到的部分内容来自上一篇文章。

问少's avatar

使用 GPG 签名你的 Commits

本文最后更新于 2019年3月15日 可能会因为没有更新而失效。如已失效或需要修正,请留言!

准备工作

首先要安装好 GPG 工具。

1
$ brew install gnupg gnupg2 pinentry-mac

配置使用环境。

1
2
3
4
5
6
$ test -r ~/.bash_profile && echo 'export GPG_TTY=$(tty)' >> ~/.bash_profile
$ echo 'export GPG_TTY=$(tty)' >> ~/.profile

$ echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf

$ killall gpg-agent

检查现有的 GPG 秘钥

1
$ gpg --list-secret-keys --keyid-format LONG

如果没有返回值,则说明此电脑上没有配置 GPG 秘钥。
如果有,则可以跳过生成 GPG 秘钥的步骤。

生成一个新的 GPG 秘钥

1
$ gpg --full-generate-key

第一步,选择加密类型,可以直接回车选择默认的 RSA and RSA
第二步,输入秘钥的强度,推荐输入 4096
第三步,选择秘钥的过期时间,嫌麻烦的同学可以直接回车选择默认的永不过期。
第四步,确认一下以上信息有没有错。
第五步,输入你的名字。
第六步,输入你的邮箱,注意此邮箱需要是你的 Github 账号中添加过的邮箱。
第七步,设置此秘钥的密码,使用此秘钥需要用这个密码来解密。
之后稍等片刻,GPG 秘钥即生成完毕。

使用 GPG 秘钥

在终端中使用 gpg --list-secret-keys --keyid-format LONG 命令查看当前秘钥的信息。

1
2
3
4
5
6
$ gpg --list-secret-keys --keyid-format LONG
/Users/hubot/.gnupg/secring.gpg
------------------------------------
sec 4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10]
uid Hubot
ssb 4096R/42B317FD4BA89E7A 2016-03-10

在这里 3AA5C34371567BD2 就是秘钥的 ID

使用以下命令来获得 GPG 秘钥的公钥,注意 <ID> 需要替换为自己秘钥的 ID。

1
$ gpg --armor --export <ID>

复制以上公钥,去往 Github 账户设置页面即可添加 GPG 秘钥。

接着使用以下命令配置 git 以使用 GPG 秘钥。

1
2
3
$ git config --global user.signingkey <ID>
$ git config --global commit.gpgsign true
$ git config --global gpg.program gpg

带有 GPG 验证的 commit 只是多了 -S 参数。

1
$ git commit -S -m "your commit message"

验证

在提交改动之后,可以使用以下命令来检验以下是否成功使用 GPG 秘钥来签名 commit。

1
$ git log --show-signature -1

若带有下面的提示,则说明成功。

1
gpg: Good signature from "Your Name <[email protected]>"

问少's avatar

Ubuntu 18.04 配置开机启动项

本文最后更新于 2019年3月14日 可能会因为没有更新而失效。如已失效或需要修正,请留言!

在 Ubuntu 16.04 版本中,配置开机启动项是一件很简单的事情,只需在 /etc/rc.local 中添加即可。

但在 Ubuntu 18.04 中,此方法失效。经搜索实践,总结了一下较为简单的设置开机启动项的方法。

首先运行

1
$ crontab -e

之后可能会出现以下提示

1
2
3
4
5
6
7
8
9
no crontab for neo - using an empty one

Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed

Choose 1-4 [1]:

推荐选 1。

在末尾添加新的一行

1
@reboot /path/to/your/boot.sh

之后把开机启动命令都写在 /path/to/your/boot.sh 这个文件里。

最后别忘了给文件加上可执行属性

1
$ chmod +x /path/to/your/boot.sh

此时重启即可看到效果。

问少's avatar

最强日期正则表达式

简单的日期判断(YYYY/MM/DD)

1
^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$

演化的日期判断(YYYY/MM/DD| YY/MM/DD)

1
^(^(\d{4}|\d{2})(\-|\/|\.)\d{1,2}\3\d{1,2}$)|(^\d{4}年\d{1,2}月\d{1,2}日$)$

加入闰年的判断

1
^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$
櫻川 浅羽's avatar

SONY SmartWatch 3 更換錶帶 SWR510 與翻新作業

淺羽的 SmartWatch 3 從 2015 年 4 月開始,也已經戴了有四年了。其實淺羽一直想換新的 Android Wear,但苦於難以找到功能齊全、好看又能長續航的錶,選來選取竟然都不滿意。平心而論,SmartWatch 3 雖然已經不再有系統更新,而且外觀太偏運動了一些,確實有些落伍了;但是它在四年的使用後還能有約兩個整天的續航,並且還有獨一無二的半透半反式液晶熒幕的設計,雖然色彩效果一般,但在強烈陽光下靠反射光線,保證可用性的同時也很有復古電子錶的味道,讓淺羽很是喜歡。不過指望索尼粑粑出下一代產品不太現實:不說遙遙無期,有沒有首先就是一個問題。所以淺羽選擇了一個簡單的解決方法:更換錶帶。

SmartWatch 3 畢竟已經很老了,雖然官方有出專用的替換錶帶 SWR510,但市面上幾乎只有熒光黃色售賣,而粉色卻很難找到。淺羽也是費了不少力氣,經過一個多月才訂購到一隻粉紅色錶帶。這錶帶沒有包裝,但是一看就知道是索尼自己出品,和原裝的黑色錶帶的風格可謂是一脈相承。大法家一貫以色調作爲賣點,這次的粉紅色款 SWR510 依然是顯眼的熒光色。

這款錶帶上的鎖釦倒是頗有亮點:中間有一條鑿空槽,錶帶的長度是可以無極調節的,很好地解決了原配錶帶三格略緊、四格太鬆的問題。相信很多戴電子錶的孩子都知道淺羽在說什麼(笑)。

順便把貼膜翻新一下,這隻 SmartWatch 3 勉強就可以當作新錶戴了。只不過防水塞已經快斷裂了,要仔細保管才是。

琴音's avatar

无题#?(Password:Villagers’ Home)

这是一篇受密码保护的文章,您需要提供访问密码:

问少's avatar

macOS 下的包管理器 Homebrew

本文最后更新于 2019年3月8日 可能会因为没有更新而失效。如已失效或需要修正,请留言!

介绍

之前使用 Ubuntu 和 CentOS 的时候,它们都各自拥有便捷的包管理器 APTYUM,使用它们安装卸载软件,自动解决依赖问题,非常方便。最近在换用 macOS 系统之后,却没有了类似的管理器,安装软件又回到了和 Windows 一样的体验。虽说 App Store 拥有一些很优秀的软件,但是作为一个未来的码农,需要的很多软件并没有 App Store 版,如果手动下载安装,以后软件更新了还需要再下载安装一次,这些无意义的重复劳动需要解决掉。

早在换 Mac 之前就听说过了 Homebrew 的名字,它自己的介绍就是 The missing package manager for macOS (or Linux),很厉害的一个项目,方便实用。它的野心不小,不满足于 macOS 系统,还将支持扩展到了 Linux 发行版系统上,甚至还支持在 WSL 中使用。

安装

安装非常简单,终端中一行命令即可完成。

1
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

使用

搜索软件

Homebrew 中搜索软件很很简单。

1
$ brew search chrome


如上图可以看到,我搜索 Chrome 的结果。搜索结果有两部分,FormulaeCasks,前者指命令行工具,后者指图形化程序。

如果想查询相关程序的信息,可以使用以下命令,对于 Formulae 程序

1
$ brew info chrome-cli


对于 Casks 程序

1
$ brew cask info google-chrome

安装软件

在知道程序准确名称之后,可以使用以下命令安装,对于 Formulae 程序

1
$ brew install chrome-cli

对于 Casks 程序

1
$ brew cask install google-chrome

卸载软件

卸载软件同样很简单,对于 Formulae 程序

1
$ brew uninstall chrome-cli

对于 Casks 程序

1
$ brew cask uninstall google-chrome

升级软件

更新软件源和 Homebrew 本身。

1
$ brew update

列出没有更新到最新版本的 Formulae 程序。

1
$ brew outdated

更新所有 Formulae 程序,

1
$ brew upgrade


或者更新特定 Formulae 程序。

1
$ brew upgrade node

对于 Casks 程序来说,更新并没有如此简单,不过可以使用一个小插件来使之简化。

1
$ brew tap buo/cask-upgrade

之后,只需运行以下命令即可检查 Casks 程序的更新。

1
$ brew cu

默认不会检查带有自动更新功能的程序,不过我想要的是让它检查,帮我更新,只需添加一个参数即可。

1
$ brew cu -a

问少's avatar

macOS 下 Android 平台工具的 PATH 配置

本文最后更新于 2019年3月7日 可能会因为没有更新而失效。如已失效或需要修正,请留言!

在安装了 Android Studio 之后,相关的 adb fastboot 等工具应该都应经下载在电脑里了。但是 AS 并没有把相关的目录加入 PATH,导致在终端里不可以方便的直接使用,需要加上很长的一串路径才可可以。这个文章记录下解决的办法。

编辑 BASH 的配置文件

1
$ nano ~/.bash_profile

在文件最后追加几行

1
2
3
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH="$PATH:$ANDROID_HOME/platform-tools"
export PATH="$PATH:$ANDROID_HOME/tools"

macOS 下的默认 ANDROID_HOME 位置就是如上配置,无需修改,其他系统下的路径需要根据实际情况修改。

之后再使刚改好的配置生效,或者重新打开终端。

1
$ source ~/.bash_profile

配置好后的效果如下图。

问少's avatar

去除 Next 主题图片的灰色边框

本文最后更新于 2019年3月6日 可能会因为没有更新而失效。如已失效或需要修正,请留言!

最近发了篇文章,带了些截图,发现对于 macOS 处理过的截图,Next 主题在图片周围加一圈灰色边框并不美观。

于是便想办法去掉它。打开浏览器检查图片样式,发现图片周围加了一圈一个像素宽度的灰色边框。

打开 Hexo 博客目录,直接搜索整个目录,果然在 themes/next/source/css/_common/components/post/post-expand.styl 这个文件里找到了配置。

只需将以下代码

1
2
3
4
5
6
img {
box-sizing: border-box;
margin: 0 auto 25px;
padding: 3px;
border: 1px solid $gray-lighter;
}

改为

1
2
3
4
5
6
img {
box-sizing: border-box;
margin: 0 auto 25px;
padding: 3px;
border: none;
}

即可去除边框。

去除边框之后的效果,看起来舒服多了。

最后记得一点,一定要先执行 hexo clean 再部署,否则样式表文件并不会更新导致修改不生效。

问少's avatar

创建 Localhost 证书

本文最后更新于 2019年3月5日 可能会因为没有更新而失效。如已失效或需要修正,请留言!

有时因为开发的需求,需要为本地的网页服务器设置 https 访问。在这里记录一下在 macOS 系统下快速创建自签名证书并设置可信的方法。

Xcode Command Line Tools

基本所有在 macOS 中开发的人应该都已经安装过了命令行工具,在终端中一句命令即可安装。

1
$ xcode-select --install

生成证书

在终端里运行以下命令即可在用户目录里生成证书和秘钥。

1
2
3
4
$ openssl req -x509 -days 3650 -out localhost.crt -keyout localhost.key \
-newkey rsa:2048 -nodes -sha256 \
-subj '/CN=localhost' -extensions EXT -config <( \
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

其中 -days 3650 参数是指定证书的有效时间为 3650 天。

设置信任

最后,需要在系统中设置信任,否则直接使用仍会提示不信任。

直接搜索打开“钥匙串访问”,“文件” - “导入项目” - 选择刚生成的 crt 文件。

双击打开刚导入的证书,设置“使用此证书时:始终信任”。

效果如下图。

櫻川 浅羽's avatar

略微難受的 Tilted 體感遊戲控制器外設開箱與動手玩

在不少 FPS 遊戲中,左右擺頭基本上是一個標配動作了。雖然大部分遊戲預設有對應的 Q、E 按鍵做出擺頭動作,但淺羽在玩遊戲時還是經常因爲太投入而做出真正的頭部動作。那麼有沒有什麼辦法把現實中的東西反映到遊戲裏呢?淺羽原先想的是通過攝像頭進行面部識別然後做出對應的動作,但國內的一家公司給出了一個更直接的方案:體感遊戲控制器。

Tilted 這款產品應該是國內團隊推出的(半成品),並在京東衆籌上有發售,提供「膚質黑」、「膚質白」雙色。不過,他們同時也在國外銷售,並且多提供一種「閃耀白」配色,但價格也比國內衆籌高出不少。考慮到黑色配上綠燈太過於雷蛇炫酷,淺羽還是選擇了膚質白配色。

英文網站提供三種配色

參加衆籌約兩個月後,淺羽突然收到了一個快遞,拆開才知道是幾乎已經被忘記了 Tilted。快遞盒子很小,內容除了塑封的 Tilted 包裝盒之外還有一份幾頁的說明書。塑封上有一個防止窒息的小孔,這倒是一個意外的細節。

包裝內除了 Tilted 本身,還有魔術貼帶用來固定 Tilted、不乾膠磁鐵、USB 無線接收器和一條極短的 Micro USB 線纜。Tilted 本身也不大,接縫處很明顯,但整體做工尚可;機身上只有一個按鈕、一圈燈號和一個 Micro USB 接口,沒有使用 Type-C 接口是一個大遺憾。

不乾膠磁鐵和右側的魔術貼帶磁鐵

包裝內配有兩塊帶磁鐵的配件:左側的不乾膠磁鐵和右側的魔術貼帶磁鐵。它們的作用都是將 Tilted 本體固定在頭上(耳機上)。根據說明書解釋,Tilted 本身是一套加速度感測器械,根據不同的情況會以鍵盤按鍵的方式傳送指定按鍵;Tilted 只有在吸附上磁鐵的情況下才會傳送按鍵訊號。

Tilted 出場的時候就預設了一套方案,拿到插好接收器即可使用。不過淺羽爲了調整設定、一探究竟,還是按照說明書安裝好驅動。驅動下載頁面是一個純英文的頁面,並且只提供 Windows 版本;考慮到 Windows 作業系統是遊戲 PC 的大主流,這倒也說得過去。然而安裝介面和主介面在 Hi-DPI 下錯位、英文翻譯錯誤百出,直接減去了淺羽的不少印象分。

  • 錯位
  • 首字母未大寫
  • 支離破碎的英文

進入驅動程式後,淺羽摸索了一下,在設定裏可以更改語言爲中文——然而只有簡體中文,沒有繁體中文。淺羽將 Tilted 開機,並且打開驅動程式,但是只看到「正在連接中…」的提示;後來才反應過來,需要用 Micro USB 線纜將 Tilted 與電腦連接,驅動才能抓到裝置使用接收器的情況下,Tilted 與雜牌無線鍵鼠無異,不能使用驅動程式操作。淺羽無法確認這樣的設計是否爲了防止遊戲認爲 Tilted 是作弊硬體;但 Logitech、Razer 等大廠均可以在無線狀態下連接驅動,這樣的理由其實並不足以作爲藉口

使用 Micro USB 線纜連接電腦後發出綠光的 Tilted

好不容易連接上之後,驅動程式終於展示出了唯一的功能介面。這個介面相當簡單,只能夠針對六個方向的持續加速度和兩個方向的瞬時加速度調整功能。爲了儘可能地減少誤操作,淺羽只設定了三個動作:左偏頭爲 Q、右偏頭爲 E、向前俯身爲 Shift。

  • 依然錯位的介面
  • 預設按鍵方案
  • 淺羽修改過的方案

然而在開始測試之前,淺羽就犯了難:雖然有頭戴式耳機,但是淺羽平時並不習慣使用它玩遊戲。一番糾結之後,淺羽做出了一個艱難的決定:把 Tilted 當作頭飾佩戴……好在,按照宣傳,Tilted 本身只有 15g 重,所以配合魔術貼戴在頭上,倒也不會覺得太重,而且也不會輕易掉下。

  • 淺羽的新頭飾好看嗎?
  • 好看嗎好看嗎?

在遊戲中,淺羽有意只使用 Tilted 控制偏頭動作,並讓手指只集中在走動控制上。然而,Tilted 的反饋非常詭異:有的時候,即使淺羽沒有東西,Tilted 也會傳送指令讓遊戲內的人物偏頭;有時即使淺羽佷用力地偏頭,Tilted 也並不認爲淺羽想要做出偏頭的動作……按照說明書內的操作校準後,Titled 依然我行我素。最終還是只能放棄。

以淺羽的簡單試用看,Tilted 並不是一個有用且好用的外設,起碼目前的階段來看不是。它的功能相對簡單,但即使如此也並沒有做出好的、容易學習和利用的體驗。Tilted 的外觀設計尚可、硬體本身也過關,同時有吸引人類的賣點;但它在驅動程式、調教等細節方面的考慮,堪稱應付了事。加上有反饋說「點擊驅動程式的固件修復後無法開機」「撥打售後電話關機」等問題,它的客戶服務幾乎等於沒有,無論是無心之過還是有意爲之,都極大地壓縮了 Titled 的價值

Roy Binux's avatar

Zerotier Nat 网关出口 和 iptables 调试

每当看到各类教程中的 iptables 指令,在格式参数组合之下可以实现从防火墙,封禁 IP 端口到 NAT 的各种操作,就如同魔法一般,看不明白,却又感到无比强大。想学,但又好像不得要领,稍微不慎可能就再也连不上了。最近配置 Zerotier 的 Nat 网关的时候,看着

櫻川 浅羽's avatar

新年印象:深圳

闊別深圳居然也已經好幾年了,雖然一直遠離,但從小有超過一半時間在深圳、另一半時間也在一河之隔的香港的淺羽,對這裏的感情當然很濃厚。即使深圳已經不能稱之爲家,但是一旦有機會,還是往深圳靠近,彷彿這樣可以找到什麼安慰或者寄託似的。其實這次回來,計劃的行程本來就短,所以只是約飯或者辦事情的時候順便路過,可以看看變化。不過,後來因爲和家裏吵架,居然意外有兩天晚上,可以慢慢地、好好地逛逛這座城市淺羽最熟悉、最愛的一小部分,也算是一點點開心和幸運的事情。
问少's avatar

修复 Ubuntu 下拼音输入法崩溃问题

最近在使用 Ubuntu 18.04 的过程中,遇到了一个拼音输入法总是在选字的时候崩溃的问题。

崩溃表现

crashed with SIGABRT in __assert_fail_base()

具体表现为:在打字时,无法使用数字键选择字词,鼠标点选也无效,只能按空格打出第一个字词。当按数字键选择字词时,输入法会崩溃,并输出字母和数字,例如我想打出“谷歌”,“谷歌”在候选列表第二个位置,按下 2,输入法崩溃,输出 guge2

我搜索了一下,并没有找到解决办法,只好退而求其次,使用 fcitx 代替了 ibus,就这么过了半个月。然而我今天再次搜索的时候竟然找到了解决办法:Selecting a number does not always return a Chinese character with ibus pinyin

解决办法

直接删除输入法的缓存就好:rm ~/.cache/ibus/libpinyin/*

Molunerfinn's avatar

Electron-vue开发实战5——开发插件系统之CLI部分

前言

祝大家2019年猪年新年快乐!本文较长,需要一定耐心看完哦~

前段时间,我用electron-vue开发了一款跨平台(目前支持主流三大桌面操作系统)的免费开源的图床上传应用——PicGo,在开发过程中踩了不少的坑,不仅来自应用的业务逻辑本身,也来自electron本身。在开发这个应用过程中,我学了不少的东西。因为我也是从0开始学习electron,所以很多经历应该也能给初学、想学electron开发的同学们一些启发和指示。故而写一份Electron的开发实战经历,用最贴近实际工程项目开发的角度来阐述。希望能帮助到大家。

预计将会从几篇系列文章或方面来展开:

  1. electron-vue入门
  2. Main进程和Renderer进程的简单开发
  3. 引入基于Lodash的JSON database——lowdb
  4. 跨平台的一些兼容措施
  5. 通过CI发布以及更新的方式
  6. 开发插件系统——CLI部分
  7. 开发插件系统——GUI部分
  8. 想到再写…

说明

PicGo是采用electron-vue开发的,所以如果你会vue,那么跟着一起来学习将会比较快。如果你的技术栈是其他的诸如reactangular,那么纯按照本教程虽然在render端(可以理解为页面)的构建可能学习到的东西不多,不过在main端(electron的主进程)应该还是能学习到相应的知识的。

如果之前的文章没阅读的朋友可以先从之前的文章跟着看。

琴音's avatar

2019/1/26 19th Reborn

在我开始写这篇文章的时候,还有二十分钟我就将到达人生第十九个年头开始的标志点。怎么说呢,十八年里自己活得不算好也不算坏,无论是爱还是友情或是憎恨又或是什么被Cwist&Orange&Larma广泛认为是我矫情属性的重要象征的东西我都经历了一个遍。

今年也不想再写什么太矫情又空洞的东西吧。

作为一个Code Farmer,语言简洁一点是好事。那我也就不那么长篇大论,先给自己定下一个2019年的关键词吧。

选择

这个词在过去的一年里被我的说说、日记、残篇和备忘录反复提到,好像我是得了什么复读症状一样,自己都快把自己的耳朵磨出了茧子。但,做选择需要的勇气和承担选择后果所需要的勇气,都是我认为我暂时还没有的东西。

大概只是意气用事,而不是深思熟虑之后才下决心走上哪条道路。

说实话,在这样一个社会下,这样去做事未免过于幼稚又无趣,但当我失去思考的能力,也放弃了生活的热情之后,做出那些让自己悔之晚矣的事情,似乎也没什么在意料之外。

做个选择吧。

第十九年,to be or not to be.

好时代,来临吧。

Molunerfinn's avatar

2018小结

终于把研究生开题的事情弄得差不多了,可以抽空写一下2018年的小结了。

Molunerfinn's avatar

图床「神器」PicGo v2.0更新,插件系统终于来了

前言

距离上次更新(v1.6.2)已经过去了5个月,很抱歉2.0版本来得这么晚。本来想着在18年12月(PicGo一周年的时候)发布2.0版本,但是无奈正值研究生开题期间,需要花费不少时间(不然毕不了业了T T),所以这个大版本姗姗来迟。不过从这个版本开始,正式支持插件系统,发挥你们的无限想象,PicGo也能成为一个极致的效率工具。

除了发布PicGo 2.0本体,一同发布的还有PicGo-Core(PicGo 2.0的底层,支持CLI和API调用),以及VSCode的PicGo插件vs-picgo等。

linkthis's avatar

Rsync使用文档

由于太菜导致反复翻车
琴音's avatar

Primo Cache试用——HDD Boost#Tech 1

文件越来越大,电影、游戏,甚至一些高保真度的音乐都动辄以GBytes作为单位计算空间占用时,HDD的读取速度就不那么尽如人意了。

作为一个算是老资历的游戏玩家,我可怜的5400rpm的希捷酷鱼每每让我在WOW读蓝条、R6转圈、以及AC:Odyssey开放世界加载地图和Warframe进入福尔图娜&希图斯时都能泡杯咖啡,耗时之久令我不禁怀疑是否它已经有了坏道。

当然,我并不是什么人民币玩家,也就不存在自掏腰包买一根2TB SSD或是一根Optane的究极举措——实话说这块HDD还是我去魔都的时候上一块WD 1TB坏掉时候换的,这才没到三个月。

嗯,是挺头疼的。

四处爬帖,最后爬到一个看起来很Dio的软件。

Primo Cache.

仔细看了看官网说明文档。

官方说明

也恰巧是有一点学过的东西,我仔细研究了一会。

简单来说,PCache拦截System至HDD的I/O请求,拦截同时检测读取数据是否已经在PCache中存储,若有,则直接使用其存储在内存中的Cache。

(吐槽:其实这大概已经是个过时的软件了。)

下载安装之后,设置界面如下。

在这里解释一下吧。

1.提升读性能:使用一级缓存和二级缓存提升顺序&随机读取的性能

2.提升读性能(仅使用SSD缓存):仅使用SSD作为二级缓存,提升顺序读取性能

3.提升写性能:和1相同,只不过提升的是写性能

4.提升读&写性能:包括以上所有,即:使用一级缓存和二级缓存提升综合读写性能

个人建议无脑选4,但如果只是为了游戏加载的话2就可以了。(当然,我还要跑AE、Pr……必然选4)。

再向下要我们选择自己需要缓存的卷了。

当然是选择存储了大量杂物的——HDD。(这里我小心翼翼徘徊了半天)

要强调的事情是PrimoCache的缓存来自于多余的内存,所以内存不够的人就直接叉掉吧。

接下来设置缓存粒度、内存设置为缓存的大小等一系列最终设置。

由于我的电脑有16GB的内存,我刻意分出了3GB的大小用于加速HDD。

缓存粒度越小,缓存的速度就越快,缓存策略则是设置缓存用于加速的趋势,而延时写入则是必须注意的一个地方。

Primo Cache的缓存是基于内存RAM实现的,所以当断电时缓存会被清空。延时写入会让写入硬盘的数据滞留在缓存中,在预设的延时之后才写入硬盘,在这个延时中若是电脑断电、死机、重启等一系列故障,内存将因此刷新,进而损毁数据甚至缓存盘。

要不要开这个选项,我个人认为需要思考。

然后确定,大功告成。

这就是最终的效果。

个人使用一周之后,感觉效果还是不错的。但是要不要拿内存换硬盘的性能……仁者见仁智者见智吧。

琴音's avatar

域名更换公告

鉴于.tk域名运营商Freenom近日来经常出现的不经告知直接收回域名的恶劣行为,我刚刚注册了一个新的域名,亦即现在的www.talrasha.me,从前那个域名将在到期之后彻底停止解析

琴音's avatar

无题#17

x的真是服了在自习室外放微信提示音的傻逼。

问少's avatar

又一次更换了评论系统

去年暑期的时候 HyperComments 开始收费,并且不给钱就不给看历史数据,一声不吭就直接进入收费模式,这也太狗了。去他妈的 HyperComments 吧,不用就不用了。于是在那个时候换了 Disqus 这个经典的评论系统。

Disqus 虽好,但国内访问不了,我那时还感叹了一下,以后评论随缘吧(说的好像能访问就有很多评论一样)。思来想去,国内用户看不到评论系统,少了点东西,那样的话看我这个网站总是怪怪的。

今天在升级 NexT 主题时,又详细看了一下配置信息,看到了 Gitment 和 Gitalk 这个玩意儿,在 GitHub 的仓库中开 Issue 为每个页面记录评论。不得不说,这个思路很清奇。本身 Hexo 博客就是托管在 GitHub 仓库中的,那么一个 Issue 就对应一个文章,这个 Issue 下面的评论就对应文章下面的评论。

现在你看到的评论框就是 Gitalk 了,比 Gitment 更新的勤快,比 Gitment 维护的人多,比 Gitment 好看,是我选择 Gitalk 的理由。

有一点不太方便的地方就是,每篇文章都需要手动初始化评论,不能自动初始化。新文章的初始化还简单些,就是访问一下页面,老文章的初始化就有些蛋疼,毕竟也有几十个呢。还好网上找到了一键脚本,得以解决这个问题。话虽是这么说,但我还是没有用一键脚本,仍是访问了每篇文章来初始化。别问为什么,就是想顺便回顾一下历史。

现在,国内用户终于可以访问我的评论系统了,不过真的会有多少人来评论吗?#捂脸

琴音's avatar

我们还有未来的时候#16

这是一篇受密码保护的文章,您需要提供访问密码:

linkthis's avatar

Telegram RSS机器人

信任Systemd的人,最终……

搭建一个Telegram的RSSBot,可以方便地订阅自己感兴趣的信息源,并实时接收RSS消息推送。

准备Telegram Bot

首先需要申请一个Telegram的机器人,即Bot。在Telegram中找到@BotFather,开始对话并根据提示创建一个新的Bot即可,在创建过程中生成的API TOKEN需要记住以便使用。
然后输入mybots找到刚才创建的Bot并选择,点击Edit Bot,选择Edit Commands输入RSSBot的命令:

rss       - 显示当前订阅的 RSS 列表,加 raw 参数显示链接
sub       - 订阅一个 RSS: /sub http://example.com/feed.xml
unsub     - 退订一个 RSS: /unsub http://example.com/feed.xml
unsubthis - 使用此命令回复想要退订的 RSS 消息即可退订, 不支持 Channel
export    - 导出为 OPML

安装RSSBot

使用iovxw开源的项目
选择使用预编译版本以节约时间,Linux版本为musl静态链接, 无需其他依赖。

1
2
3
apt install unzip
wget https://github.com/iovxw/rssbot/releases/download/v1.4.3/rssbot-v1.4.3-linux.zip
unzip rssbot-v1.4.3-linux.zip

解压完成之后即可运行:

1
./rssbot DATAFILE TELEGRAM-BOT-TOKEN

DATAFILE为数据库保存路径(JSON文件,无需手动创建)。TELEGRAM-BOT-TOKEN为刚才创建的机器人对应的Token

Systemd配置

为了保证RSSbot持续运行和管理,使用Systemd进行操作。
执行vi /etc/systemd/system/rssbot.service,参考以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=A RSS Bot
After=network.target
Wants=network.target

[Service]
Type=simple
WorkingDirectory=/home/rss
ExecStart=/home/rss/rssbot DATAFILE TELEGRAM-BOT-TOKEN
Restart=on-failure
RestartSec=10
User=rss

[Install]
WantedBy=multi-user.target

然后执行:

1
2
3
systemctl daemon-reload
systemctl enable rssbot
systemctl start rssbot

如果需要定时重启等操作,编写对应的Time文件即可。

Bot命令示例

个人订阅:/sub <RSS 地址>
频道订阅:/sub @channelname <RSS 地址>
查看个人订阅列表:/rss
查看个人订阅列表并显示订阅链接:/rss raw
如果需要把机器人加入频道,则机器人的身份需要为管理员

Systemd真香。
本文采用CC BY-NC-ND 4.0许可协议进行许可,转载请注明出处。

本文最后更新时间为:2019-05-29-Wednesday-08:45:53 PM

琴音's avatar

Waiting#15

愿你的现实待你温柔。

linkthis's avatar

Openwrt IPv6 配置

从起点出发然后回到起点。

OpenWRT IPv6

之前一直只有教育网或者局部地区测试的IPv6现在已经大范围推开,大部分地区的ISP均正确部署了IPv6。通常来说,Openwrt获取IPv6的方式有三种:中继、穿透和NAT,由于ISP已经提供了IPv6和某些方案的缺陷,所以只采用中继的方法。

准备

首先将光猫的模式调为桥接或者混合模式,然后通过电脑拨号确认ISP是否正确配置IPv6。
然后升级路由器的Openwrt的版本,最好不要低于17.01,否则odhcpd可能会出现问题,当然更老的版本也能正确获取IPv6,不过你可能需要每隔一段时间就重启一次odhcpd

配置

从Openwrt 15.xx(即CC版本)开始,默认的初始设置中就会含有wan6,无需安装其它的软件。
由于Openwrt默认分配IPv6私网网段,首先应该删除网络>接口页面内全局网络选项IPv6 ULA 前缀中以fd开头的/64随机IPv6地址段并保存生效。其实这个时候,在较新版本的Openwrt上面应该已经成功获取了IPv6
然后我们需要修改/etc/config/dhcp文件,使用无状态地址自动配置(SLAAC)IPv6,而不是DHCPv6。配置示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
config dhcp 'lan'
        option interface 'lan'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv6 'relay'
        option ra 'relay'
        option ndp 'relay'
        option ra_management '1'

config dhcp 'wan'
        option interface 'wan'
        option ignore '1'
        option dhcpv6 'disabled'
        option ndp 'relay'
        option ra 'relay'
        option master '1'

config dhcp 'wan6'
        option dhcpv6 'relay'
        option ra 'relay'
        option ndp 'relay'
        option master '1'

配置完成之后需要重启network服务,以便接入终端获取IPv6地址:

1
/etc/init.d/network restart

至此所有的客户端包括路由器均可获得可用的IPv6地址,不过在Windows下面,由于祖传BUG的原因,你可能无法正常使用IPv6,需要在CMD中执行如下命令:

ipconfig /release6
ipconfig /renew6

不需要重启,即可生效,是否有效需要看具体网络配置。

体验

体验并不优秀,客户端的地址无法ping通,访问海外地址也出现问题。在客户端造成了1分钟左右的延时。大概就是鸡肋,所以只在路由器上面保留了IPv6地址。

咸鱼IPv6立即关闭,获取更好的网络体验。
本文采用CC BY-NC-ND 4.0许可协议进行许可,转载请注明出处。

本文最后更新时间为:2019-05-19-Sunday-09:47:19 PM

vitech's avatar

ElasticSearch 配置Logstash导入mysql数据库

网上教程不少,但是大多对新手不太友好,细节也不太好,这里针对ElasticSearch小白。

以ElasticSearch 5.6.12 和 LogStash 5.6.13为例。这两个的安装从略。
尽量保证两者版本不要相差太多。考虑到LogStash只作为管道,版本不需要一致。

先到LogStash目录下安装JDBC插件

cd /opt/logstash
bin/plugin install logstash-input-jdbc

如果是windows下,请自行在可执行文件后加上.bat

安装完之后开始导入,这个导入过程我们编写一个conf文件实现,这里以logstash.conf为例,为了方便可以直接在logstash/bin下创建一个logstash.conf

input {
  jdbc { 
    # "your-database" 是数据库名    
    jdbc_connection_string => "jdbc:mysql://localhost:3306/your-database"  
    #mysql数据库用户名密码
    jdbc_user => "root" 
    jdbc_password => "********"
    #schedule 可选,如果有schedule则会自动同步,这里意思是每一分钟同步一次,没有就只同步一次。具体的见官方文档
    #schedule => "* * * * *"
    #这里需要使用一个mysql连接库,文末有下载地址,自行下载后随便放一个地方,这里只是举例
    jdbc_driver_library => "/usr/local/logstash/mysql-connector-java-6.0.5.jar"
    jdbc_driver_class => "com.mysql.jdbc.Driver"
    #查询,这里只需要select一下即可,比如从your-schema数据表
    statement => "SELECT * FROM `your-schema`"
    }
  }
output {
  stdout { codec => json_lines }
  elasticsearch {
  "hosts" => "localhost:9200"
  #your-index是事件要被写进的索引 如果没有索引就新建一个
  "index" => "your-index"
  #your-type-name 只是数据集的分类,自定义,同类数据尽量使用同一个type
  "document_type" => "your-type-name"
  #可选,这里的意思是绑定原mysql表的id列作为主键,可以避免重复
  "document_id" => "%{id}"
  }
}

然后执行

cd /opt/logstash/bin
./logstash -f logstash.conf

可以看到一排输出,然后数据就注入成功了。

顺带一提,如果小白注入完数据发现有unassigned数据,或者说集群健康度不够,是因为现在的节点分片不够存储数据集的1份备份(默认一份)。只需要执行诸如

curl -XPUT 'localhost:9200/your-index/_settings' -d '{"number_of_replicas": 0}'

将备份数降低即可。

一个可用的Maven的mysql-connector-java-6.0.5.jar

vitech's avatar

lnmp配置laravel/thinkphp时出现no input file specified的常见问题

lnmp的域名绑定命令即使到最新的1.5版都是一套不太成熟的做法。
我们每次执行诸如lnmp vhost add时,都会在目录下生成一个类似这样的.user.ini文件

open_basedir=/home/wwwroot/your-project/:/tmp/:/proc/

.user.ini的作用是覆写php.ini中的部分参数,在这里来说,open_basedir在php.ini中可能有一个全局值,而在这个目录下有一个局部的值会覆盖全局值。

而open_basedir则是造成nginx/php-fpm 报错的罪魁祸首,这么说可能不恰当,因为.user.ini的本意是好的,其机理是限制php访问目录,举例来说,你在这个目录下配置的php文件只能操作/home/wwwroot/your-project/下的文件。

而这样就导致了我们在使用诸如laravel/ThinkPHP框架时的问题。比如我们在home/wwwroot下建立了名为your-project的laravel项目,但是lnmp绑定vhost时,按常理是要绑定到/public目录下的。因为/public下是整个网站的入口,这样一来就产生问题了:.user.ini中会生成/home/wwwroot/your-project/public/:/tmp/:/proc/这样的参数,然而这个项目的php是必须要有要调用/public外文件的权限的!这个问题的产生往往会让人难以排查,因为不管是浏览器输出,亦或是nginx和php-fpm的log都不会给出任何错误信息,一个隐藏在/public下的.user.ini文件很难让新手发觉出问题。

解决方案:

.user.ini被安全锁定了,先使用

chattr -i .user.ini

将其解锁,然后vim编辑去掉/public,再chattr +i .user.ini加锁。
当然你也可以直接解锁后删掉,这样损失了一定安全性,对于小项目或者本地项目倒没什么意义了。

Molunerfinn's avatar

一周一部好电影V【WEEK210 网络迷踪】

2018-11-11 WEEK210 网络迷踪

网络迷踪——————————————Searching

  • 导演:阿尼什·查甘蒂
  • 主演:约翰·赵/米切尔·拉/黛博拉·梅辛/约瑟夫·李/萨拉·米博·孙/亚历克丝·杰恩·高/梅金·刘/刘卡雅/多米尼克·霍夫曼/西尔维亚·米纳西安/梅丽莎·迪斯尼/康纳·麦克雷斯/科林·伍德尔/约瑟夫·约翰·谢尔勒/阿什丽·艾德纳/托马斯·巴布萨卡/朱莉·内桑森/罗伊·阿布拉姆森/盖奇·
    比尔托福/肖恩·奥布赖恩/瑞克·萨拉比亚/布拉德·阿布瑞尔/加布里埃尔D·安吉尔
  • 片长:102分钟
  • 影 片类型:剧情/悬疑/惊悚
  • 豆 瓣评分:8.7/10(from85,981users)
  • IMDB评分:7.8/10(from38,178users)
's avatar

硬改hexo-generator-feed使某些文章不被rss推送

前言

由于鄙人博客的rss加入了北邮人博客圈这么大佬的博客圈,所有的博客更新都会被整合。由于我太菜了,有些文章实在是拿不出手,放上去十分丢人,但是想作为自己的积累写下来,老是扔在草稿区也不是个事,所以就有了这么个想法。

前排提醒: 实现方式十分不优雅,有更好的方式还请各位指教

实现方式

RSS的文件生成应该和hexo是一个模式–模板渲染,直接在node_modules\hexo-generator-feed找到这个包

负责渲染每个文章的是

{% for post in posts.toArray() %}

存储需要渲染文章的是posts

在这个目录下搜索posts,在lib\generator.js找到

1
2
3
4
5
6
7
8
9
10
11
12
// @ line: 28
posts = posts.filter(function(post) {
return post.draft !== true;
});
// @ line: 40
var xml = template.render({
config: config,
url: url,
icon: icon,
posts: posts,
feed_url: config.root + feedConfig.path
});

filter函数是筛选器,大致用法:

1
2
3
4
5
var arr = ['A', '', 'B', null, undefined, 'C', '  '];
var r = arr.filter(function (s) {
return s && s.trim(); // 注意:IE9以下的版本没有trim()方法
});
r; // ['A', 'B', 'C']

修改如下:

1
2
3
4
// @ line: 28
posts = posts.filter(function(post) {
return post.draft !== true && post.DontInRss !== true;
});

这下,一会后不想加入RSS的文章只需要在文章属性上加上DontInRss: true就可以了。

瑟瑟发抖

作为一个在大佬之间瑟瑟发抖的萌新,只能瑟瑟发抖了。。。

's avatar

记一次痛失域名的经历

声明

我自己域名到期没续期,并且freenom已经给我发过邮件提醒我续期,但是我没看见,我自己的锅。

PS: 本站从之前域名(xice.cf)正式迁移到(xice.wang)现在已经完成了大部分服务的迁移工作,新域名的工信部备案已经完成,公安备案正在审核。

自己没看见,能赖谁?没有检讨自己就妄下结论实在不妥。freenom为我们提供免费的域名,实在是感谢,我也借此机会直接切换到可以备案的域名。

Gaojianli's avatar

即日起本站域名切换到gaojianli.me

一直以来,我都使用的是

Roy Binux's avatar

少女前线拖尸脚本 和 生成它的可视化工具

最近在玩少女前线,这是一个手机游戏,over。不是,就真的没有什么好讲的嘛,了解的人早有耳闻,不了解的就只要知道这是个手机游戏就好了,嗯。

然后,我会好好地,正常地,氪金地去玩这个游戏吗?不可能的,玩游戏哪有破解它有意思呢。当年破解 Ingress 是因为它用的 HTTPS 通信的,算是本行。百万亚瑟王是因为别人已经逆向好了,我只是写了一些 bot。现在这么办,玩不了了吗?作为一个不会安卓,不会逆向,不会汇编的菜鸡,那我只好上按键精灵了啊。于是乎,我找到了这个: AnkuLua

AnkuLua 是一個專注在自動化的Android App
基本自動化動作有:

  • 抓取螢幕並找尋指定圖案
  • 對找圖結果採取使用者要的動作(例如點擊、抓放(drag and drop)、打字…等等)

最重要的是,它能运行 lua 脚本!虽然我是一个不会安卓,不会逆向,不会汇编的菜鸡,但是我会 lua 啊。

ankulua-vision

不过,在使用过程中发现,找寻指定图案,需要不断截图/裁剪,这样太麻烦了。于是我又用 electron 做了一个可视化的截图资源管理器 ankulua-vision,像这样的:

基本思路就是,一般游戏是由众多 UI 界面组成的,点击某个按钮能跳转到某个界面上去。那么通过截图,标注识别区域,那么程序就能知道游戏现在所处的界面。通过标注按钮区域,那么只需要 goto('battle'),程序就能自动规划从当前界面到 battle 的可行路径,然后点啊点啊就完成需要的操作了。这样一方面不需要自己去裁剪图片了,另一方面通过框架代码,在运行过程中能够有更多的错误检查,自动应对可能出现的各种异常。

理论上,对于点啊点的游戏,是能实现无代码的。即使不能,对于复杂的动作,也可以通过 lua 拓展。

源码在这里:https://github.com/binux/ankulua-vision

你依旧需要在安卓手机或者模拟器中安装 ankulua,然后加载生成的 start.lua 脚本。默认自带了一个简单的循环逻辑,运行后可以直接图形化界面配置运行。当然你也可以通过 lua 脚本拓展,除了 ankulua 本身的 API 可用之外,你也可以使用 stateMachine 这套界面跳转逻辑 API,重用简化步骤。stateMachine 的 API 在 README 中有简略的文档说明。

源码使用 GPLv3 或 MIT 许可证,取决于第一个有效 PR(例如 fix typo 不算),如果第一个 PR 之前有商业化需求或者 PR 作者要求,则 MIT。

少女前线拖尸脚本

WARNING: 任何使用脚本的行为都是官方禁止的,我不对下文所述任何内容以及其后果负责

于是,这里就是 少女前线的拖尸脚本:

https://github.com/binux/binux_github_com/releases/download/gf/shojo.zip

同时它也是一个 ankulua-vision 的项目,你可以通过 ankulua-vision 打开这个项目目录,调整截屏或者按钮位置。

脚本实现的功能

  • 43e, 02, 52n 拖尸
  • 自动重启后勤
  • 自动强化或者分解人形
  • 自动修理

使用方法

  1. 根据 [填坑结束?][失了智]萌新向拖尸教学帖[更新8-1N相关] 一文准备好打手和阵型,一队练级队,二队补给队,52n 还需要 3 队狗粮队。
  2. 解压拷贝脚本到手机中,在 ankulua 中加载 start.lua。
  3. 在启动界面中选择你的两个打手(每轮结束后,两个打手会交换),选择拖尸任务,如果仅自动后勤,选择 null 就好了。

其中 52n 会在战斗中撤退 5, 8 号位 (见 NGA 文 “43e的说明” 展开部分),02 在选择 m4a1 时会撤退 1, 7 号位。

然后开始吧!

WARNING: 任何使用脚本的行为都是官方禁止的,我不对上文所述任何内容以及其后果负责

over

问少's avatar

COM6506

Week 02

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Person {
String name;
double weight;
double height;

public Person(String name, double weight, double height) {
this.name = name;
this.weight = weight;
this.height = height;
}

public String getName() {
return name;
}

public double getWeight() {
return weight;
}

public double getHeight() {
return height;
}

public static void main(String[] args) {
Person jeff = new Person("Jeff", 72.4, 2.2);
Person jim = new Person("Jim", 65, 1.7);
System.out.println("Jeff is " + jeff.getHeight() + "m tall.");
System.out.println("Jim is " + jim.getHeight() + "m tall.");
}
}
问少's avatar

COM6516

Week01-02

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/*
* HelloWorld.java
* A traditional Hello World program!
*/

// In Java, all programs reside in a class. This class is called HelloWorld,
// and should be saved in a file called HelloWorld.java. This class has a single
// method called main, which is the entry point to the program.
//
// Compiling the class with javac HelloWorld.java will produce a bytecode file
// called HelloWorld.class if compilation is successful. This bytecode can then
// be run on any machine with a java bytecode interpreter. You can run the
// bytecode in a console by typing java HelloWorld.

public class HelloWorld {
public static void main(String[] arg) {

String helloString = "Hello";
String worldString = "World!";

// In Java the System.out.println command displays the argument to the
// console. However the command below doesn't work, because helloWorldAString
// has not been declared. Try compiling this file to see what happens,
// and take a careful look at the error message that is produced.

System.out.println(helloString + " " + worldString);

// In Java, we can use the '+' operator to concatenate strings,
// so to fix this problem, either change the argument passed to the
// System.out.println method from (helloWorldString) to
// (helloString + " " + worldString)
// or declare the variable helloWorldString before it is used by
// System.out.println by inserting
// String helloWorldString = helloString + " " + worldString;

// In Java a variable can be declared anywhere in the code, so it is
// possible to declare a variable just before it is used, which makes for
// code that is easier to read and understand.

// It is conventional to use mixed case for variable names and method
// names in Java, with with the first letter lower case, and then the
// first letter of each internal word in upper case -- e.g. helloString.
// Class names start with a capital letter -- e.g. HelloWorld.java

// details at: http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-135099.html

}
}
Kay's avatar

如何入门科学上网

每当我们希望通过 Facebook 与国际友人聊天,想在 Twitter 看川普吹嘘,或是想上 Youtube …

继续阅读“如何入门科学上网”

Kay's avatar

果园小学期的个人感想

很久之前就了解到会有这次小学期,听说是几个同学组成一组,完成一个代码量相对较大的程序。年轻气盛的我还满怀着期待 …

继续阅读“果园小学期的个人感想”

Gaojianli's avatar

树莓派添加温控风扇(二)

前言

上回说到,对于arm64的系统来说,目前并没有一个库可以支持对GPIO的调用。那么接下来摆在我面前的就三条路:

  1. 修改setup.c,让cpuinfo中包含相应的Hardware信息,随后重新编译内核
  2. 修改wiringPi源码
  3. 放弃使用库

可行的方法

上面三个选项中,1和2显然是极其不现实的,因此我决定采用第三条路。在之前那个issue中,我看到了这样一种用法:

Gaojianli's avatar

树莓派添加温控风扇(一)

前言

前不久不知道树莓派抽什么风,风扇的噪音突然变得奇大无比,弄得潇叫苦连连。虽然我亲自去听了之后觉得声音远远比不上他的神舟和那台安装了FreeBSD的古董机,但毕竟有求于人,这样下去也不是个办法。稍加分析不难得出,风扇声音大是因为24小时常开导致了积灰和磨损,尤其是前者更是难以避免。而我树莓派大部分时候都处于闲置状态,风扇其实是没必要24小时上线的。那么,能不能让风扇按需启动呢?这样一来可以改善噪音问题,同时树莓派困扰许久的供电不足问题也能够得到相应的改善。

Brian Lee's avatar

有向图

《Algorithm》(Sedgewick)笔记:有向图


术语

一幅有 方向性的图 (或

Brian Lee's avatar

并查集

《Algorithm》(Sedgewick)笔记:并查集


动态连通性

动态连通性

Brian Lee's avatar

广度优先搜索

《Algorithm》(Sedgewick)笔记:广度优先搜索


原理

遍历图G 时,要找到从sv 的最短路径,从s 开始,在所有一条边就可以到达的顶点中寻找v ,如果找不到就继续在与s 距离两条边的所有顶点中查找v ,如此一直进行。当两次寻找相遇时,合二为一。直到查找到最短路径。


相关问题

单点最短路径

给定一幅图和一个起点s ,回答“从s 到给定目的顶点v 是否存在一条路径?如果有,找出其中最短的那条”


实现

使用一个队列来保存所有已经被标记过但其邻接表还未被检查过的顶点。

先将起点加入队列,然后重复以下步骤直到队列为空:

  1. 取队列中的下一个顶点v 并标记它
  2. 将与v 相邻的所有未被标记过的顶点加入队列

搜索过程

  1. 首先将顶点0 标记并加入队列
  2. 从队列中删去顶点0 并将其邻居顶点215 标记、加入路径,并加入队列中
  3. 从队列中删除顶点2 并检查其相邻顶点,01 已被标记,将34 标记、加入路径并加入队列
  4. 从队列中删除顶点0 并检查其相邻顶点,发现已经全被标记,于是跳过
  5. 从队列中删除顶点5 并检查其相邻顶点,发现已经全被标记,于是跳过
  6. 从队列中删除顶点3 并检查其相邻顶点,发现已经全被标记,于是跳过
  7. 从队列中删除顶点4 并检查其相邻顶点,发现已经全被标记,于是跳过

代码

public class BFS {    private boolean[] marked;   //到达该顶点的最短路径是否已知    private int[] edgeTo;   //到达该顶点已知路径上最后一个顶点    private int s;  //起点    public BFS(Graph G, int s) {        marked = new boolean[G.V()];        edgeTo = new int[G.V()];        this.s = s;        bfs(G, s);    }    private void bfs(Graph G, int s) {        Queue<Integer> queue = new LinkedList<>();        marked[s] = true;   //标记起点        queue.offer(s);     //起点加入队列        while (!queue.isEmpty()) {            int v = queue.poll();   //从队列中删去下一顶点            for (int w : G.adj(v)) {                if (!marked[w]) {   //对每个未被标记的相邻结点                    edgeTo[w] = v;  //保存最短路径的最后一条边                    marked[w] = true;   //标记它,因为最短路径已知                    queue.offer(w); //将它添加到队列中                }            }        }    }    public boolean hasPathTo(int v) {        return marked[v];    }    public Iterable<Integer> pathTo(int v) {        if (!hasPathTo(v))  return null;        Stack<Integer> pathReverse = new Stack<>();        for (int x = v; x != s; x = edgeTo[x])            pathReverse.push(x);        pathReverse.push(s);        Queue<Integer> path = new LinkedList<>();        while (!pathReverse.isEmpty())            path.offer(pathReverse.pop());        return path;    }}

DFS与BFS区别

  • 深度优先搜索搜索一幅图的方式是寻找离起点更远的顶点,只在碰到死胡同时才访问近处的顶点;广度优先搜索会首先覆盖起点附近的顶点,只在临近的所有顶点都被访问了之后才向前进。
  • 深度优先搜索不断深入图中并在栈中保存了所有分叉的顶点;广度优先搜索则像扇面一样扫描图,用一个队列保存访问过的最前端的顶点。
  • 深度优先遍历算法借助于 结构实现;广度优先遍历算法借助于队列 结构实现。

源代码

https://github.com/XutongLi/Algorithm-Learn/tree/master/src/S4_Graphs/S4_1_Undirected_Graph/S4_1_5_Breadth_First_Search


's avatar

记在Windows平台上将proto翻译为JS的一个小坑

研究gRPC的时候,接触到了proto文件,现阶段我觉得这应该是一个可以翻译成各种语言、并且可以使用gRPC进行极其方便的远程调用的描述数据结构的文件。这次记录一下自己的愚蠢行为。

Brian Lee's avatar

深度优先搜索

《Algorithm》(Sedgewick)笔记:深度优先搜索


原理

要搜索一幅图,用一个递归方法来遍历所有顶点。在访问其

Brian Lee's avatar

无向图

《Algorithm》(Sedgewick)笔记:无向图


定义

无向图是由一组顶点和一组能够将两个顶点相连的边组成的。边仅

Brian Lee's avatar

散列表

《Algorithm》(Sedgewick)笔记:散列表


原理

在记录的存储地址和它的关键字之间建立一个确定的对应关系;这

Brian Lee's avatar

二分查找树

《Algorithm》(Sedgewick)笔记:二分查找树


原理

一棵 二叉查找树

Brian Lee's avatar

二分查找

《Algorithm》(Sedgewick)笔记:二分查找


原理

  • 在数组有序的前提下
  • 先将被查找的键和子数组的中间键比较,如果被查找的键小于中间键,就在左子数组查找,大于就在右子数组查找,否则中间键就是要找的键
  • 若表中存在该键,则返回该键的位置
  • 否则返回小于该键的元素数量

时间复杂度

$O(logN)$

分析

令 $C(N)$ 为在大小为 $N$ 的数组中查找一个键所需进行的比较次数。

显然有 $C(0) = 0$ 、$C(1)=1$

对于 $N>0$ 可得到归纳关系式:

$C(N)\leq C(\lfloor N/2 \rfloor)+1$

无论查找会在中间元素的左侧还是右侧继续,子数组大小都不会超过 $\lfloor N/2 \rfloor$ ,需要一次比较来检查中间元素和被查找的键是否相等,并决定继续查找左子数组还是右子数组。

当 $N=2^n-1$ 时,$\lfloor N/2 \rfloor=2^{n-1}+1$ ,

迭代得:

$C(2^n-1)\leq C(2^0)+n$

得:$C(N)=C(2^n)\leq n+1<lgN+1$


图示


代码

非递归

public static int binarySearch (int[] integer, int n, int key) {        int low = 0;        int high = n - 1;        while (low <= high) {            int mid = (low + high) / 2;            if (key < integer[mid]) {                high = mid - 1;            }            else if (key > integer[mid]){                low = mid + 1;            }            else {                return mid; //查找到            }        }        return low;  //未查找到,返回比其少的元素数量    }

递归

public static int search (int[] integer, int key) {        int lo = 0, hi = integer.length - 1;        return binarySearch(integer, key, lo, hi);    }public static int binarySearch (int[] integer,  int key, int lo, int hi) {        if (lo > hi)            return lo;    //未查找到,返回比其少的元素数量        int mid = (lo + hi) / 2;        if (integer[mid] == key)            return mid;        else if (integer[mid] > key)            return binarySearch(integer, key, 0, mid - 1);        else            return binarySearch(integer, key, mid + 1, hi);    }

源代码

https://github.com/XutongLi/Algorithm-Learn/blob/master/src/S3_Searching/S3_1_SymbolTables/S3_1_5_BinarySearch/BinarySearch.java


Brian Lee's avatar

TopK问题

Topk 问题,即求得 N 个乱序元素中第 k 大(小)的元素,是一个很经典的问题。在此文章中,我总结了自己对此问题的思路。


思路

Dimpurr's avatar

钉子的谜之 SETUP 18 @ Ningen

本文原载于 人间 / Dimpurr Cheny ,前文 钉子的谜之 SETUP (2014) 。

?‍? 简要介绍一下自己,并且谈谈正在做什么?

这里钉子,现役帝都大学生。曾经写写画画做过不少事情,当过宅圈内知名前端博主,设计过几个流行的 WordPress 主题,发起过一点音乐社区相关小项目,都已经成为过去。大一以来,唯一的成就是为了拯救北邮人技术组废部危机,不得不成为偶像,建立了 BYRIO 开源社区。目前在选择遵循自己内心去做游戏设计和编曲,还是顺应他人期待继续在 CASIA 和 MSRA 的 ML 搬砖日常前犹豫不决。

? 你使用的硬件有?

主役 MacBook Pro + Surface Pro ,经常同时携带 (虽然很重) ,前者用于影音处理、工程开发、平面设计、绘图板画画 (Wacom Intuos PTM CTH680) ,后者用于 PDF 阅读和批注、 OneNote 笔记、 Surface Pen 作画、推 Gal 和小游戏 (V-A HALL, FrostPunk) 。 Surface Pro 虽然性能有限,但是在轻薄的前提上能让自己在任何时空基本具备进行任何工作的能力。

宿舍配备 Linksys WRT1900AC v1 用于享受百兆校园网 (IPv6 免流 + 学校网络中心成员特权套餐) ,一块 26’ DELL UltraSharp Monitor U2415 外接屏一般连接 MBP 用于宿舍组团看 Rick and Morty 或少女歌剧、瀑布流展示作画和人体结构参考资料、工作时看论文和文档等,计划接上 Switch Dock 之后用来在宿舍玩舞力全开。配置 MIDIPLUS X6 键盘 + ATH-AD2000X 开放式大耳用于演奏。

随身 Sony XPERIA XZ1 ,佩戴 Moto 360 。 SHURE SE846 耳塞退烧,前端 iBasso DX90 和耳放 Sony PHA3 常年借给同学。 iPad mini 用于音游 (Cytus II, Arcera, Groove Coaster, Dynamix) , Nintendo Switch 用于 Party Game (分手厨房) 和沉迷死喷浪涂 (Splatoon) 。

? 你使用的软件有?

常年 macOS, Windows 和 Linux 跨平台用户,曾经是 OpenSUSE 党。 macOS 下剪贴板历史 Paste 和快速访问 Spotlight 重度用户, Win 对应工具是 Ditto 和 Keypirinha 。所有常用 App 必须选择跨平台解决方案, 必备滴答清单 + SimpleList 。日常 IM Telegram 和 QQ ,偶尔用 HexChat 挂 IRC 。念念不忘的 Mac 独占 App 有 Sketch, GarageBand, Agenda, OmniFocus 和 XLD 。念念不忘的 Win 或者 Unix 独占 App 没有,非要说的话 PC 游戏。

曾经 Sublime Text 2 党,如今 Visual Studio Code 忠实用户,必备插件是 background 自带魔理沙背景 + GitLens 。终端分别 iTerm2 和 Cmder / MobaXTerm 。 macOS 下用 SourceTree 做 Git GUI ,用 MAMP PRO 做服务器测试环境。写作环境 ByWord 和 Typora ,设计主 Sketch 辅 Axure 和 PhotoShop ,偶尔用 Illustrator 描矢量画或者 InDesign 做小册子。剪辑一般用 Final Cut Pro 或者 Premiere 。三维制作 3DS MAX 和 Blender 。

主要用 CLIP STUDIO PAINT 作画,新的拟真铅笔手感非常好。有时候会使用 Krita , Tyson 大大绘制的 Kiki 启动屏幕非常可爱,自带的丰富笔刷和镜像画笔等功能很能激发创作灵感, BYRIO 社区还组织参与过 Krita 中文文档的翻译工作,在此安利。

? 你梦想中的设备是怎么样的?

梦想是巨硬让 Surface Pro 性能、品控和售后再好一点,水果让 MacBook Pro 再便宜一点,索法不要搞 XZ2 这种歪门邪道好好出 XZP 这种全平衡侧面指纹带耳机孔的好手机。离开大学宿舍后可能会对个人工作站的设备有新的愿望,目前暂时并没有什么其他的梦想。

? 以下附图。

Surface Pro 桌面

Surface Pro 开始

MacBook Pro 桌面

MacBook Pro LaunchPad

本文来自 钉子の次元 - Dimpurr - 千里之行,始於足下。 ,原文地址 钉子的谜之 SETUP 18 @ Ningen

Brian Lee's avatar

排序算法总结

《Algorithm》(Sedgewick)笔记:排序算法总结


比较

算法是否稳定是否为原地排序最好时间平均时间最坏时间辅助空间
选择排序$O(n^2)$$O(n^2)$$O(n^2)$$O(1)$
插入排序$O(n)$$O(n^2)$$O(n^2)$$O(1)$
冒泡排序$O(n)$$O(n^2)$$O(n^2)$$O(1)$
希尔排序$O(n^{1.3})$$O(1)$
归并排序$O(nlogn)$$O(nlogn)$$O(nlogn)$$O(n)$
快速排序$O(nlogn)$$O(nlogn)$$O(n^2)$$O(logn)$
堆排序$O(nlogn)$$O(nlogn)$$O(nlogn)$$O(1)$

稳定 : 如果一个排序算法能够保留数组中重复元素的相对位置则可以被称为是稳定的。

原地排序 :原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。


一些结论

快速排序时最快的通用排序算法,因为它内循环中的指令很少,而且可以利用缓存。在使用三向切分之后,快速排序对于实际应用中的可能出现的某些分布的输入变成线性级别。

如果稳定性很重要而空间又不是问题,归并排序可能是最好的。

当n较小时,如(n<50),可采用直接插入或简单选择排序,前者是稳定排序,但后者通常记录移动次数少于前者

当n较大时,应采用时间复杂度为 $O(nlgn)$ 的排序方法(主要为快速排序和堆排序)

当n较大时,为避免顺序存储时大量移动记录的时间开销,可考虑用链表作为存储结构(如插入排序、归并排序、基数排序)


源代码

https://github.com/XutongLi/Algorithm-Learn/tree/master/src/S2_Sorting


Brian Lee's avatar

堆排序

《Algorithm》(Sedgewick)笔记:堆排序


原理

  • 使用一个面向最大元素的优先队列并重复删除最大元素
  • 分为两个阶段:堆的构造阶段下沉排序阶段

复杂度

时间复杂度

$O(NlogN)$

空间复杂度

$O(1)$


堆的构造

目的

将原始数组重新组织安排进一个堆中

实现

  • 可以从左到右遍历数组,将各元素插入堆中,每次插入后用swim()保证堆有序。时间复杂度为 $O(NlogN)$
  • 另一种更高效的方法是从右至左用sink()构造子堆。如果一个结点的两个子结点都已经是堆了,那么在该结点上调用sink()可以将它们变成一个堆。这个过程会递归地建立起堆。时间复杂度为 $O(N)$ 。在此我们采用这种方法。

图示


下沉排序

目的

从堆中按递减顺序取出所有元素并得到排序结果

实现

将堆中的最大元素删除,然后放入堆缩小数组后空出的位置

时间复杂度为 $NlogN$

图示


代码

public static void sort(Comparable[] a) {        int N = a.length - 1;        //构造堆        for (int k = N / 2; k >= 1; k--)            sink(a, k, N);        //下沉排序        while (N > 1) {            exch(a, 1, N--);            sink(a, 1, N);        }    }    private static void sink(Comparable[] a, int k, int N) {        while (2 * k <= N) {            int j = 2 * k;            if (j < N && less(a, j, j + 1))                j++;            if (!less(a, k, j))                break;            exch(a, k, j);            k = j;        }

排序过程


优缺点

优点

  • 是唯一能够同时最优地利用空间和时间的方法
  • 对记录数较大的文件很有效

缺点

  • 无法利用缓存。数组元素很少和相邻的其他元素进行比较,因此缓存未命中的次数要远远高于大多数比较都在相邻元素间进行的算法

源代码

https://github.com/XutongLi/Algorithm-Learn/blob/master/src/S2_Sorting/S2_4_5_HeapSort/HeapSort.java


Brian Lee's avatar

堆与优先队列

《Algorithm》(Sedgewick)笔记:堆与优先队列




Brian Lee's avatar

快速排序

《Algorithm》(Sedgewick)笔记:快速排序


原理

  • 快速排序是一种分治的排序算法
Kay's avatar

食其家の丼

食其家 食其家1982年创立于日本横滨,是以牛丼作为主力商品的快餐连锁店。在上海、江苏、浙江、北京、天津、广东等都有直营店。在北京门店并不多,一共6家,我这次去的是海淀区的翠微凯德MALL店。

关于丼

丼在汉语中:1、jǐng同“井”。2、dǎn 一为投物井中所发出的声音;二作姓。宋 邵思《姓解》卷一:“丼,蕃姓也” 而在日语中:可以指盛装饭或面的食具,又称丼钵;丼物,以碗盛装的饭上浇盖各式食材的日本庶民料理;另一则为投物井中所发出的声音。 所以食其家的丼应该就可以理解为日本盖浇饭的意思。日本最普遍的五大丼为GYUDON(牛丼)、KATSUDON(胜丼)、OYAKODON(亲子丼)、TENDON(天丼)及UNAGIDON(鳗丼)。而食其家以牛丼为主,也有鳗丼。

这家店

店面不大,是那种开放式的,正常的快餐店吧。桌子中间有个小架子,放着菜单、餐具、餐巾和酱料,旁边还有个服务铃。入店落座后,服务员会先上一杯茶,比起一般的快餐店,食其家的服务会稍好一些。值得一提的是食其家并不是先买单后用餐的,而是先用餐再买单的(导致了我忘了买单,尴尬地被叫了回去)。

这一餐

点得算是比较多。
牛肉/鳗鱼双拼丼
牛肉拌着酱汁渗入米饭里,感觉可以说是不错了。牛肉比较薄,肥瘦相间,既有脂肪饱和的口感,又不至于太腻。烤鳗鱼的口感也不错,入口有蒲烤的香,细嚼有鳗鱼的鲜。但是内侧脂肪有点多,口感有点油腻。
温泉蛋
调味裙带丝
章鱼小丸子
虽长得不怎么好看,盘也没码好,但味道还行。

在最后

之前也吃过别的食其家,相比之下,这家的环境不算好,可能是地段位置的原因。菜品都差不多,毕竟都是直营店,都是正常的日本快餐。服务的话,说不上很好,但由于普通的快餐店。
Brian Lee's avatar

归并排序

《Algorithm》(Sedgewick)笔记:归并排序


原理

Brian Lee's avatar

希尔排序

《Algorithm》(Sedgewick)笔记:希尔排序


原理

  • 改进了插入排序,交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序
  • 希尔排序的思想是使数组中任意间隔为h的元素都是有序的,这样的数组被称为h有序数组。换句话说,一个h有序数组就是h个互相独立的有序数组编织在一起组成的一个数组

复杂度

时间复杂度

不超过$O(n^2)$ ,当$n$ 较大时,比较和移动次数约在$n^{1.25}$ 到$1.6n^{1.25}$

空间复杂度

$O(1)$


图示


代码

public static void sort(Comparable[] a) {        int N = a.length;        int h = 1;        while (h < N / 3)            h = 3 * h + 1;        while (h >= 1) {            //分别进行插入排序            for (int i = h; i < N; i++) {                for (int j = i; j >= h && less(a[j], a[j - h]); j -= h)                    exch(a, j, j - h);            }            h = h / 3;        }    }

上述代码使用了序列$\frac{1}{2}(3^k-1)$ ,从$N/3$ 开始递减至$1$

序列计算:

$h_{k+1}=3\times h_k+1 (h_1=1)$

$h_{k+1}+\frac{1}{2} = 3(h_k+\frac{1}{2})$

$\therefore h_k+\frac{1}{2}= \frac{3}{2}\times 3^{k-1}$

$\therefore h_k=\frac{1}{2}(3^k-1)$


特点

  • 希尔排序更高效的原因是它权衡了子数组的规模和有效性
  • 时间复杂度取决于N与增量序列
  • 如何选择最佳增量序列,目前尚未解决,但最后一个增量值必须为1,且避免增量序列中的值(尤其是相邻的值)有公因子

源码

https://github.com/XutongLi/Algorithm-Learn/blob/master/src/S2_Sorting/S2_1_6_ShellSort/ShellSort.java


Brian Lee's avatar

冒泡排序

算法笔记:冒泡排序


原理

  1. 比较相邻的元素,如果第一个比第二个大,交换这两个元素
  2. 对每一对相邻元素进行同样的工作,从开始第一对到结尾最后一对。这步做完后,最后的元素会是最大的数
  3. 重复以上步骤,除了已选出的元素,直到没有任何一对元素需要比较,则序列有序

复杂度

时间复杂度

$O(n^2)$

空间复杂度

$O(1)$


图示


代码

实现一

最优情况$O(n^2)$

public static void sort(Comparable[] a) {        int N = a.length;        for (int i = 0; i < N; i++) {            for (int j = 1; j < N - i; j++) {                if (less(a[j], a[j - 1]))                    exch(a, j, j - 1);            }        }    }

实现二

最优情况$O(n)$

优化点 :由于冒泡排序要遍历整个未排好的部分,如果在整个排序过程中没有交换,我们就可断定列表已经排好。因此可以改良冒泡排序,使其在已知列表排好的情况下提前结束。

public static void sort2(Comparable[] a) {        int N = a.length;        boolean isExch = true;        for (int i = 0; i < N && isExch; i++) {            isExch = false;            for (int j = 1; j < N - i; j++) {                if (less(a[j], a[j - 1])) {                    exch(a, j, j - 1);                    isExch = true;                }            }        }    }

实现三

最优情况$O(n)$

优化点 :记录已排好序的位置,之后的遍历到此位置就可以停止。

public static void sort3(Comparable[] a) {        int N = a.length;        boolean isExch = true;        int tail = N, temp = N;        for (int i = 0; i < N && isExch; i++) {            isExch = false;            for (int j = 1; j < tail; j++) {                if (less(a[j], a[j - 1])) {                    exch(a, j, j - 1);                    isExch = true;                    temp = j;                }            }            tail = temp;        }    }

特点

  • 每进行一趟排序,就会少比较一次,因为每进行一趟排序都会找出一个较大值

源码

https://github.com/XutongLi/Algorithm-Learn/blob/master/src/S2_Sorting/Others_Bubble_Sort/Bubble.java


Kay's avatar

初入股市的一点想法……

成年以来,我尝试了许多以前因为各种原因不能做的事情,其中一样就是炒股。

如何入门炒股

首先得选择一家靠谱的证券公司。何谓靠谱的证券公司?看看中国证监会公布2018年证券公司分类结果吧。而我选择了AA级的广发证券,大概是因为在广东比较有名。关于广发证券与广发银行,广发证券的前身是1991年9月8日成立的广东发展银行(简称广发银行)证券部。1993年末,作为广发银行子公司的广东广发证券公司正式成立。2001年,通过增资扩股,改制为广发证券股份有限公司,广发银行仍作为其第一大股东。1999年5月,根据银证分离的要求,广发银行将广发证券股权全部转让出去,成为两个完全独立的公司。
然后开一个股票账户。可以带好身份证等证件去最方便的营业部开户,但广发证券实现了非常便捷的线上开户。下载APP,填写和上传一些资料,阅读并同意一些条款后,就可以注册上交所和深交所的账户了,按规定开户费用是深圳证券账户50元,上海证券账户40元,共90元,但是有些营业所直接垫付了,不需要交开户费,还有些是交部分开户费,而我开户的营业部是先帮我垫付了,说是销户的时候再交,大概是想防止用户流失吧。
再之后就该注入资金了,先绑定银行卡,再银行转证券,然后就能看到资金转入了账户中的现金。
有了现金,就该选一只股票了。至于怎么选,那就太深奥了。投资有风险,入市需谨慎。选好后就可以买入了,可以选择合适的买入价格和买入数量。国内是以100股为一手,交易的最小单位也是一手,也就是说最少也要买100股。对于像我一样的小白来说,最好先从低价的,稳健的,少量的股票入手,先试试水。还有国内的交易时间是工作日的早上9:30-11:30和下午1:00-3:00,其他时间可以先委托。可以使用一些软件来分析股票,像同花顺、大智慧。

初入股市

前一天晚上抱着试试的心态,以3.65的价格委托买入天津松江(600225)一手,也就365元。第二天,几番波动后,竟然涨停了!第一次买股票就涨停,还行。之后,我选择了见好就收,在T+1日就以4.16的价格卖出了。算了一下,盈利51元,也就一顿饭钱吧,毕竟只投入了300+r。设想一番,如果投入的是三百万,就能赚一辆不错的轿车了。股市还是挺刺激的。初入股市,小获成功。

Brian Lee's avatar

插入排序

《Algorithm》(Sedgewick)笔记:插入排序


原理

  1. 将每一个元素插入到其他已经有序的元素中的适当位置
  2. 为了给要插入的元素腾出空间,需要将其余所有元素在插入之前都向右移动一位

复杂度

时间复杂度

$O(n^2)$

空间复杂度

$O(1)$


图示


代码

public static void sort(Comparable[] a) {    int N = a.length;    for (int i = 1; i < N; i++) {        for (int j = i; j > 0 && less(a[j], a[j - 1]); j--)            exch(a, j , j - 1);    }}

特点

  • 插入排序所需要的时间取决于输入中元素的初始顺序
  • 插入排序对于部分有序数组十分高效,也很适合小规模数组

源码

https://github.com/XutongLi/Algorithm-Learn/blob/master/src/S2_Sorting/S2_1_3_Insertion_Sort/Insertion.java


Brian Lee's avatar

选择排序

《Algorithm》(Sedgewick)笔记:选择排序


原理

  1. 找到数组中最小的那个元素
  2. 将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)
  3. 在剩下的元素中找到最小的元素,将它与第二个元素交换位置
  4. 直到将整个数组排序

复杂度

时间复杂度

$O(n^2)$

空间复杂度

$O(1)$


图示


代码

public static void sort(Comparable[] a) {        int N = a.length;        for (int i = 0; i < N; i++) {            int min = i;            for (int j = i + 1; j < N; j++) {                if (less(a[j], a[min]))                    min = j;            }            exch(a, i, min);        }    }

特点

运行时间和输入无关

有序数组或值全部相等的数组和一个元素随机排列的数组所用的排序时间一样长。

数据移动最少

每次交换都会改变两个数组元素的值,因此选择排序用了N次交换,交换次数和数组的大小是线性关系。其他任何排序算法都不具备这个特性。


源码

https://github.com/XutongLi/Algorithm-Learn/blob/master/src/S2_Sorting/S2_1_2_Selection_Sort/Selection.java


Brian Lee's avatar

背包

《Algorithm》(Sedgewick)笔记:背包

目的

帮助用例收集元素并迭代遍历所有收集到的元素。用例也可以检查背包是否为空或者获取背包中元素的数量。

特点

  • 迭代的顺序不确定且与用例无关
  • 不支持从中删除元素

API

public class Bag<Item> implements Iterable<Item>

Bag()创建一个空背包
void add(Item item)添加一个元素
boolean isEmpty()背包是否为空
int size()背包中的元素数量

实现

public class Bag<Item> implements Iterable<Item> {    private class Node {        Item item;        Node next;    }    private Node first;     //栈顶    private int N;          //元素数量    public boolean isEmpty() { return N == 0; }    public int size() { return N; }    public void add(Item item) {        Node oldFirst = first;        first = new Node();        first.item = item;        first.next = oldFirst;        N ++;    }    public Iterator<Item> iterator() {        return new ListIterator();    }    private class ListIterator implements Iterator<Item> {        private Node current = first;        public boolean hasNext() { return current != null; }        public void remove() { }        public Item next() {            Item item = current.item;            current = current.next;            return item;        }    }}

源码地址

https://github.com/XutongLi/Algorithm-Learn/tree/master/src/S1_foundation/S1_3_BagQueueStack/S1_3_3_10_Bag

Kay's avatar

2018 BUPT Summer Training #1 (恢复训练) 部分题解(仍会更新)

原题链接 A. Treasure Island Time limit: 2000 ms Memory limi …

继续阅读“2018 BUPT Summer Training #1 (恢复训练) 部分题解(仍会更新)”

Brian Lee's avatar

队列

《Algorithm》(Sedgewick)笔记:队列

目的

用集合保存元素的同时保存它们的相对顺序:使它们入列顺序和出列顺序相同

特点

  • 基于先进先出(FIFO)策略

API

public class Queue<Item> implements Iterable<Item>

Queue()创建空队列
void enqueue(Item item)添加一个元素
Item dequeue()删除最早添加的元素
boolean isEmpty()队列是否为空
int size()队列中的元素数量

实现

public class Queue<Item> implements Iterable<Item> {    private class Node {        Item item;        Node next;    }    private Node first; //指向最早添加的结点的链接    private Node last;  //指向最近添加的结点的链接    private int N;    public boolean isEmpty() { return N == 0; }    public int size() { return N; }    //向表尾添加元素    public void enqueue(Item item) {        Node oldLast = last;        last = new Node();        last.item = item;        last.next = null;        if (isEmpty())            first = last;        else            oldLast.next = last;        N ++;    }    //从表头删除元素    public Item dequeue() {        Item item = first.item;        first = first.next;        if (isEmpty())            last = first;        N --;        return item;    }    public Iterator<Item> iterator() {        return new Queue.ListIterator();    }    private class ListIterator implements Iterator<Item> {        private Node current = first;        public boolean hasNext() { return current != null; }        public void remove() { }        public Item next() {            Item item = current.item;            current = current.next;            return item;        }    }}

源码地址

https://github.com/XutongLi/Algorithm-Learn/tree/master/src/S1_foundation/S1_3_BagQueueStack/S1_3_3_9_Queue

's avatar

使用valine为博客添加评论功能

前言

昨天被高渐离嘲笑没有评论功能,本来是不太想加的,因为加了可能也没人用,放着怪冷清的,不过 真香。

既然高先生都使用了Gitalk为博客添加Gitalk评论插件–高渐离)我就不能用一个一样的是吧(手动滑稽。再看了看对于几个常见的评论系统的使用报告之后,我决定使用valine为我的博客提供评论功能。

Gaojianli's avatar

为博客添加Gitalk评论插件

前言

一直以来都想要给自己的博客弄个评论系统,但是hexo作为一个静态博客,本身是不可能具有这种功能的,只能仰仗第三方插件。这方面的插件也非常多,比如disqus、vline等。但这些插件都存在或多或少问题,比如注册麻烦或者干脆国内不能访问。考虑到我家长城宽带的现实,必须选择一个在各地都能流畅访问的插件,这里我选择了Gitalk.

简介

先来看看官网的简介吧:

Gitalk is a modern comment component based on GitHub Issue and Preact.

顾名思义,这是一个基于GitHub的issue功能构建的评论系统。为了部署方便,我的博客本身也是托管在GitHub上的,而且其CDN也遍布全球各地,即使是长城宽带也能保证访问。此外相信本文的绝大多数读者也都具有GitHub账号,这也省去了大家注册的麻烦。因此,从各种意义上来说,它都是一个理想的插件。

Kay's avatar

Hello World!

世界你好

早在去年,就有建立个人网站的想法,在解决了一万个问题之后,终于在今天,Kay 的个人博客– Kay’ Blog 正式启用,这也是第一篇正式文章。

成年之际

今天也是 Kay 的十八岁生日,成年之日,这个网站也算是给自己的一个生日礼物吧。

终至今日

对于今天,与我可谓期待已久。由于一些原因,在同学中我往往是年龄最小的,长期与虽没有大多少确早已成年的同学们接触,不免会对成年之日抱有奇怪的幻想,或是渴望,或是恐慌,甚至有些迷茫……从我的经历来看,这个社会对未成年人太不友好了,或者说过度保护了,在我还未成年的大一,在受到了许多限制(不能考驾照,不能注册 PayPal ,不能开信用卡,不能单独出境,甚至不能注册某些手机卡 etc.) 在今天,在法律意义上,我终于成为了一名拥有完全民事行为能力的自然人,法律赋予了我作为一位成年公民所应有的权利,我获得了更大的自由。里程碑式的日子,故事才刚刚开始。

这一年来

从刚高考完拿到录取通知书,虽知道自己专业是什么,确对其一无所知的萌新,到照着教程一个字母一个符号地打出 Hello World ,到踏入大学校门,频繁地听到大佬们讨论人工智能、机器学习……对专业有了一定了解,到C语言期中考意外拿了第一,到逐渐在选修课和校会部门中学会PS修图、剪视频、处理音频,到不断刷GPA,开始备考托福,到开始打算法竞赛,到组队着手做大创……直至今天。这一年,遇到过许多困难,经历过许多失败,也曾感到懊恼和失落,但总的来说,这一年奠定了我的专业基础。I am not a freshman anymore. 这不是终点,恰恰相反, 这是个新的起点,18岁的我还须要不断前进。新的一年,请多指教。

这十八年

十八年前,呱呱坠地,幸运地来到这个世界。十八年来,承蒙关照,一步步不断成长。直至今日,如你所见,呈现在你们面前的 Kay 。感恩伴我成长的每一个人。成年的我还有很长的路要走。千里之行,始于足下。

关于博客

回到博客。主要分享一些学习记录和即兴随笔。可能主题:算法、前端、托福等。不定时更新,尽量周更吧。欢迎各位大佬的建议和指正。但务耕耘,莫问收获。

2018年7月17日 于 广东惠州

Gaojianli's avatar

搭建自己的Git

前言

事情的起因非常简单,得益于某位校长的功劳,我的网络访问Github奇慢无比,最近甚至出现了push失败的情况,我连博客都没法好好更新了!(说的好像你更新得很多一样)
嘛,正好潇在给我孜孜不倦地推荐Gitea,我就来试试在树莓派上搭建一下吧。
首先我们来看官方文档:

易安装
您除了可以根据操作系统平台通过 二进制运行,还可以通过 Docker 或 Vagrant,以及 包管理 安装。

嚯,挺厉害嘛,那就图个省事,用Docker安装吧。然而这之后我才知道,这是地狱的开始。

Docker试探

安装

官方的教程非常的简单,看起来就和能用一样

's avatar

《高校微信小程序开发大赛》入围作品个人盘点

前言

个人也自不量力去和高渐离大佬组队参加了这次比赛,结果不出意料的一轮就被刷下来了。这次比赛产生了不小的争议,我也挺好奇入围的作品到底长啥样的,所以就以我个人的感觉,一个用户的感觉评论一下。评论的时候我已经把队员名字以及学校都去掉了,但是也不保证绝对公正。

个人向的评论难免有失偏颇,请各位谅解。我达不到他们的高度,但是也应该有权发表一下自己的见解。

如果有哪里错误的地方还请多多谅解,本人能力有限,谢谢。

icebound's avatar

如何入门算法竞赛

朋友,你听说过算法竞赛吗?著名算法竞赛选手、教练刘汝佳曾说过,算法竞赛是一种【思维的体操】。在每年的春天,学校都会有归队赛、新生赛、校赛,筛选一批优秀选手进入ACM集训队。在集训队中,会有去过world final的大佬带着我们训练,每年暑假的集中训练是提升个人水平的最好机会!相比其他学校,北邮的编程气息浓厚,几乎所有人都会写代码,这也会对你的学习有帮助。

如何入门算法竞赛 原载于 BYRIO

's avatar

Vuex使用笔记

Vue-cli虽然好用,但是各个模块之间、各个页面之间的数据传递非常繁琐。所以才有了这个Vuex模块,用来管理Vue项目中的全局变量。既然都有全局变量了,谁还要局部变量呢?

这篇笔记本着够用就行,能用就行的宗旨,尽量以最少学习代价在实战项目中使用Vuex。

Ps:文中漏洞百出,还请各位批判阅读。

第一步 安装

npm包层面

1
$ npm i vuex -S

良好的目录结构

为了有一个良好的目录结构,防止被同事打死方便维护,新建目录结构(加星号部分)

1
2
3
4
5
6
/
|- src
|- store *
|- index.js *
|- modules *
|- <modelsName>.js *
  • src/store 用来存放所有的全局变量相关文件
  • src/store/index.js 用来引入vuex模块并导入所有的全局变量模块
  • src/store/modules 用来存放所有的全局变量模块
  • src/store/modules/<modelsName>.js 一个全局变量模块

引入

修改 src/main.js 添加

1
import store from './store'; // 引入全局变量组件

src/store/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import Vue from 'vue'
import vuex from 'vuex'

Vue.use(vuex);

import <modelsName> from './modules/<modelsName>' // 引入所有的模块

export default new vuex.Store({
modules:{
<modelsName> // 把所有的模块引入
},
state:{
// 这里可以添加一点 真·全局变量 ,比上面的少一层,下面引用可知
}
})

全局变量模块化的用处是防止变量重名,并且可以明确所属关系。

src/store/modules/<modelsName>.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
export default {
state:{ // 这里用来定义所有的全局变量
cookie:null,
login:false,
show:false,
nick_name: null,
avatar_url: null
},
mutations:{ // 这里的方法必须同步!
switch_dialog(state){//这里的state对应着上面这个state
state.show = state.show?false:true;
//你还可以在这里执行其他的操作改变state
},
// 调用方式:$store.commit('<modelsName>/switch_dialog')
increment (state, payload) {// 这是一个可以传参数(真名:载荷-payload)的方法
state.nick_name = payload.nick_name // 传进来的参数可以是对象
}
// 调用方式: $store.commit('<modelsName>/increment', {nick_name: 'asdf'})
// 或: $store.commit({type:'<modelsName>/increment', nick_name: 'asdf'})
},
actions:{ //这里放异步操作
switch_dialog(context){//这里的context和我们使用的$store拥有相同的对象和方法
context.commit('switch_dialog');
//你还可以在这里触发其他的mutations方法
},
// 调用方式: $store.dispatch('<modelsName>/switch_dialog')
},
getters:{ // state的派生属性
not_show(state){//这里的state对应着上面这个state
return !state.show;
}
// 调用: $store.getters.not_show
// 这就像一个值一样,不用加括号进行调用
}
}

第二步 使用

现在你已经基本完成了整个全局变量的框架建构,现在可以开始滥用使用了。

关于各种方法的使用请参照上面的文件,这边就简单写一下数据的使用吧。

this可以取到data的地方

1
that.$store.state.<modelsName>.nick_name

模板渲染的地方

1
{{$store.state.<modelsName>.nick_name}}

后记

基本上这样就可以足够应付大多数的情况了。另外Vuex还有很多的好用的功能(虽然我没用过)。

更多信息请看Vuex 是什么?

问少's avatar

更换评论系统

最近一直在忙着毕业的事情,没有打理博客。等到基本事情都做完回来看博客的时候发现,原来使用的 HyperComments 评论系统已经开始收费了,并且只有在订阅之后才可以进入管理页面。

这样一来,原本的评论想要找回来就只能强制被收费了,那只好对 HyperComments 说再见了,重新投入 Disqus 的怀抱。

然而 Disqus 在国内被屏蔽,这也是没办法的事情,所以……以后网站的评论就只能是随缘评论了……

via these people and places