duangsuse::Echo
718 subscribers
4.26K photos
130 videos
583 files
6.48K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
虽然我连 GAWK 都不会用
UPDATE: 上面的 "(.*)" 应改成 "(.*?)"、<*?><*> 的意思不一样,它表示『最小匹配』…… 也就是说 takeUntil 到下一项 '"'; 以上 Regex 会把 <abc><123> 弄错,没注意到是因为 <.> 不匹配换行符,感谢细心观众 https://t.me/bystartw_tw. refs
duangsuse::Echo
真想早点睡…… 不得不先带头谈谈学校里打算谈的事,虽然 改天我要不要回顾一下之前的历史? 我果然还是进步得太慢…… 最近也才开始看得懂《编译原理实践教程》(指USTC资料,虽然我不是很看得上)和《深入分析GCC》 一般来说, #school 里我记录的笔记(很多是比较逗逼的,比如上面的修错,虽然修久了我会发现我连逻辑推导都做不到了)都会讲一遍 没做笔记的不会讲。 首先当然是 #book 好书(文)推荐 — 《她是龙》小狱 |Telegraph 注:使用 online OCR 字符识别,哦不,没找到多好的工具。…
她是龙.md
15.4 KB
/(.*)。$/ [$1。\n]
/^(.*):『(.*)』$/ [$1:『$2』\n]
/regex/ [replacement]
替换一下再修改处理出来的Markdown版本
duangsuse::Echo
自动粘滞(sticky)Regex 有点牛逼啊,我之前的都是那些一匹配啥都匹配的,也不可能用 ?! negative lookahead 断言
那我就照本宣科地念了:
+ (信息)声音:就是物体的震动,振子的振幅,就是信号。
+ (信息)图像:就是一堆『像素』的二维矩阵xy……
+ 24bpp:(色彩深度)24个二进制位per pixel
其中一般是 R(8bits), G(8bits), B(8bits); BGR 也有
最多显示 1677万 (R*G*B) 种颜色
+ 32bpp:(色彩深度)一般是带Alpha混成像素色值的颜色
+ 灰度:心理学灰度公式(线性)
Y = 0.2126R + 0.7152G + 0.0722B
显而易见地,数学不好是不能做计算机视觉甚至数字图像处理的……
+ 信息学、熵(shang1)、电子(electron)、热
密码学、加密、隐写、编码技术、千年虫、64k-intro、DEOM技术、huffman算法

最小公倍数、最大公约数(gcd, greatest common division)、fibonacci、函数变化率

我也不知道为什么有这些东西,大概是我看小说看到的,我物理和数学都不好

+ 谈谈 Base=64 是啥意思
这还准备教 Base=1000 呢
后来我觉得我佛系了,我就扔一个公式就走人。

2**(8*n) = 64**x where n, x in N+
看起来这个等式不是很好解啊
两个未知数都在指数的位置
一个解是 n=4; x=3

那Base=1000呢
2**(8*n) = 1000**x
只能用miniKanren解了呢……

https://codon.com/hello-declarative-world
https://github.com/nd/mk.java/blob/master/src/main/java/MicroKanren.java

可是我不会啊…… 这里也有两个未知数呢
def solved(n, x); 2**(8*n) == 1000**x; end
上枚举吧, n=(1, 10]; x=(1, 10]
(1..1000).to_a.combination(2).map { |nx| [solved(nx[0], nx[1])||solved(nx[1], nx[0]), nx] }.find_all { |it| it[0]}

好像还是不行呢…… 可是第一个表达式是有办法的
[[3, 4], [6, 8], [9, 12], [12, 16], [15, 20], [18, 24], [21, 28], [24, 32], [27, 36], [30, 40], [33, 44], [36, 48], [39, 52], [42, 56], [45, 60], [48, 64], [51, 68], [54, 72], [57, 76], [60, 80], [63, 84], [66, 88], [69, 92], [72, 96], [75, 100]]
hhhhhh好无脑
+ 依照CFG(Control Flow Graph) 谈 return early

虽然我好像已经谈过了(而且这次显然我不会扯到SSA的PHI……),
就是说可以要在一个函数返回前添加固定的步骤,所以不能直接 return 这样
我们这里谈的不是和 calling convention 里栈帧末的收尾代码。

说点抽象的,如果我们一直用 if (p) {…} clean(); return;
实际上不管怎么样 if (p) 里面的东西,除非return跳转都会 fallthruclean(); return; (隐式return也一样)

但是如果你
if(!p) return;
if(!p1) return;
clean(); return;
就不一样了,显然直接 return 会跳过 clean();


那该怎么办呢?C宏(辣鸡宏)你可以很dirty的搞个
#define clean(x) { clean(); x; }
void do_sth() {
if (!p) clean(return);
if (!p1) clean(return);
clean(return);
}
#undef
很甜吧,但是稍微有点常识的人都不会用
还有,内联(inline)、嵌套(nested)函数是不允许的

C++ 你可以用 object + finializer,直接RAII(Resource Aquring Is Initialization)
可是 C 里面貌似没更好的解决方法。
一般来说都是
if(!p) goto out;
out: clean(); return;

+ 语文课上居然都谈到区块链
第一时间
《区块链离我们有多远》

我只知道金仨字面意义上的书记有一大堆,所以单单一个书记想伪造敲诈公款是不可能的……
别人说什么造假成本高于造假收益,反正就是密码学啊计算机网络那一些(可信计算?)的东西?


+ 我做梦居然梦到华为EMUI的计算器应用升级
居然还能递等式,还把括号里的东西加了箭头…… 其实我本来可以学学画dot图的,还是直白一点算了
大概是我想 Calc.kt 的二元链解析算法想过分了。
1 + 2 * 3 (梦里比这个复杂得多,我记得当时还是设计质能公式的一个略繁琐的物理算式…… 居然能那样)
= 1 + 6 — 箭头指着上面的 2 [*] 3……
= 7 — 还是有箭头……

+ #book
文章|书 名作者
《她是龙》 小狱
《手机城》 最安神
《盛夏方程式》 东野圭吾
《莫言谈教养》 任万杰
《生气有啥用,还不是在原地转圈圈》 程智超

+ 谈谈知识付费

有时候看到知识付费呢,总会觉得是『知识』要『付费』,付费修饰知识。
可是总觉得,很多人心里会是这么想,实际上却是理解为『能够付费的知识』呢。

就是说,『付费』以得到知识。
『付费』比知识更重要。

付费的东西一定比不付费的强吗?其实这是很大程度依赖上下文的,无法作概论。
知识付费其实不是新概念,实际上学术界也有不少不得不向出版社掏钱的情况,但付费从不是目的,只是为了取得知识不能不拿出来的一点小代价。

如果还看重的是知识的话,就要明白呢…… 不要叫『知识付费』,叫『付费的知识』。

+ 谈谈Calc.kt现在的(基于ADT栈的)解析算法错在哪里

比如,解析词条流 a + b * c + e % c * a
(优先级自己从下面我列的结果推)
(a + (b * c)) + [(e % c) * a]
这是正经情况。
然而实际上,解析器会认为是这样:

a (+) (b*c) (+) [(e%c) * a]
(a + [(b * c) + (e%c * a)])
看到区别了吗?ADT Stack 是右结合的,即便 (+) 的左优先级更大也是一样
只是因为,a+b*c 里要先解析乘法,导致栈是这样:
a (+) (b*c)
如果过一会又出现了加法会怎么样?答案是会归到 (b*c)里:
a (+) ((b*c)+a)
如果又是加乘呢?
a (+) (b*c) (+) (a*c)
所以遇到这种连续两次 (+) 的情况,就都会变成右结合(参考Recursion的reduce方法),实际上应该是左结合的
Expected: (a + (b*c)) + (a*c)
Actual: (a + ((b*c) + (a*c)))

+ 写两个递推式子
我也不知道有啥用,但是笔记上有。

y_0 = (inputs)
y_{n+1} = let x = y_{n} in f_{n+1}(W_{n+1}·x+B_{n+1})

0! = 1
n! = (n-1)!·n
当然也可以这么写,可这好像不是递推式了?
0! = 1
(n+1)! = n!·(n+1)
好奇怪啊

+ PL/0 实践的重点『难点』
1. 实现内嵌函数的作用域嵌套(nested function, leveled stack storage……)
2. 『一个好的解析器应该接受所有输入的所有部分且不能抛出错误』这个不算难,实现『「同步」的keyword token』也不难,就是跳过认不出的token
3. source map (指令序列pc到源码)(其实原教程没有)

+ PL/0 实践教程上的扩展题
虽然我觉得很废

—基础
注释:加入C风格 // 和 /**/
数组:多维数组
函数:传值调用
控制流:加入C风格 for, return,if elif else、exit
判断:(1) 短路求值 (2) && || ! (3) 表达式非零即为真
—提高
提供函数:print(_), print(_, _), random(), random(_)
提供intrinsic:CALLSTACK()
数组多维初始化,var i, j 快速初始化
函数:传地址调用
函数:传procedure调用
do while, switch 和 break, continue 甚至 goto, label
C风格表达式:比如 &, |, <<, ? : ternary 三元表达式, 赋值表达式(愚蠢


虽然照本宣科而且语言设计的也不好,但可见编译原理还是比所谓的『精通』强太多,因为编译原理就可以直接把 if else, do while, swich, break continue goto 什么的结构直接枚举出来,精通还太浅。
Forwarded from duangsuse Throws
笑话:斐波纳奇汤:今天的汤=昨天的汤+前天的汤(自某期《第一时间》笑话部分) #Math
duangsuse::Echo
虽然我连 GAWK 都不会用 UPDATE: 上面的 "(.*)" 应改成 "(.*?)"、<*?> 和 <*> 的意思不一样,它表示『最小匹配』…… 也就是说 takeUntil 到下一项 '"'; 以上 Regex 会把 <abc><123> 弄错,没注意到是因为 <.> 不匹配换行符,感谢细心观众 https://t.me/bystartw_tw. refs
关于正则表达式说几句 #learn 因为这次我错了……(气死,怎么能够犯低级错误,虽然我也没高级到哪里去……)

正则表达式呢…… 就是一种描述『模式(pattern)』的语言
比如说,你大爷喜欢养猫
你大爷有四只猫,分别是黑猫(B)、白猫(W)、花猫(H)、龙猫(L)

—例1
他今天给你带来一只花猫
明天是黑猫
后天是白猫
大后天是龙猫(怎么有点奇怪的东西混进来了……)

你大爷的情绪很波动,所以你需要根据带来猫猫的顺序,判断他情绪的走向。(怎么感觉这个例子举得很是戏谑……)

上面的[例1]可以用我们的『正猫表达式(Regcx, REGular Cat eXpression)』表达:
/HBWL/ — 顺序(sequential)

不过我们比单纯的 "ABCD" 四个字符走得更远,因为可以存在变量 — 而且显然一个『位置』不一定只有一种情况
比如说,你大爷经常带黑猫或者白猫来表示他的心情不好,而你不知道可能(or)『匹配』到的是哪种
/B|W/ — 可能性(or)
花猫或者龙猫表示他的心情好
/H|L/
「括起来」就是给这种情况一个名字,然后我们可以在该『顺序』接下来的时间里以名字使用这个东西
/(H|L)/

我们假设(很平常地):
你大爷情绪波动的时候会带来与昨天不同的猫猫
因为你是有记忆的,所以你只需记住他昨天是带来什么猫就好了
但是有一点:如果我们每次把 (B|W|H|L) 写全就太麻烦了,于是就有了简记法:我们称之为『猫类』
所有猫就这么表示吧: /🐱/
/(🐱)$1/
这就是表达两天里带的是同一种猫($1 是匹配上次的猫 (🐱)),情绪不波动。

可是这只能判断两天里的情况啊!?

于是我们得引入重复的『模式』
不过有一点 — 除了处理现实生活的情况,你可能还要应付你大爷带猫的记录,某个月的记录有可能(因为你的懒惰)是空的
换句话说可能一个猫也没有。

又或者,你尝试匹配的某个模式期待的是 B 黑猫,但是你看到的却是 W 白猫。
这是经常发生的。

/B+/ — 一直是黑猫,且至少有一只(some)
/B?/ — 一只黑猫,不过也可能没有(optional)
/B*/ — 一直是黑猫,也可能没有(many)

/((🐱)\1)*/
就是这个意思了,它会匹配 BBWWHHLL 这种…… 不过这其实不叫『情绪平稳』
/(🐱)\1*/

BBBBBBB; WWWWW; HHH…… 这才叫

== 那么最基本的(顺序、可能性分支、重复)模式就在上面了,下面来说一些表达性的东西,就是 Regex 了。

不过 Regex 是解决字符流匹配的问题,不是猫流(哈哈哈)匹配的问题……

0. 有些项目(item)很特殊,比如 /./ 匹配单个字符、/^/ 匹配一行的开始、/$/ 匹配一行的结尾
一般他们被用于顺序匹配,比如单行 emmm: /^emmm$/
1. 当你想表达『可能是一类』的时候,你可以:
\猫类名
字符流也可以……
\d digits "123"
\w 像 "hello_world123" 这种
\s \S 空格和非空格(基本都是大写逆命题的form,\d \D 也是)

3. 也可以直接用 [...] 区间:
[a-z]
[A-Z]
[a-zA-Z0-9]
[...] 里面是对集合(字符的『类』)所有元素的穷举描述
a-b 这种语法是只有 [...] 里能用的,它表示 a~b 区间里的所有字符…… 字符都是有自己编号的
Unicode 里这个标号叫 code point
是一种枚举(enumeration)!

/a?=(b)/ 是 positive lookahead,意思是我们要 a,但是只有在b前面时才「匹配」
/a?!(b)/ 正好相反,只有不在 b 前面才匹配
这被称为『先行断言』

然后懒得说了…… 😕
https://regex101.com/
Regex 的语法可以很无穷尽的,一般都是以 PCRE (Perl Compatible Regex) 为准
下面你们可以稍微学得深一点 — 『正猫表达式』的确是存在的!

……如果不存在,那就造一个。
我们使用的是目前虽然看起来无bug但是很麻烦的Parser.kt库。
……算了好像重新写工作量也不大,毕竟这个架构是简单

— Regcx cat class
class of cats in: [BW]
class of cats not in: [^BW]
class of cats in|(not in) range: [B-W]
class of cats in ranges: [B-WH-L]

— Regcx wildcard
any cat: 🐱
any nil record: ✖️
peek a cat: 👀

— Regcx structure and capture
seq: HBL
or: H|B|L
capture: (H)

— Regcx quantifier
some: H+
many: H*
optional: H?
exactly-count: H{3}
greater-count: H{3,}
range-count: H{3,6}

— Regcx anchor
begin of records: 📝
end of records:
武器是难用的、玩具是方便的,我还是一直这么写玩具算了……
突然感觉这么弄很没意义
duangsuse::Echo
下面你们可以稍微学得深一点 — 『正猫表达式』的确是存在的! ……如果不存在,那就造一个。 我们使用的是目前虽然看起来无bug但是很麻烦的Parser.kt库。 ……算了好像重新写工作量也不大,毕竟这个架构是简单 — Regcx cat class class of cats in: [BW] class of cats not in: [^BW] class of cats in|(not in) range: [B-W] class of cats in ranges: [B-WH-L] — Regcx…
Cat = 'B' | 'W' | 'H' | 'L'
Factor0 = '.' | '✖️' | 'x' | Cat
CatClass
= (leftSQ hill Factor0+ rightSQ)
| (leftSQ Factor0+ rightSQ)
Struct = Seq | Capture | Or | Repeat | Optional
Seq = Factor {Factor}
Capture = '(' Factor ')'
Or = Factor {'|' Factor}
Optional = Factor '?'
Repeat
= Factor '+'
| Factor '*'
| ExactRepeat
ExactRepeat
= Factor (leftBR N rightBR)
| Factor (leftBR N comma rightBR)
| Factor (leftBR N comma N rightBR)
Factor = Factor0 | CatClass | Struct
Regcx = Factor

这就可见是一个 LL(1),不过其实我更喜欢PEG,emmm。
突然觉悟出『完全面向对象』设计不好……
duangsuse::Echo
突然觉悟出『完全面向对象』设计不好……
解锁新成就——整个项目,都是笑话x2
黑猫白猫什么的说说就好了…… 非得写那么多太当真hhh
This media is not supported in your browser
VIEW IN TELEGRAM
#linux #sysadmin 小科普:(简易)Graphviz 的 dot 怎么使用呢?
digraph J {
node [shape=record];
0 [label="江泽民"];
1 [label="胡锦涛"];
2 [label="习近平"];
0 -> 1 [style=solid, label="蛤"];
1 -> 2 [label="🐻"]
}
然后
dot -Tpng a.dot -o a.png
咳咳。那我就真说一下 Base64 编码的问题了。 #CS
这个问题是我看一篇小说《数据的尽头》注意到的,作者是JavaScript/PHP程序员。

讲解的时候犯了一些低级错误,我就不说了。

下面我编写的时候不会考虑性能问题,所以数据模型上会有很大出入。

Base64是什么?

/** Binary `2**8` 0-63 */
enum class Radix64 {
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,
`0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`,
`+`, `~`; /*'/'*/
companion object Read {
fun from(ordinal: Int): Radix64 = values()[ordinal]
fun from(c: Char): Radix64 = when (c) {
in 'A'..'Z' -> from(c.minus('A').toInt())
in 'a'..'z' -> from(c.minus('a').toInt()+26) //size[A-Z]
in '0'..'9' -> from(c.minus('0').toInt()+26+26) //size[A-Za-z]
else -> when (c) { '+' -> `+`; '/' -> `~`; else -> throw Error() }
} }
} //padding '='

typealias Base64 = Array<out Radix64>
interface Base64Coder {
fun from(orig: ByteArray): Base64
fun to(code: Base64): ByteArray
}


就是这样。
2**(8*3) = 64**4
2^{8*3}=64^4

可以使用 4 个Radix64来表达3个byte。
如何换算,才是问题所在。

那么怎么换算呢
就是进制换算啊

base=2 换算到 base=64 嘛。

都是用 2**6 速查表的…… 因为2**6直接对应到了Radix64
问题是编码后长度会有多长
因为加了padding我们认为输入长度肯定是
(n+3.dec()) / (3*4) + 1

首先想想padding是怎么用的
就是在最后一个单位(3byte)不足时,为1byte补两位、为2byte补一位的 '='

讲不下去了,实在想不出比率比率……
学不会算法尤其是看不懂数学公式,找不着等价算式的人废话最多
虽然数学不好,但其实也可以勉强弄一些逻辑性比数学性强的
比如说,一个深度为 N 的满二叉树,我知道它有 1+2**(N-1)个节点,而这个式子我能把它对应到二叉树的图形上(模糊地,因为这个抽象就是模糊的……
比如说,稍微想想还是能够想出Category甚至Functor里面的样子的,可惜我看到的是一堆模糊的东西,没有态射因为我只知 2=0.inc().inc(); 所以范畴就是一堆模糊的对象……
我实在没有办法,因为我就是数学不好。

我说的数学不好主要还是算术实在是做不过来,这样一些我需要枚举/计算一些东西的时候就会出差错或者至少影响我的思路
比如说,假如有一个 val a = if (p) 1 else 2,然后
下面哪怕是一个简单的 val b = a * 3
我根本没办法想出 p 不 p 时 b 有啥区别
可能稍微花个5秒我能想出来,不过这样的速度面向排错编程肯定是用不上了……(可能要尝试N遍来找一个可能的修法

其次是抽象上也不过关,比如说我经常忘记 1/2 是啥意思,好像它和 2/1 没区别一样。
实例就是,a*n/k 比率计算我都会觉得有点莫名其妙,要是再复杂一点的公式就GG了。
等式性质(比如 a*(a+1) 什么的)上可能勉强一点
#book 这些是我在学校里想起曾经看过的书……
感觉还是没有什么进步啊
果然是这样吗?

— 注,书名作者名全都是我记忆里的版本,不对正确性作出担保
《ES6标准入门》by 阮一峰
《Kotlin极简教程》by 陈光剑
《The Little Scheme — 递归与函数式的奥妙》 虽然现在表述式(过程式,命令式)、定义式(函数式,声明式)、逻辑式(描述式)都不流行hhhh?就是那个 The Little Schemer 的中文版
《嵌入式Linux系统与工程实践》
《完美应用OpenSUSE》by 何晓龙
《算法图解》 Grokking Algorithms
《算法I-IV(C++实现)》 Algorithms in C++ I-IV: Fundamentals, Data Structure, Sorting, Searching by Robert Sedgewick
《Ruby元编程 II》 Metaprogramming Ruby II
《深入剖析Ruby虚拟机》 Ruby under a Microscope by Paolo Patrick
《CLR via C# 中文版》 CLR via C# by Jeff Richester
《快速轻量级JavaEE开发》 Continuous Enterprise Development in JavaEE
《Qt5.9 C++实战》
《操作系统笔记2019》
《一本通 二级C语言》
《软件工程导论》
《有趣的二进制》
《Internet原理与技术》
《手把手教你FPGA设计——基于大道至简的设计法》
《职场新生代 嵌入式600问》
《小白都能看懂的Python大数据分析》
《LLVM Cookbook中文版》 LLVM Cookbook
《深入分析GCC》
《深入理解Java虚拟机——JVM高级特性与最佳实践》by 周志明
《PHP内核分析》
《Lua设计与实践》by codedump
最后还有一点我做的笔记 #CS #sysadmin #linux 我懒得详细讲了,照本宣科当人肉 OCR……

AWK -F
/regex/ {}
BEGIN {} END {}
gsub(/(\d)/, $1 "n")
print;
a=1;
for (i=0; i<10; i++)
NF, RS
str sprintf("%i", n)
while (1)

SED s/origin/substitution/g; s/a/b/g
tr -d '[:blank:]'
grep -E|-P, sort, uniq
[] || &&, |, >, >>
<<END
heredoc
END
head tail
head -n|-c
tail -c +N

cmd=`printf "str"`
$cmd


BasicBlock, CFG, CallGraph, SSA
AST,GENERIC,HL GIMPLE, LL GIMPLE, SSA GIMPLE, RTL, instruction scheduling, register allocation, coloring, spilling, peephole, pipeline
输入/输出、存储、运算、控制
nested function
(!partial)full parser
source map

.text .data .bss .rodata .symtab

call set use clobber return
对称(symmetric)、交换(commutative)

reg, subreg, mem, cc0, pc, scratch

asmos, sched, vector, call, emutls, c, cxx, option_hooks