用笨办法应对充满不确定性的未来

【ARTS 周刊】第一期:花有重开日,人无再少年

2023.07.06

零:碎碎念

不知道大家有没有一种感受,就是时间会过得越来越快。

在学校读书那会,日子是一天一天地过,刚毕业那会是一周一周地过,而现在就是一个月一个月地过了。

明明物理意义上的时间流逝都是一致的,但是个体的感受却随着人生经历的增长而有所不同。

比如说,我想要开始 ARTS 计划其实是在 2021 年,但是中途夭折了。在 2022 年底又想捡起来,结果直到今天才开始正式写第一期。现在回想起来,那几次的踌躇满志与抛之脑后,就像发生在昨天一样,成语历历在目。

笔记中甚至还有当年想发表第一期时留下的记录:

<2022-11-24 Thu> 哈哈哈,原来时间已经过去那么久了吗,那就把今天当作第一天吧。

正好最近看到 阮一峰博客上分享了关于 Day1 的故事,其中有一部分我是认可的:保持在 Day1 的状态,就永远有新机会、永远有无限可能、此时做事情阻力是最低的。

好了,本期碎碎念到此为止,以下是 ARTS 的正文:

一、Algorithm

既然是第一期,就用 leetcode 上的第一题吧:two-sum

问题: 给定一个整数组成的数组,返回相加正好等于某个特定值的两个元素的下标,假定每个问题正好只有一个解,并且每个元素只能用一次。

解题思路:

1. 暴力方法,做两层遍历。代码如下

var nums = [2,7,11,15];
var target = 9;
// answer start
var twoSum = function (nums, target) {
    let result = [null, null]
    for (let i = 0; i <= nums.length; i++) {
        for (let m = i + 1; m <= nums.length; m++) {
            if (nums[i] + nums[m] === target) [
                result = [i, m]
            ]
        }
    }
    return result
};
// answer end
var paire = twoSum(nums,target);
console.log(paire);

时间复杂度是 O(n^2),因为使用了两层嵌套遍历。

以下是 Python 版本的暴力法解,只写了核心部分:

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        n = len(nums)
        for i in range(n):
            for j in range(i + 1, n):
                if nums[i] + nums[j] == target:
                    return [i, j]

2. 使用哈希表

var twoSum = function(nums, target) {
    if (nums.length < 2) {
        return []; // 数组长度小于 2,返回一个空数组
    }

    var map = new Map();
    for (var i = 0; i < nums.length; ++i) {
        var complement = target - nums[i];
        if (map.has(complement)) {
            return [map.get(complement), i];
        }
        map.set(nums[i], i);
    }

    return []; // 没有找到符合条件的答案,返回一个空数组
};

时间复杂度是 O(n),因为只遍历了一次,而在哈希表中查找元素的时间复杂度为 O(1)。

以下是 Python 版本的解答:

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        num_dict = {}  # 哈希表,用于存储元素和索引的映射关系
        for i in range(len(nums)):
            complement = target - nums[i]  # 当前元素的补数
            if complement in num_dict:
                return [num_dict[complement], i]
            num_dict[nums[i]] = i  # 将当前元素及其索引存入哈希表

解析:

这里的关键点在于要减少遍历数组的层数,这就需要有一个数据结构能够快速的检查目标值是否在数组中,以及查找该元素在数组的下标。

这里使用了 ES6 的 Map() 来简化代码,实际上用 Array 或者 ObjectSet 也可以的。

二、Review

Zamansky 81: Elfeed-webkit

这篇文章是从 Emacs Planet 上看到的。他介绍了 elfeed-webkit,从名字上可以看出这是一个关于 elfeed 和 webkit 的包,实际上正是如此:它能够让我们在阅读 RSS 时使用 webkit 内核渲染网页,而不用手动跳转到浏览器中。

作者不仅仅写了这一篇文章,在这之前还有两篇:链接1链接 2。并且每篇都盛赞这个包,称自己“全心全意”地向大家推荐它。

而我也是这么觉得的。

为什么呢?我很早就看到 Emacs 能够支持 webkit 了(需要开启编译 flag),并且有一个 xwidget-webkit-browse-url 命令,我尝试用它打开 Google、打开一些网站,我尝试在页面中点击、输入文本,发现非常卡顿,使用起来很别扭。我认为是打开的 webkit buffer 跟 Emacs 缺少联动,导致两者结合得非常生硬。于是尝试过几次后就放弃不用了。

直接看下效果吧

启用 elfeed webkit 效果

启用 elfeed webkit 效果

由于阅读 RSS 时并不需要跟网页元素做很多交互,只是需要借助渲染引擎的能力把页面画出来,完美避开了缺点。

对比一下不开启 webkit 渲染的效果:

关闭 elfeed webkit 后的效果

关闭 elfeed webkit 后的效果

是不是很棒: )

三、Tip

英文:如何在bash中判断变量为空

if [ -z "$var" ]
then
      echo "\$var is empty"
    else
      echo "\$var is NOT empty"
fi

限制前端工程只能使用某个包管理器:only-allow

可以限制只能使用 npm、cnpm、yarn、pnpm 等 用法:

{
  "scripts": {
    "preinstall": "npx only-allow npm"
  }
}

问题:如果主工程的用到的第三方包中也使用了 only-allow,那在主工程中也会执行该 preinstall 脚本。 有人提过 issue:链接

buzz 音频视频转录成文本

四、Share

流浪猫该不该喂

流浪猫该不该喂?我去研究了一只流浪猫究竟给城市带来了什么,也在想我们怎么跟他共处呢?

这篇视频本身不属于技术文章,但是视频作者使用的分析问题的方式很值得我参考,因为这本质上是尝试从多个视角来看待一个现实中的复杂问题。

“流浪猫该不该喂”,每个人的答案或许各有不同,而人们会有不同的立场正是人之常情。

有人对此做了调查,记录了各个相关方的看法。并且尝试用数据模拟的方式来估算流浪猫对城市的影响,最终尝试研究人们如何与之相处。

有的人觉得喂养流浪猫会导致他们过度繁衍,危害生态,而且可能影响孩子们的安全。

也有人支持对流浪猫 TNR 的方法,即捕捉-绝育-放归的方式来降低新生的流浪猫数量,而不是采取捕杀的方式。

也有人觉得应该捕杀流浪猫。

小区里会去喂猫的人大多比较有同情心,流浪猫中其实不乏品种猫、戴着项圈流浪的,认为有很多是因为人类的弃养而变成流浪猫的。

视频中还记录了学者、物业、政府部门等的意见。

我认为这并不是一个简单的喂还是不喂的问题,而是牵涉到了方方面面,包括动物福利、伴侣动物、人的情感需求和安全需求、社会治理等等问题,也是我们如何去对待我们的伴侣动物的问题。

但是现在很遗憾的是人的权利都无法得到保障,更何况动物了,在这个议题上各人有各人的看法,可能在现有条件下很难有解决方案。