Hypercube's Channel
236 subscribers
98 photos
12 videos
9 files
79 links
@SmartHypercube 随便发最近关注的东西
欢迎找我私聊讨论
可以使用 Telegram 的转发功能转发消息
Download Telegram
我一直听说过两个乐理知识:
1. 如果同时演奏的音符频率之比可以约分为小整数比例,例如大和弦的三个音符是 4:5:6,就会听起来和谐。
2. 现代音乐一般使用一个等比数列中的频率,公比为 2^(1/12),也就是把 1:2 等比地分成 12 步。

它们显然是不互相兼容的,1 产生的都是有理数,2 产生的几乎都是无理数。之前才意识到 1 有一个问题:从一个初始频率开始,每次乘以 2 和每次乘以 1.5 分别得到的频率序列中,永远不包含相等的频率。虽然每个序列内部是和谐的,但两个序列之间无法约分,因为一侧有越来越多的素因子 2,另一侧有越来越多的素因子 3。

“纯律”就是按 1 的思想的,“十二平均律”则是 2。采用 12 步恰好可以产生非常接近 2:3 3:4 4:5 等小整数比例的频率(分别相隔 7 5 4 步),但不可能做到完全相等,总是有一点误差。以这些误差为代价,换来了可以随意改变音符的绝对频率,而保持相对频率关系完全不变。

因此也就不难理解为什么十二平均律中 12 个音并不被平等地使用了,人们一般按照“101011010101”的模式选出 7 个主要使用(可以循环移位,有 12 种选法),而不太用另外 5 个,因为这 7 个频率之间的关系更和谐一些。很多流行歌曲还会只用 5 个音,按照“101010010100”的模式(这个模式串就是上一个模式串循环移位后取反的结果,这是有原因的)。当你看到一首歌的简谱中只有 1 2 3 5 6 这 5 个数字时,就是这种情况了,例如《七子之歌——澳门》。
👍5
Media is too big
VIEW IN TELEGRAM
看到 https://t.iss.one/toMyBlackParade/416 推荐 Bloons TD 6 这个游戏,最近玩了比较多,感觉好玩😆
👍4
Telegram Bot API 提到:
1. update 的 ID 从某个正整数开始连续递增,但如果至少一周没有 update,下一个 ID 会重新随机选择,而非连续递增。
2. getUpdates 接口的 offset 参数应当设置为收到的最大 ID + 1,小于它的 update 均被视为已确认。
3. 所有整数字段,除非特别说明,都可以安全地用 32 位有符号数存储。

这几条规则合在一起让我完全摸不着头脑——如果持续收 2^31 条 update 怎么办?如果 ID 被重新随机选择成更小的值了,调用 getUpdates 岂不是会意外确认掉还没收到过的新消息?为什么我实际测试时,指定更大的 offset 仍然可以拿到更小 ID 的 update?

读了相关代码后,我明白了为什么大家写的 bot 一般都不会出问题了,但仍然觉得整个设计挺怪异的:
1. 长时间没有 update 或者 ID 达到 2e9 都会导致重新随机选择 ID,随机范围是 2e6 到 1e9。
2. offset 参数比最新 ID 大 10 或比最早的未确认的 ID 小 1e5 就会被忽略,不确认任何 update,只正常返回实际列表。
3. 如果 ID 达到 2e9 时存在未确认的 update,似乎会修改它们的 ID(也可能是丢掉,这里我不太确定代码中一些函数的语义)。
👍1
https://github.com/SmartHypercube/lambda-response-limit

冷知识:AWS Lambda 官方说返回的 payload 最大 6MB,实际上每种语言的 runtime 有自己的编码规则,编码后最多 6Mi + 100 字节。

另外,不仅每种语言的 runtime 的编码规则不一致,而且这些规则都和真正发回 HTTP response 时编码的规则不一致。在 Python 中返回 {'s': '/' * 6291567} 或在 Node.js 中返回 {s: '/'.repeat(6291568)} 都能正好用尽最大长度(注意到 Node.js 能多塞进一个 / 字符,因为 Node.js 检查长度时,冒号后面没有空格),但收到的 HTTP response 的长度分别是 12583102 和 12583104,远远超过 6MB。真正发回 HTTP response 时,冒号和逗号后面没有空格,但 / 字符会不必要地被编码成 \/,这产生了以上结果。
👍1
看 Steam 年度回顾提到“创意工坊物品订阅者数”,疑惑我又不在创意工坊发布东西,哪来的订阅者?结果检查了一下,很久以前随便存到创意工坊的几个城市天际线存档居然有这么多订阅者和收藏者??比我认真做的 YouTube 视频反响好多了😂
👍4
尝试录屏并剪辑了 Advent of Code 中两道题的做题过程,之后可能还会发更多:

day 18: https://youtu.be/i4EB36076Pw
day 19: https://youtu.be/toJVMxv-AuE

我以前思考过如果直播或录制我写代码的过程,有没有可能别人会想看。我一直挺怀疑的,不过前两天和 @zzh1996 聊天时他提到一些细节做法可能有参考的价值,例如:
- 使用 copilot 的频率
- 使用自动补全的频率
- 怎么快速看特定函数的文档
- 边写边编译检查还是最后统一解决编译报错

我觉得有道理,正好 Advent of Code 每道题比较简单、互相独立,更适合做成视频,就用它试试。

我以为别人不会对我的城市天际线存档感兴趣,因为只是我按自己的想法和目标玩的,对别人没啥用。但居然有人收藏下载,所以我又知道什么呢😂说不定这种录屏也会对别人有用吧。
👍3
我每天吃饭的时候会在直播平台上找一个循环连播电视剧的频道看,但最近发现某个这样的频道有一个小问题:它循环长度约等于 24 小时,导致我总是看相同的一些集。我在想如果我做这样循环连播的频道,应该把循环长度控制在多少最合适呢?

我的第一反应是应该和 24 互素,但时间是连续的,并不是以小时为最小单位离散的。第二反应是应该令最大公因数最小,但这意味着任何无理数循环长度都一样最优,显然不是我想找的答案。我其实希望每天看到的位置和前几天看过的都相隔足够远。

我认为答案应该是黄金分割比,令循环长度为 24 小时的 0.382、0.618、1.618 等倍数。这正好和另一个我思考过的问题相同:在色调的一圈 360 度上选择颜色,该怎么选出 n 个颜色,让它们两两都相隔尽量远?当 n 已知时 n 等分即可。当 n 未知时(不断要求再增加一个颜色),如果 m 等分了前 m 个颜色,第 m+1 个颜色只能放在某两个颜色中间,离两侧都太近。按照黄金分割比,总把第 i 个颜色选在 i*0.618*360 度处,按我的理解是最优的。植物的叶片也近似是按这个规则生长的,可以在总数量未知的情况下尽量均匀分布。

参考: https://en.wikipedia.org/wiki/Golden_angle
👍2
Hackergame 将选手 ID 加上电子签名称为 token,用于题目认证选手。考虑到题目中的认证逻辑可以被选手看到,但不应该能生成他人的 token,所以不能用 HMAC。现有做法是:将选手 ID 转为字符串,与椭圆曲线签名再 base64 的结果拼接,例如“42:MEUCIQCE……”。题目需要:
A1. 将收到的 token 按冒号切开。
A2. 将右侧 base64 解码后验证是否为左侧的合法签名。
A3. 用整个 token 或只用左侧隔离不同选手的环境,以及限制资源用量。
A4. 用整个 token(加盐)哈希作为题目答案。不能只用左侧是因为不应该能生成他人的答案。

关键问题是一个选手能否对应多个不同但都合法的右侧部分。如果能的话,A3 必须只用左侧,不能用整个 token。A4 一个选手会对应多个不同的题目答案,处理起来很棘手。如果不能的话就全简单了,A3 和 A4 都可以直接用整个 token。

想确保一个选手只能对应唯一 token 的话,需要注意以下细节:
B1. 按冒号切开的这一步不要写出漏洞,例如不要接受“42:garbage:MEUCIQCE……”。
B2. 椭圆曲线签名可以被人为变换产生另一个不同但也能通过数学验证的签名(malleability),解决这个漏洞的标准做法是规定只有某一个合法,另一个非法。
B3. 很多 base64 库会把不同输入对应到相同输出,例如“A/B=”改成“A/ B=”、“A/B”、“A_B”、“A/C=”可能都可以得到相同输出,应当只允许标准形式。Python 所有版本的 base64 库都有此问题。
B4. 尤其不要不验证就直接相信左侧的 ID。

libsodium 可以解决以上所有问题,它不像 OpenSSL 等库提供底层算法,而是提供绝大多数程序实际需要的高层功能,考虑了各种细节。crypto_sign 函数把 ID 变成 token,crypto_sign_open 函数变回来。
C1. 不用自己切分 token 了。
C2. 它生成的 token 格式不直观,一定程度上避免绕过 crypto_sign_open 直接看 ID。
C3. crypto_sign_open 能确保一个选手对应唯一 token,遇到其他形式或验证失败都不会返回 ID。

延伸阅读: https://hdevalence.ca/blog/2020-10-04-its-25519am
👎1
https://tom7.org/abc/
非常有趣的一篇 paper(和一个程序)。这个作者的其他项目,以及 SIGBOVIK 的其他 paper 我也都很喜欢。
前几天我在想,怎样能设计一个游戏,它的核心玩法涉及 AI 独特的能力(也就是不用 AI 就做不出这样的游戏),并且不是对话式的(因为对话式的 AI 相关游戏已经太多了)。

我做了一个这样的 demo,从“金木水火土”5 个汉字开始,每一步玩家可以点击两个字来组合,AI 决定组合得到什么,游戏目标是组合出某个特定的字。但是玩了玩感觉并不是很有趣,尤其是绝大多数心里想的目标实际上非常难组合出来。我尝试了很久合成“新年快乐”四个字中的任何一个,这几个字的含义都有点抽象,很难通过具体的概念得到。

今天在 Hacker News 看到简直一模一样的想法被别人做了😂其实还是有一定可玩性的,不过确实和我当时遇到的困难一模一样,就是想合成特定目标的话非常难,导致只能是个随便玩玩的游戏,没法引入胜利条件或者分数的概念。

(建议手机上尝试,电脑版的 UI 逻辑不好用。)
在看游戏音乐拍号(time signature)相关视频,评论里有人提到 Splatoon 的音乐 Frothy Waters 每小节增加一拍,依次用了 10/8、11/8、12/8 直到 25/8 的拍号。它就是 Splatoon 3 正常打工过程的背景音乐,我听了那么多遍居然都没注意到这个特点🌚

https://youtu.be/jcxsYaWoIkQ?t=1082
没想到不同银行在存款证明方面的逻辑有这么大差异,我目前试出来的信息:
- 招商银行:可开非冻结或冻结的,会显示开户日期,可以任意输入更小的金额数字
- 中国银行:只能开冻结的,可以冻 1 天但不能不冻
- 中国建设银行:可开非冻结或冻结的(他们称为时点和时段),不显示开户日期,不能自定义金额,只能是当前实际余额
👍1
👍7
不同云服务商的几台机器之间有安全通信的需求的话(例如需要调用 HTTP API 或连接数据库),可以选择 VPN 或者 TLS。如果自己维护一个 CA,为所有机器正确配置 server certificate 和 client certificate 的话,是可以达到与 VPN 相似的保护效果的。

但是由于种种原因,TLS 有一些设计并不令我满意,效果上总是比 VPN 差那么一点。例如:端口号是公开的,别人一扫就知道你在运行什么服务,改用随机端口的话不太方便,并且仍然可以扫出一些信息。验证 client certificate 之前就会发送 server certificate,这里面可以泄露不少信息,包括 hostname、证书签发时间、CA 的名字等,可以用于猜测这台机器的拥有者和功能。SNI 目前仍然是没加密的。用 VPN 的话是没有这些信息泄露的。

但 VPN 也有自己的问题,配置起来更麻烦一些,不适合增量式地为每个应用配置,需要提前决定好怎么把所有机器组网,想临时给别人一个权限时,给对方签一张 client certificate 也更轻量级。

如果想要一种可以为各个应用按需启用的、可以灵活配置权限规则的方案,似乎还是更像 TLS 一点。它要是把更多步骤挪到检查客户端证书之后再做,并且都加密传输,就好了。
遇到了一个神奇妙妙 bug,我使用某系统时总是有概率登录失败,需要重试才能成功。而且最近几个月以来失败概率越来越高,到了难以忍受的程度,常常需要重试两三次才能成功。但别人都没遇到同样的问题。

今天在 @taoky42 认真调查之后终于搞明白了,问题在于登录时在数据库中查询我的本月用量花费的时间超过一秒。数据库表结构为 使用记录(时间, 用户, 用量),时间列和用户列分别有单列索引,查询语句为 select sum(用量) from 使用记录 where 用户 = ... and UNIX_TIMESTAMP(时间) > ...。

我看到这个查询的第一反应是,这肯定用时间索引,然后行数很少,应该不会慢,就算慢也不可能只有我一个人慢,应该是大家一样慢。但是,注意以下两种写法的区别:

1. UNIX_TIMESTAMP(时间) > ...
2. 时间 > FROM_UNIXTIME(...)

1 运行花费 1.37 秒,2 运行花费 0.05 秒。1 用不上时间索引,只能用用户索引,导致行数多了不少,并且每行还有函数调用开销。
👍1
SQLite 支持一些处理 JSON 的函数,可以直接对 JSON 格式的列进行查询和建立索引,看似很方便,但要当心:

1. json('{"a/b": 1}') != json('{"a\/b": 1}')
虽然在 JSON 的意义上两个 object 是一样的,但 SQLite 认为是不等的。

2. json_extract('{"a\/b": 1}', '$.a/b') is null
类似地,json_extract('{"\u0031":1}', '$.1') is null
类似地,json_extract('{"\u6211":1}', '$.我') is null
这个问题只在老版本的 SQLite 上存在,最新版本已经修复了。

感觉很坑,因为很多时候我是没法控制我用的 JSON 库怎么 escape 各种字符的,例如 / 这个字符其实不必 escape,但有的库会把它 escape 成 \/,进了 SQLite 后就会出现匹配不到 key 的问题。
微信备份/迁移聊天记录时会丢失和公众号的对话记录,包括公众号推送的文章和消息记录,以及自己打字和公众号对话的记录。望周知。

(上一条消息搞错了,删了重发)
怎么避免“毕业论文10.pdf”排序时排在“毕业论文1.pdf”和“毕业论文2.pdf”之间?一个非常简单并且足够好的做法就是把连起来的数字看作一个整体,["毕业论文", 10, ".pdf"] > ["毕业论文", 2, ".pdf"]。这样遇到“毕业论文13送审版.pdf”、“毕业论文13送审版2.pdf”等更复杂的情况时也会正好产生好的结果。

我之前一直觉得这个问题就算是已经解决得很好了,今天给 @zzh1996 讲这个算法时,他说“听起来十六进制的文件名会完全乱掉”,我才意识到有这个坑😂我好像从来没有在 Windows 文件管理器等程序中打开过包含很多十六进制文件名的目录。

那 Windows 是怎么解决的呢?刚刚调查了一下,Windows 还真就没解决这个问题,我想了想也没想到好的方法。
👍1