龙胆虎威中的四加仑水迷题(Die Hard 3)

线性组合 最大公约数 数论 离散数学

龙胆虎威 3 中的一个场景:在泉水旁有两个瓶子,容量分别是 5 加仑和 3 加仑。 Bruce 需要在 5 分钟内精确地得到 4 加仑水来停止定时器,差一盎司都会引起爆炸。可是用这两个瓶子总是能构造出来要求的水量吗?如果能,那么有确定的数学方法来告诉 Bruce 具体的步骤吗?

本文对这个问题进行推广,分别讨论有解的条件解的构造两个问题,再给出判断是否有解的简单方法。有关解的存在性,我们主要证明以下两个命题:

如果目标水量 c 能够写成 a 和 b 的线性组合就有解,否则无解。具体地:

  1. 得到的水量一定是 a 和 b 的线性组合。即如果 c 不是 a 和 b 的线性组合就无解。
  2. 重复地把 a 接满倒入 b,b 满了就倒掉,a 空了就装满,就可以得到在 b(假设 b > a)中得到所有线性组合。即只要能写作线性组合就一定会得到。

c 是否能写作 a 和 b 的线性组合,取决于 c 能否被 gcd(a,b) 整除:

  1. gcd(a,b) 是 a 和 b 最小的正的线性组合。
  2. gcd(a,b) 能整除 c 等价于 c 是 a 和 b 的线性组合。

为方便讨论,本文所有线性组合都指整数线性组合,所有数字 x、y、m、n 都表示整数。

TypeScript 来做依赖注入的限制

TypeScript 依赖注入 装饰器

依赖注入 是编写可测试/复用代码的关键。 在 TypeScript 中所有对象、属性和方法都有类型,可以大幅简化人工标注的代码,这让很多人重新考虑在 JavaScript 中实现依赖注入。 比如 Angular2 以后的 DI 实现。 本文用来讨论 TypeScript 仍然无法解决哪些问题,以及相关技术可能存在的风险。

首先简单过一下基于 TypeScript 做依赖注入的步骤。 ES6 中提出了Reflect 用来访问和操作对象对象属性。 而 Reflect Metadata 提案 让 Reflect API 可以提供对类型的元数据进行操作的方法。 这样就可以在 tsc 编译时产出注册元数据的代码,在运行时就可以读到编译时的类型了,这一类型就提供了依赖注入的 Token。 运行时的注入器根据函数签名的类型拿到依赖关系,再根据类型对应的 Provider 来创建依赖树。

ArchLinux 键盘映射:交换 CapsLock 和 Ctrl

ArchLinux hwdb scancode keycode Xmodmap MacBook

笔者在几个月前 切换到 Linux 下干活,使用 Xmodmap 交换掉 CapsLock 和 Ctrl。 但 Xmodmap 只能改键无法区分是哪个键盘硬件设备(偏偏 HHKB 的 Caps 本来就在左边),而且只在 X11 下好使(Virtual Console 下不起作用)。 于是近日研究了下 scancode 到 keycode 映射,通过 udev 匹配和配置特定的输入设备。 我的环境是 MacBook 下的 ArchLinux,下面的命令以此为例,但其他环境也应该类似。

注意:本文只讨论如何重新定义个别键的 keysym 的问题。更改键盘布局请参考 kbdmap,更改快捷键请使用 xbindkeys 或 i3 bindsym 或你的桌面系统配置。

AMD 模块化最佳实践

AMD JavaScript 异步 模块化

AMD 是 RequireJS 给出的模块加载方案。 支持递归依赖解析、模块异步加载,夜兼容 CommonJS 可以在 Node.js 里用。 虽然目前已经不再流行,很多站点更倾向于编写 ES Modules 并直接 Webpack 打包, 但 AMD 是完整的,兼容性良好的,支持动态加载的模块化方案,在大型的、独立部署的、异构的项目中仍然有一席之地。 所以还是决定写一篇关于 AMD 最佳实践的文章,致敬老式的 Old School 的 Web 开发。

TL;DR

  • 源文件中,模块应该匿名编写。区分好“使用 AMD 语法”和“模块化”,充分利用 AMD 又不被套牢。
  • 一个模块对应一个文件。每个模块是一个单独的源文件,每个文件只包含一个模块定义。
  • 避免手动写依赖列表,可以通过编译工具自动生成。
  • 独立维护的工具模块,应当通过打包编译隐藏其内部结构。

Angular DI 是怎么工作的?

TypeScript 依赖注入 反射 装饰器

这又是一篇短命的(short-lived)描述当下技术框架的博客文章。 DI(依赖注入、Dependency injection)是一种设计模式,常用来提升代码的可复用性、健壮性和可测试性。 DI 在前端的流行很大程度上归功于它在 Angular1.x 中的应用。 Angular 2 以后借助 TypeScript 的类型分析,可以干脆省去了 Angular1.x 中冗余的依赖声明。 本文用来解释这个魔法是怎么工作的,以及相关的标准化 Proposal 和实现 Trick。

对于不熟悉依赖注入的同学可以参考我的另外两篇文章 什么时候应该使用依赖注入JavaScript 依赖注入实现, 或者 Wikipedia: DI。这里还有一篇 Angular 的教程:https://angular.io/guide/dependency-injection

Linux 下 MacBook 触摸板设置

Linux MacBook xinput X11 触摸板 i3wm

在 MacBookPro 上安装 ArchLinux 后最大的问题就是那一排功能键和触摸板还能不能用。 功能键比较复杂涉及你的桌面系统或窗口管理器的选择, 本文解释 MacBook 触摸板如何在 ArchLinux 下进行配置。 依赖的软件只有触摸板驱动 xf86-input-mtrack 和 X11,本文应该对绝大多数 Linux 发行版都适用。(不过 Ubuntu 貌似是 Wayland 窗口服务?)

我们重点解释如何恢复 OSX 下独有的触摸板手感和功能: 自然(反向)滚动、三指选择和拖动、四指横向滑动、滚动惯性、鼠标加速(Pointer Acceleration)。 触摸板的通用配置比如敲键时禁用触摸板、手掌识别等,可以参考 Harttle 的另一篇文章: Linux 下的触摸板设置

TL;DR

文中主要介绍一些技巧和原理。心急的同学可以直接按以下步骤操作:

  1. 安装 AUR 包 xf86-input-mtrack
  2. 50-mtrack.conf 下载到 /etc/X11/xorg.conf.d
  3. pkill x 或者 sudo reboot

安装 AUR 软件包

ArchLinux AUR 编译

AUR(ArchLinux User Repository)是 ArchLinux 的社区驱动的软件仓库, 属于不受支持的软件仓库(unsupported)。 但它却是 Arch 社区最有活力的仓库,很多官方仓库(Official Repositories)中的包都来自于 AUR。 AUR 之于 ArchLinux 官方仓库,类似于 Boost 社区之于 STL,类似于 PPA 之于 Ubuntu 官方仓库。 比如 在 MacBookPro 上安装 ArchLinux 时就用到了非常多的 AUR 包。

由于 AUR 中的包不受支持,ArchLinux 的官方包管理工具 pacman 不支持从 AUR 安装。 这就需要额外的工具,几年前 yaourt 独大,在很多 ArchLinux 安装教程中都会介绍如何安装 yaourt。 时至今日 yaourt 已经停止开发(discontinued),官方更愿意推荐 AUR 工具而非安装器。 因为这些包属于 unsupported,你要为安装和维护它们负责,ArchLinux 认为你应当知道一个包是怎样编译和安装进入你的系统的。

本文先介绍 ArchLinux 提供的软件包构建/安装方式,以及如何手动从 PKGBUILD 构建/安装一个软件包。 最后再介绍一些 AUR 工具。

上一页 下一页