Home

A simple way to turn callback pattern to coroutine pattern in Lua

My game project is written by Lua. However, its framework does not provide a coroutine pattern, it uses a simple callback pattern instead. For example, to send an http request and receive the response, you must write like this: http_get("https://luyuhuang.tech/sitemap.xml", function(code, content) if code ~= 200 then print("an error...

Read more

全排列问题

给定 n 个不同的元素, 问有多少种不同的排列方式. 这就是全排列问题. 我们高中时就学过排列公式 $A_n^m = \frac{n!}{(n-m)!}$, 因此对于 n 个元素, 全排列数等于 $A_n^n = \frac{n!}{(n-n)!} = n!$ . 例如对于序列 [1, 2, 3] 全排列为 [1, 2, 3] [1, 3, 2] [2, 1, 3] [2, 3, 1] [3, 1, 2] [3, 2, 1] 共 $3! = 6$ 种. 这里我们讨论 Leetcode 上的三道全排列问题. 1. 全排列 题目源自 Leetcode 46 题 给定一个没有重复数字的序列,返回其所有可能的全排列。 示例: 输入: [1,2,3] 输出: [ ...

Read more

只出现一次的数字

这里分享三道寻找数组中只出现一次的数字的问题. 这些题使用哈希表都很好做, 但这里我们使用位运算, 可以很巧妙地在常数空间复杂度内解决问题. 第一题 题目源自 Leetcode 136 题 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 说明: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 示例 1: 输入: [2,2,1] 输出: 1 示例 2: 输入: [4,1,2,1,2] 输出: 4 异或运算的特性是, 异为真同为假. 即 1 ^ 1 = 0, 0 ^ 0 = 0, 1 ^ 0 = 1, 0 ^ 1 = 1. 因此, 两个相同的数异或的结果...

Read more

[翻译] RFC 1928: SOCKS 协议第 5 版

socks5 是一个常用的代理协议, 它既可以用来代理 TCP, 也可以代理 UDP. socks5 的用途非常广泛, 许多网络软件都支持 socks5, 主流操作系统也支持使用 socks5 作系统代理. RFC 1928 是 socks5 协议的规范文档, 本文是对 RFC 1928 的翻译. 原文见 RFC 1928 - SOCKS Protocol Version 5. 以下是翻译正文: 文档声明 本文档为互联网社区规范了一个互联网标准跟踪的协议, 并征求讨论和改进建议. 请参阅当前版本的 "互联网官方协议标准(STD 1)" 以获取此协议的标准化的状态. 本文档的发布不受限制. 致谢 本文描述的协议是其之前版本 (第 4 版) [1] 的升级版. 该协议离不开积极的...

Read more

Y-Combinator: 如何在匿名函数中递归调用自身

如何实现一个阶乘函数? 最简单的做法是使用递归: 'use strict'; function factorial(n) { if (n === 0) { return 1; } else { return n * factorial(n - 1); } } 很好. 那么如何将 factorial 函数写成一个匿名函数, 且同样递归调用自身呢? (arguments.callee 禁止) 答案略显诡异. 它是这样的: 1 2 3 4 5 6 7 8 9 10 11 'use strict'; const Y = (F) => ((g) => g(g))((g) => F((x) => g(g)...

Read more

搞清楚令人头疼的乱码问题

相信我们每个人都被乱码的问题困扰过. 乱码常常令人十分头疼, 这主要是因为没有搞清楚字符编码的问题: 何为 encode 何为 decode, UTF-8 和 Unicode 是什么关系, 它与 UTF-16 和 UTF-32 的区别又是什么, BOM 头又是什么东西等等. 这里我们彻底地捋一遍字符编码问题. 首先搞清楚几个概念: 基本概念 字符 字符指语言中的书写原子, 是不可再分的最小单元, 例如字母 a é, 表达符号 ; 。, 汉字 阿, 假名 あ, emoji 😂 等等. 总之是书写的最小单位, 它们都应该看作一个字符. 字符库 人类的字符太多了, 我们一次用不了这么多. 所以我们根据不同的情况, 取全体字符的一个子...

Read more

使用 LPeg 解析语法

LPeg 是一个 Lua 的模式匹配库. 笔者刚刚接触到 LPeg 时, 以为它只是另一种形式的正则表达式; 深入了解才发现, 它的功能远远强于正则表达式, 能够轻易匹配正则表达式难以匹配的复杂模式, 乃至解析语法. 事实上, LPeg 即是 Parsing Expression Grammars for Lua, 它设计出来就是用来解析语法的. 使用 LPeg 能够轻松地解析各种语法, 比如用四百行代码将 Lua 源码解析成抽象语法树. 有了它, 静态分析代码, 自定义 DSL(Domain Specific Language) 将会变得易如反掌. 本文不会详细介绍 LPeg 中的每一个函数, 每一个操作符, 这些内容官方文档中都很清楚; 这里主要介绍 LPeg 的匹配机制以及使用...

Read more

使用 Cloudflare 免费搭建 HTTPS 服务

细心的朋友可能发现博客的域名变了. 笔者最近买了一个域名, 让它映射到我的 Github Pages 上. 然后我还在搬瓦工买了一个廉价 VPS 用于搭建一些服务, 比如 RSSHub 和 TTRSS, 同样把域名映射到这上面. 为什么要用域名而不直接使用 IP 地址呢? 一是域名要比 IP 地址好记, 可以使用主机名区分不同的服务 (而不是端口); 二是可以使用 HTTPS. SSL 证书通常很贵, 这里我使用 Cloudflare 的免费代理服务实现免费 HTTPS. 这篇文章总结一下我是怎么做的. Cloudflare 代理 HTTPS 证书实在是太贵了, 一个通配符域名证书一年要至少花上一两千. 那么如何满足广大人民群众建站需求呢? Cloudflare 就是一个很好的选择...

Read more