Forwarded from duangsuse Throws
不少知识和信息,除了从书上看到我还从其他爱好者的资料里看到。
USTC ce 系学生的一些分享不知道为什么不见了,我很遗憾,因为那些资料也都很方便。
不过我给大家一个建议:比起直接从理解『解决方式』来理解问题,更应该从理解问题本身来理解问题的解决方式。
对任何复用库的开发者而言,设计时要以使用者的角度思考;对任何使用者而言,想理解问题要先自己设计一个问题的解决方案,然后从编写者的视角再看别人的解决方案。
或许用户的思维是幼稚的,可你不必总当用户。当你实践理论的时候,它们才真正到了你的脑子里。
我也相信,先理解问题还是先理解解法,是创造与重复之间最根本上的鸿沟。
USTC ce 系学生的一些分享不知道为什么不见了,我很遗憾,因为那些资料也都很方便。
不过我给大家一个建议:比起直接从理解『解决方式』来理解问题,更应该从理解问题本身来理解问题的解决方式。
对任何复用库的开发者而言,设计时要以使用者的角度思考;对任何使用者而言,想理解问题要先自己设计一个问题的解决方案,然后从编写者的视角再看别人的解决方案。
或许用户的思维是幼稚的,可你不必总当用户。当你实践理论的时候,它们才真正到了你的脑子里。
如果你对知识进行了彻底的分析和思考,且你脑海中生成的概念已经与生硬的文本之间没有很强的相似性,我们就认为这个知识是被理解的。(大意)据说这是冰封哥的一个朋友说的。emmm……
彻底的分析和非平凡的变换,是获得真知的标志性特征。
我也相信,先理解问题还是先理解解法,是创造与重复之间最根本上的鸿沟。
GitHub
USTC-Resource/USTC-Course
:heart:中国科学技术大学课程资源. Contribute to USTC-Resource/USTC-Course development by creating an account on GitHub.
duangsuse Throws
真的很替华为惋惜,虽然程序设计语言领域的冰封哥支持华为并且称有多为 CE 的朋友在开始工作了 可我觉得原型是很重要的,如果一个东西很久连个基本的框架都没有,我们是不是可以认为,它的可维护性很差?模块化程度太低???
说句不漂亮的话,本频道的订阅者和频道主都菜炸了,因为(ice1000、thautwarm)他们都开始 fmap 顺序了,谈什么 lift 成参数成闭包、lambda calculus 模型, unify lambda,dependent type, linear type system、形式化文法, ANF,冰封问怎么实现 sum type 还说 tagged union 外居然能用 visitor,
还谈论普通递归下降(准确的说是递归比较构造式二元结合)外的二元解析算法,还要用两个 double-linked list、reverse-polish,区分左结合右结合自定义的情况,对别人发的论文评头论足。
除了群里两三个大佬外还有一些活宝(但是随便抓一个出来水平都比我高,而且都是CE/CS/Math的,基本功过硬),而且有类似 hoshi野这样的低龄dalao的存在。
这还是今年二月份的消息,我都舍不得跳过编译原理群的哪怕是一条消息,一条消息都比 USTC ce 的、华为所谓方舟编译组的、什么知识付费啊培训班啦好上十倍。
在 LLVM 里和 exception handling 相关的 IR 有: (1)call (2)invoke (3)resume (4)ladingpad,
可能在别的地方这是『大佬』们显示自己『超常之处』的地方,可在这群有人都把这问题当笑话答。『我选call。』,『真强,完美避过所有正确答案。』
说句题外话,虽然我不是很了解 exception handling 的实现(只知道 cxa throw 啊 unwrap, personality 什么的),把绝句(我会实现它的) 的 catch 起名『
这就是个单纯为了讨论技术而生的Q群,别的什么都不管,尽管我更喜欢Telegram但我没找到资源那么集中的群,可以说只有AndroidCN稍微谈那么一点。
我要说,Android开发的话题就是比CE/PLT/FP(functional programming)/math/logics的低级,肯定有人不认账、不过我还真是觉得只会Android开发是不好的,总该多学点。
现在的我似乎很奇怪为什么即便 Java 的 Annotation Processor 可以生成代码,许多 Android 开发者也不会写 Annotation processor,是因为它写起来麻烦?
即便它可以用来生成代码的话也是一样?
说实在话,我觉得和他们群里一比,王垠什么的都爆炸了,比算法比不过,比 PLT, TT 更比不过,他是清华的又怎么样?我要是他,博文里绝对发满了新学到和做出来的算法和找到的新问题。
冰封高二的时候弄的『动态(时序)作用域优化』,今年二月都开始大谈实现同构(isomorphism)了。
而且不止是谈,而拿 Agda 写过实际的代码,这一点上是可以说已经上天了,而且这还是去年的事情。
每一天他们都不一样,士别三日都要做好心理准备才能接受,光看他们好像做了什么是只能了解大概的动向的。
和我对入门者、大牛的感觉一样,虽然你们看冰封 GitHub 都没起新项目,那是因为都拿去研究报告学习了。
还谈论普通递归下降(准确的说是递归比较构造式二元结合)外的二元解析算法,还要用两个 double-linked list、reverse-polish,区分左结合右结合自定义的情况,对别人发的论文评头论足。
除了群里两三个大佬外还有一些活宝(但是随便抓一个出来水平都比我高,而且都是CE/CS/Math的,基本功过硬),而且有类似 hoshi野这样的低龄dalao的存在。
这还是今年二月份的消息,我都舍不得跳过编译原理群的哪怕是一条消息,一条消息都比 USTC ce 的、华为所谓方舟编译组的、什么知识付费啊培训班啦好上十倍。
在 LLVM 里和 exception handling 相关的 IR 有: (1)call (2)invoke (3)resume (4)ladingpad,
可能在别的地方这是『大佬』们显示自己『超常之处』的地方,可在这群有人都把这问题当笑话答。『我选call。』,『真强,完美避过所有正确答案。』
说句题外话,虽然我不是很了解 exception handling 的实现(只知道 cxa throw 啊 unwrap, personality 什么的),把绝句(我会实现它的) 的 catch 起名『
接迎』是这个原因。当然我知道这不是多高明这就是个单纯为了讨论技术而生的Q群,别的什么都不管,尽管我更喜欢Telegram但我没找到资源那么集中的群,可以说只有AndroidCN稍微谈那么一点。
我要说,Android开发的话题就是比CE/PLT/FP(functional programming)/math/logics的低级,肯定有人不认账、不过我还真是觉得只会Android开发是不好的,总该多学点。
现在的我似乎很奇怪为什么即便 Java 的 Annotation Processor 可以生成代码,许多 Android 开发者也不会写 Annotation processor,是因为它写起来麻烦?
即便它可以用来生成代码的话也是一样?
说实在话,我觉得和他们群里一比,王垠什么的都爆炸了,比算法比不过,比 PLT, TT 更比不过,他是清华的又怎么样?我要是他,博文里绝对发满了新学到和做出来的算法和找到的新问题。
冰封高二的时候弄的『动态(时序)作用域优化』,今年二月都开始大谈实现同构(isomorphism)了。
而且不止是谈,而拿 Agda 写过实际的代码,这一点上是可以说已经上天了,而且这还是去年的事情。
每一天他们都不一样,士别三日都要做好心理准备才能接受,光看他们好像做了什么是只能了解大概的动向的。
和我对入门者、大牛的感觉一样,虽然你们看冰封 GitHub 都没起新项目,那是因为都拿去研究报告学习了。
duangsuse::Echo
说句不漂亮的话,本频道的订阅者和频道主都菜炸了,因为(ice1000、thautwarm)他们都开始 fmap 顺序了,谈什么 lift 成参数成闭包、lambda calculus 模型, unify lambda,dependent type, linear type system、形式化文法, ANF,冰封问怎么实现 sum type 还说 tagged union 外居然能用 visitor, 还谈论普通递归下降(准确的说是递归比较构造式二元结合)外的二元解析算法,还要用两个 double-linked…
把二元操作直接 parse 成一个操作序列而不是 infix binary tree…… 嗯…… 直接能上后序遍历结果?以后我可以考虑一下
我现在是在用手写递归下降的栈算法做的,如果用显式栈或许会快一些,不过我不在乎(我又不是 parser compiler 的编写者,只是用 parsec(ombinator) 就可以了)
结合不结合我都是用优先级考虑的(Lua式左右优先级实现),按降序先结合可能 (+) 是 (precL=1, precR=2) 这就是 inifixl.
我现在是在用手写递归下降的栈算法做的,如果用显式栈或许会快一些,不过我不在乎(我又不是 parser compiler 的编写者,只是用 parsec(ombinator) 就可以了)
InfixTree scanNextInfix(InfixTree base); 结合不结合我都是用优先级考虑的(Lua式左右优先级实现),按降序先结合可能 (+) 是 (precL=1, precR=2) 这就是 inifixl.
(1+2)+3 => (+2):1 <(+3):2
(1+2)+3 => (+3):2> (+2):1
duangsuse::Echo
常参/量/变参 定义(别人称为声明)是语句 (解量)赋值都是语句 判…[(值/属/在)],…… {以上情况皆,……} 否则,…… 注意 判p { 是真、是假,都一样()、回。 } 应该是有效的 是表达式 判断,…… {以上情况皆,……} 否则,…… 是语句 若…,……否则,…… 是表达式 若…,…… 是语句 尝试,…… {接迎……(成…)?,……} 是表达式 带上 终焉,…… 就是语句了 尝试将…成Name,…… 接迎~…… 是表达式 带上 终焉,…… 依然是语句 即便可以方便一点,绝句也没引入…
看了某位大佬的 reley (一个类似 Haskell 编译到 Python VM Bytecode 的程序设计语言)
我觉得,其实 Java 和 Kotlin 的
……还是留着吧,毕竟 Java 系的不是 Haskell 的风格
绝句还不是绝句Script 呢。
不过我觉得可以给「包」声明一个扩展:
等等……好像默认就是公开 emmm
这将有利于程序员对定义繁多的文件快速建立第一印象
我觉得,其实 Java 和 Kotlin 的
package…… 都不利于代码的简洁性,我是好好想了一会的,其实未必没有办法引入『导出』文法,代价是,必须去掉包声明,不然不好看……还是留着吧,毕竟 Java 系的不是 Haskell 的风格
绝句还不是绝句Script 呢。
不过我觉得可以给「包」声明一个扩展:
— 数域.jue来说明这个文件『公开』定义实现了的接口,但是
包 绝句.区间,
物,节域、短数域、数域、长数域、
浮数域、实数域。
公开的物 节域 这个公开修饰符不能省去,不然会使语法不一致不美观等等……好像默认就是公开 emmm
这将有利于程序员对定义繁多的文件快速建立第一印象
平时总是觉得数学有点难,其实除了自己真的是数学不好以外,还是有其他原因的。
数学,或者至少是『中等』(也就是高中水平)程度的数学,是运行思维的『形式化』方法。(其实也没有那么形式化哈)
数学也有很多抽象模型:数、运算、结合性、数轴、区间、集合、对(pair)、未知项和关系、逆运算、直角座标、极座标、映射、命题逻辑、微积分……
数上面的很多运算,除了可以用一个个计算的纸面表达方式(比如,递等式、开根式、除法上位,减、乘法十进制移位叠加……),其实也可以用其他的思想去表达:
+ 加法就是重复 "1"
1 + 2 = 1 + (1+1)
我知道这十分不好理解,不过『0』『1』的确应该是最特殊的数字了(但和二进制无关),小数分数都不够特殊。
从 1 开始的加法,可以直接从『数羊』这个行为想。
+ 乘法就是重复 "+"
1 * 3 = 1
11 + 21 = (1+1+1... (*10)*1 +1) + (1+1+1... (*10)(*2) +1)
解类似『我们这每人都有 10 只羊,一共有多少只?』这种问题的时候可以使用。
「羊」就是羊,「小明」的羊和「小红」的羊其实没有区别,都是「羊」。
数学允许我们在这个抽象角度上忽视掉无关量来思索问题,但需要注意的是,数永远代表着实际的含义:羊、用户、一棵树的分叉数目……
所以也就出现了『有效』和『无效』的数以及描述数值的『表达式』。
当然,表达式也是可以『惰性计算』的,就是说你 1+2+3 你可以描述成 (1+2)+3 而不一定非得计算时求 3+3 等于几
求解『两个足球队A,B(分别是a人,b人的)一对一PK能赛几场』这种问题也可用到乘法的定义:
显然对于 A 队伍的每个人,都得和 B 对的每个人 PK
所以,我们把 A 的每个人视为 (1+1+1... *b),这里的 "1" 表示一次比赛,最后实际上是b被『重复』了a次。
就是
求解配对问题也很类似,不过要去掉自己和自己的配对:
这也是一种抽象:不管你是什么,我只知道你是 "1"
不管你是小明还是小红,我只知道为了求得所有配对,你要和除自己外(n-1)个数的人配对。
+ 求幂就是重复 "*"
解类似可以用到乘方运算的定义:重复了『指数』次的『底数』
比如说,国家实现「全面二胎」的理想情况是,每两个人都有两个宝宝(惊恐)
如果一个住了5对夫妻的豪宅,照这样下去3代,第三代多少人?(无论死活长幼,子代一定与外人结婚……)
5*(2**3) 得40人,其中 (2**3) 是8,算的是一个家庭三代产生的宝宝数目。
想象一下:
+ 第一代的夫妻有2个宝宝
+ 第一代产生的2人找到配偶后,每人也都有2个宝宝
+ 第三代的宝宝长大后也是一人两个宝宝
+ 2*2*2 = 2**3,就是这个逻辑,算的是三代后的宝宝数目
如果要算总人数可以用递推函数式表达:
其中b是每代娃娃数,c是此代总人数,gen是代数
当然是可以优化的
+ 求对数(logarithm)就是给定『乘』的并列次数求并列项
这个相对困难些,用处比如: log10 100 = 10,你
对数还应该提到 ln 和 e,不过我不知道是为什么。
+ 求方根(root)就是给定『乘』的并列项求并列次数,这不是太困难,因为可以直接除:
求最终解构的乘法数目(也就是可以除的数目),所以不困难
+ 除法(a / b)就是算 a 里出现了几次 b
比如:小明一家每天炖一只羊,请问:50只羊够他们炖几天?
+ 取模 (a mod b) 可以保证 (a mod b) 结果小于 b,如果不够除,则值是a。
它的「循环」(因为『除』是按『一块一块的b』来算的)性质偶尔被拿来作指针碰撞(移动啦……)
整除 (a mod b) == 0 的性质偶尔被用来作图
+ 小数就是把一切乘一个倍数,以某一种最小单位(而不是整数 "1")执行计算
+ 小数和分数都是可以互化的(不过有些分数只能化成无限位长的小数……)
不过分数是有一个基本性质: a/b = (a*c)/(b*c)
分子分母同时乘一个c,分数值不变。
举例:(9)班有10位同学,全班的同学一共有20只眼睛,每人都有两只眼睛(20/10,10位同学平分20只眼睛,正好一人一双)。
某个学校有10个班,每个班的情况都是这样,请问这个学校每个人有几只眼睛?
由分数的这个性质我们可以在不实际除法计算的情况下,得出这10个班级里也是一人2只眼睛。
这不是小学数学,同时,我想说:现在很多程序员真的是连小学数学的所谓『数学逻辑』『数学性』都败光了。
数学的优雅性和准确性,嗯哼?
老实想想,这些看似『低级』的解释方法,自己现在还记得几条?自己编程的时候又用到几条?
当然数学也是可以涉及除了表达式本来『结合顺序』外的基本逻辑的:
+ 函数可以是『分支函数』,实现了控制上的『判断』
+ 函数可以定义成递推式的形式,也就是递归『重复』
关于是否的确能够『循环计算』,当然是可以的,毕竟至少有应用序 Y 组合子(applicative order Y combinator)嘛
注意这里两个 \c... 是一样的(也自然是循环的『样子』喽)
稍微有点数学/逻辑学爱好的人一定知道逆波兰记法(reverse polish notation):
(1+3)*6 等价后缀(postfix)表示的
后缀表示我就不说什么了,一个 LIFO。(后压入的先弹出,换到Java字节码就是先求值push的最后pop,按此顺序『倒数第一参数最先求值』)
数学主要的缺点是在表示上:虽然一些人眼里数学的确是很『天才』(当然不天才也没什么过错)
数学的高冷风格(什么希腊字母啊……把「美」和「丑」、「简洁」和「冗长」、会和不会分得太开)反而是不好。
比如说,『年久失修的伦敦大桥终于塌了。』
用数学的话说就是『伦敦大桥塌了。』
这很简洁,可是也包含一点不那么令人满意的因素:
+ 一些数学者认为,『年久失修』这个信息是可以从『大家都会』的知识上下文里推导出来的,所以不需要写明。
并且当他们往下说的时候,已经默认你把『伦敦大桥』想成是『年久失修』的伦敦大桥,可是,万一有些人认为它只是『设计不当』,或者干脆笨一点,没想过『伦敦大桥』是什么样的,该怎么办?
这类人往往被数学者称为『IQ低』『理解力差』。
+ 『终于』可以删掉而完全不影响这句话的数学含义,可是它实际上是有作用的:表达了作者对此事件的情感。
虽然这一条你看不出它对下文有什么用处,可保不准缺了它,就会使得本来不多的相关表达更少了隐含的信息。
其实写不写明这是个仁者见仁的问题,实在是和『艺术是瞬间的还是永恒的』这个问题一样争论不休,自然是各有各的好处,所以我们说点别的。
一般来说,接触某个新问题的人都必须先大概知道为什么会有这个问题,以及解决这个问题的示例,这样才能更好的理解问题。
一上来就以一种
从这个角度看,《算法(C++)实现III》一书可以说是正面例子了 -- 讲算法先讲道理,全书内容信息依赖安排得当,与目标群体的原本知识系统相契合。
Robert Sedgewick 就真是字面意义上的『教授』,名副其实。
大部分人会觉得计算机科学是为计算机解决问题而生的,而数学是为人解决问题而生的。
其实好像一切都喜欢反着来:计算机科学看起来是更考虑人的感受,而数学则是半人半机。
数学,或者至少是『中等』(也就是高中水平)程度的数学,是运行思维的『形式化』方法。(其实也没有那么形式化哈)
数学也有很多抽象模型:数、运算、结合性、数轴、区间、集合、对(pair)、未知项和关系、逆运算、直角座标、极座标、映射、命题逻辑、微积分……
数上面的很多运算,除了可以用一个个计算的纸面表达方式(比如,递等式、开根式、除法上位,减、乘法十进制移位叠加……),其实也可以用其他的思想去表达:
+ 加法就是重复 "1"
1 + 2 = 1 + (1+1)
我知道这十分不好理解,不过『0』『1』的确应该是最特殊的数字了(但和二进制无关),小数分数都不够特殊。
从 1 开始的加法,可以直接从『数羊』这个行为想。
+ 乘法就是重复 "+"
1 * 3 = 1
11 + 21 = (1+1+1... (*10)*1 +1) + (1+1+1... (*10)(*2) +1)
解类似『我们这每人都有 10 只羊,一共有多少只?』这种问题的时候可以使用。
「羊」就是羊,「小明」的羊和「小红」的羊其实没有区别,都是「羊」。
数学允许我们在这个抽象角度上忽视掉无关量来思索问题,但需要注意的是,数永远代表着实际的含义:羊、用户、一棵树的分叉数目……
所以也就出现了『有效』和『无效』的数以及描述数值的『表达式』。
当然,表达式也是可以『惰性计算』的,就是说你 1+2+3 你可以描述成 (1+2)+3 而不一定非得计算时求 3+3 等于几
求解『两个足球队A,B(分别是a人,b人的)一对一PK能赛几场』这种问题也可用到乘法的定义:
显然对于 A 队伍的每个人,都得和 B 对的每个人 PK
所以,我们把 A 的每个人视为 (1+1+1... *b),这里的 "1" 表示一次比赛,最后实际上是b被『重复』了a次。
就是
solve(a, b) = a*b 了,或者说 solve = (*) 。求解配对问题也很类似,不过要去掉自己和自己的配对:
paircount-of(n) = n*(n-1)这也是一种抽象:不管你是什么,我只知道你是 "1"
不管你是小明还是小红,我只知道为了求得所有配对,你要和除自己外(n-1)个数的人配对。
+ 求幂就是重复 "*"
解类似可以用到乘方运算的定义:重复了『指数』次的『底数』
比如说,国家实现「全面二胎」的理想情况是,每两个人都有两个宝宝(惊恐)
如果一个住了5对夫妻的豪宅,照这样下去3代,第三代多少人?(无论死活长幼,子代一定与外人结婚……)
5*(2**3) 得40人,其中 (2**3) 是8,算的是一个家庭三代产生的宝宝数目。
想象一下:
+ 第一代的夫妻有2个宝宝
+ 第一代产生的2人找到配偶后,每人也都有2个宝宝
+ 第三代的宝宝长大后也是一人两个宝宝
+ 2*2*2 = 2**3,就是这个逻辑,算的是三代后的宝宝数目
如果要算总人数可以用递推函数式表达:
total-count(b, gen, c)|gen == 0 = c|else = c+total-count(b, gen-1, c*b)其中b是每代娃娃数,c是此代总人数,gen是代数
当然是可以优化的
+ 求对数(logarithm)就是给定『乘』的并列次数求并列项
这个相对困难些,用处比如: log10 100 = 10,你
floor(log10(x)) 就可以得到十进制位数了(二进制有 Striling 公式,不过也是可以用对数算)对数还应该提到 ln 和 e,不过我不知道是为什么。
+ 求方根(root)就是给定『乘』的并列项求并列次数,这不是太困难,因为可以直接除:
sqrt(2) = 1sqrt(n*2) = 1+sqrt(n)求最终解构的乘法数目(也就是可以除的数目),所以不困难
+ 除法(a / b)就是算 a 里出现了几次 b
比如:小明一家每天炖一只羊,请问:50只羊够他们炖几天?
+ 取模 (a mod b) 可以保证 (a mod b) 结果小于 b,如果不够除,则值是a。
它的「循环」(因为『除』是按『一块一块的b』来算的)性质偶尔被拿来作指针碰撞(移动啦……)
整除 (a mod b) == 0 的性质偶尔被用来作图
+ 小数就是把一切乘一个倍数,以某一种最小单位(而不是整数 "1")执行计算
+ 小数和分数都是可以互化的(不过有些分数只能化成无限位长的小数……)
不过分数是有一个基本性质: a/b = (a*c)/(b*c)
分子分母同时乘一个c,分数值不变。
举例:(9)班有10位同学,全班的同学一共有20只眼睛,每人都有两只眼睛(20/10,10位同学平分20只眼睛,正好一人一双)。
某个学校有10个班,每个班的情况都是这样,请问这个学校每个人有几只眼睛?
(20*10/10*10) = (20/10) = 2由分数的这个性质我们可以在不实际除法计算的情况下,得出这10个班级里也是一人2只眼睛。
这不是小学数学,同时,我想说:现在很多程序员真的是连小学数学的所谓『数学逻辑』『数学性』都败光了。
数学的优雅性和准确性,嗯哼?
老实想想,这些看似『低级』的解释方法,自己现在还记得几条?自己编程的时候又用到几条?
当然数学也是可以涉及除了表达式本来『结合顺序』外的基本逻辑的:
+ 函数可以是『分支函数』,实现了控制上的『判断』
+ 函数可以定义成递推式的形式,也就是递归『重复』
关于是否的确能够『循环计算』,当然是可以的,毕竟至少有应用序 Y 组合子(applicative order Y combinator)嘛
Y = \f. (\c. (f (c c))) (\c. (f (c c)))注意这里两个 \c... 是一样的(也自然是循环的『样子』喽)
稍微有点数学/逻辑学爱好的人一定知道逆波兰记法(reverse polish notation):
(1+3)*6 等价后缀(postfix)表示的
1 3 + 6 *后缀表示我就不说什么了,一个 LIFO。(后压入的先弹出,换到Java字节码就是先求值push的最后pop,按此顺序『倒数第一参数最先求值』)
数学主要的缺点是在表示上:虽然一些人眼里数学的确是很『天才』(当然不天才也没什么过错)
数学的高冷风格(什么希腊字母啊……把「美」和「丑」、「简洁」和「冗长」、会和不会分得太开)反而是不好。
比如说,『年久失修的伦敦大桥终于塌了。』
用数学的话说就是『伦敦大桥塌了。』
这很简洁,可是也包含一点不那么令人满意的因素:
+ 一些数学者认为,『年久失修』这个信息是可以从『大家都会』的知识上下文里推导出来的,所以不需要写明。
并且当他们往下说的时候,已经默认你把『伦敦大桥』想成是『年久失修』的伦敦大桥,可是,万一有些人认为它只是『设计不当』,或者干脆笨一点,没想过『伦敦大桥』是什么样的,该怎么办?
这类人往往被数学者称为『IQ低』『理解力差』。
+ 『终于』可以删掉而完全不影响这句话的数学含义,可是它实际上是有作用的:表达了作者对此事件的情感。
虽然这一条你看不出它对下文有什么用处,可保不准缺了它,就会使得本来不多的相关表达更少了隐含的信息。
其实写不写明这是个仁者见仁的问题,实在是和『艺术是瞬间的还是永恒的』这个问题一样争论不休,自然是各有各的好处,所以我们说点别的。
一般来说,接触某个新问题的人都必须先大概知道为什么会有这个问题,以及解决这个问题的示例,这样才能更好的理解问题。
一上来就以一种
a=1 => ab 式的语序(当然一个问题里还不止这一种)说定义,甚至弄出什么 若……对所有……且……当…… 这样连在一起分不清主次和句子结构的东西,那不用说自然是只会从自己的角度考虑问题的『聪明人』了。从这个角度看,《算法(C++)实现III》一书可以说是正面例子了 -- 讲算法先讲道理,全书内容信息依赖安排得当,与目标群体的原本知识系统相契合。
Robert Sedgewick 就真是字面意义上的『教授』,名副其实。
大部分人会觉得计算机科学是为计算机解决问题而生的,而数学是为人解决问题而生的。
其实好像一切都喜欢反着来:计算机科学看起来是更考虑人的感受,而数学则是半人半机。
为什么数学有时候反而应该是『更适合计算机阅读』?其实是因为数学想表达的东西太宽泛也太松散了,
数学家说数学有很强的逻辑性,其实让自然语言学家来看看:的确是很明确 -- 比如,p q 是一个『对(pair)』里两个项目的名字
这很准确,但这会使得我们不知道 p, q 里哪一个是『主语』、哪一个是『宾语』,即便实际上哪个都不是也哪个都是(因为它们的关系具有对称性(symmetric)),这才是数学嘛。
编程时我们一般认为从左到右,左边的是『宾语』(操作的对象,相等判断的变量) 比如
上面这个问题也出现在合并查找(union find)的算法里,如果引入逻辑上的传递性(a R b; b R c)而不止『数对』,就会很容易解决『没主语』的问题了,而且不会影响到逻辑的严密性。
其实不少数学问题在正常人看来都是描述『语序不当』甚至略微『成分残缺』,之所以觉得没有问题是习惯了而已,但习惯了也不能代表是最好的做法。
数学习惯的就是把一堆『特化』的东西(比如「逆命题」「简单命题」「复合命题」「分数」「小数」「无理数」「非负数」……)和没特化的大体混在一起,所以你得自己给他们归到树型,你得知道「XX命题」都是「命题」、「XX数」都是「数」…… 并且好好总结一下他们的特点和计算 -- 这不就是编程时高层抽象的多态吗?
如果只有看一个问题的能力,数学水平不容易提高,但是数学家也真是应该好好改正一下自己的说话水平了,如果不能以初学者的视角看问题,就找不到在表达上优化的方法。
计算机科学,它不像数学里,有些东西实际上是来自于数学者的『直觉』的,直觉这个东西往往很有用,但对传达知识来说,它会严重影响其他人对知识的理解(因为你「隐式」也就是「含糊」地引用了某些概念,比如什么「即得」啊「易证……」啊「只要证……」啦)。
许多数学书,比如你们的人教课本上,就会在某些问题上略过一些直白的解释,使得数学感不好的人保持半通不通只能靠做题找感觉的样子。(当然即便做了题考满分也未必代表彻底理解了)
计算机就像是什么都不会的婴儿,它很有执行能力,但完全是一片空白,所以我们不得不更加严密地处理『导入』问题(因为它和所有人一样,是有所不知的,最重要的是它比任何人都「蠢」,只会你教它的),仔细界定问题涉及到的计算、模型,这一点是许多数学问题从来不曾想的 -- 反正那一切都是数学,数学就是一堆纠缠在一起『密不可分』的模型概念。
甚至一个偏序理论,都或多或少地和几何纠缠在一起,问题得不到根本上的简化,自然对大部分人来说难以理解了。
所以计算机科学和数学对某个问题的解释,往往是数学的含糊一些,计算机科学的长不少;像是很多计算机会区分整数和浮点,而数学认为数可以是整数、分数、小数、非1自然数……,甚至是虚数)
同桌问我(一个app)为什么分苹果版和Android版,我反问他:
其实我也清楚这很不准确,但我觉得对一个问题,兴趣和简明的第一印象,远比定义是否准确更重要吧。
只是说一下看法而已。 #CS #Math
数学家说数学有很强的逻辑性,其实让自然语言学家来看看:的确是很明确 -- 比如,p q 是一个『对(pair)』里两个项目的名字
这很准确,但这会使得我们不知道 p, q 里哪一个是『主语』、哪一个是『宾语』,即便实际上哪个都不是也哪个都是(因为它们的关系具有对称性(symmetric)),这才是数学嘛。
编程时我们一般认为从左到右,左边的是『宾语』(操作的对象,相等判断的变量) 比如
[i++] == '\0' ,为什么我们不反着来?可是如果命名为 p q,理论是优雅了,写起来可是略微『美丽冻人』。上面这个问题也出现在合并查找(union find)的算法里,如果引入逻辑上的传递性(a R b; b R c)而不止『数对』,就会很容易解决『没主语』的问题了,而且不会影响到逻辑的严密性。
其实不少数学问题在正常人看来都是描述『语序不当』甚至略微『成分残缺』,之所以觉得没有问题是习惯了而已,但习惯了也不能代表是最好的做法。
数学习惯的就是把一堆『特化』的东西(比如「逆命题」「简单命题」「复合命题」「分数」「小数」「无理数」「非负数」……)和没特化的大体混在一起,所以你得自己给他们归到树型,你得知道「XX命题」都是「命题」、「XX数」都是「数」…… 并且好好总结一下他们的特点和计算 -- 这不就是编程时高层抽象的多态吗?
如果只有看一个问题的能力,数学水平不容易提高,但是数学家也真是应该好好改正一下自己的说话水平了,如果不能以初学者的视角看问题,就找不到在表达上优化的方法。
计算机科学,它不像数学里,有些东西实际上是来自于数学者的『直觉』的,直觉这个东西往往很有用,但对传达知识来说,它会严重影响其他人对知识的理解(因为你「隐式」也就是「含糊」地引用了某些概念,比如什么「即得」啊「易证……」啊「只要证……」啦)。
许多数学书,比如你们的人教课本上,就会在某些问题上略过一些直白的解释,使得数学感不好的人保持半通不通只能靠做题找感觉的样子。(当然即便做了题考满分也未必代表彻底理解了)
计算机就像是什么都不会的婴儿,它很有执行能力,但完全是一片空白,所以我们不得不更加严密地处理『导入』问题(因为它和所有人一样,是有所不知的,最重要的是它比任何人都「蠢」,只会你教它的),仔细界定问题涉及到的计算、模型,这一点是许多数学问题从来不曾想的 -- 反正那一切都是数学,数学就是一堆纠缠在一起『密不可分』的模型概念。
甚至一个偏序理论,都或多或少地和几何纠缠在一起,问题得不到根本上的简化,自然对大部分人来说难以理解了。
所以计算机科学和数学对某个问题的解释,往往是数学的含糊一些,计算机科学的长不少;像是很多计算机会区分整数和浮点,而数学认为数可以是整数、分数、小数、非1自然数……,甚至是虚数)
同桌问我(一个app)为什么分苹果版和Android版,我反问他:
猫能吃鱼,狗也可以吗?所以食物得分开给。
他又问『那为什么这个(web应用)不分了呢?』,我就回答:猫是动物,能叫;狗也是动物,也能叫,所以有时候不用分太开。
难道我要提到,Android和iOS本身「软件包『格式』不兼容」甚至「Android有libdvm.so,iOS没有」「基于JavaScript和DOM只需要他们都实现了这种(WWW)技术即可,和(原生)应用大不一样」这种技术细节?其实我也清楚这很不准确,但我觉得对一个问题,兴趣和简明的第一印象,远比定义是否准确更重要吧。
只是说一下看法而已。 #CS #Math
我可以很轻松写 Lisp 系的解释器,也可以同样轻松地写 JSON 解析器、计算器;但是 Trie 树实在是难写啊!怎么还分四种情况?还要把叶子上岔出分叉来?
可是如果我不写 Trie 树,就没法实现自定义的二元运算符了…… 因为没有线索树的话,扫描 a+b 这种就不知道该何时分 a,b 这些名字和加号了 emmmm 😂
我不敢用别人的实现,我觉得他们实现得肯定更复杂更难看,我只需要一个简单、递归的 API 就够了……
还以为能够写出带启发式合并的 Radix 树的
RangeMap 什么的也很绕啊…… 不过不像 Trie 树的泛型那么烧脑
可是如果我不写 Trie 树,就没法实现自定义的二元运算符了…… 因为没有线索树的话,扫描 a+b 这种就不知道该何时分 a,b 这些名字和加号了 emmmm 😂
我不敢用别人的实现,我觉得他们实现得肯定更复杂更难看,我只需要一个简单、递归的 API 就够了……
还以为能够写出带启发式合并的 Radix 树的
RangeMap 什么的也很绕啊…… 不过不像 Trie 树的泛型那么烧脑
duangsuse::Echo
我可以很轻松写 Lisp 系的解释器,也可以同样轻松地写 JSON 解析器、计算器;但是 Trie 树实在是难写啊!怎么还分四种情况?还要把叶子上岔出分叉来? 可是如果我不写 Trie 树,就没法实现自定义的二元运算符了…… 因为没有线索树的话,扫描 a+b 这种就不知道该何时分 a,b 这些名字和加号了 emmmm 😂 我不敢用别人的实现,我觉得他们实现得肯定更复杂更难看,我只需要一个简单、递归的 API 就够了…… 还以为能够写出带启发式合并的 Radix 树的 RangeMap 什么的也很绕啊………
其实并不是真的完全没法用,只是性能会差很多:有 N 个项目的情况下找一个 M 长度的键
Trie 树最差情况下也是
如果你用列表一个一个排除,最差情况是每个都试到最后一个字符,然后都失败:
Trie 树最差情况下也是
O(M) 的时间复杂度,是线性,非常稳定如果你用列表一个一个排除,最差情况是每个都试到最后一个字符,然后都失败:
O(M*N)trie.zip
2.1 MB
已经失败了,初试不利。
看来只能量力而行,我打算这周暂时不写 Trie,更不可能写 Radix 树了,先做点力所能及的工作吧。
但是,其实也是有好的地方的,因为我的 Feeder 写的可以说是史无前例的简单、不强耦合,简单到我都觉得有点不正常,但它就是 works
至于 Trie 的泛型和建支问题,我相信以后会有改进。
看来只能量力而行,我打算这周暂时不写 Trie,更不可能写 Radix 树了,先做点力所能及的工作吧。
但是,其实也是有好的地方的,因为我的 Feeder 写的可以说是史无前例的简单、不强耦合,简单到我都觉得有点不正常,但它就是 works
至于 Trie 的泛型和建支问题,我相信以后会有改进。
https://github.com/evil-huawei/evil-huawei/tree/master/events/%E5%8D%8E%E4%B8%BA%E5%9B%9B%E5%A4%A7%E5%90%8D%E8%91%97 #huawei #Low #China
GitHub
evil-huawei/events/华为四大名著 at master · evil-huawei/evil-huawei
Evil Huawei - 华为作过的恶. Contribute to evil-huawei/evil-huawei development by creating an account on GitHub.
duangsuse::Echo
自从用上 Java 后,我写算法的能力越发降下了;本来我还想 peek 一下 BST(binary search tree) 的 mid 然后判 GT LT EQ 再二分找的 (GT -> first(LE); LT -> last(LE)),JDK NavigableSet<E> 都直接弄好了……
有了 RangeMap,可以实现光标下的符号高亮解析这样的功能,当然没有的话就几乎很难实现了,太慢
虽然只能在 JDK 上用……(Kolin 好像没 sorted sets?)
虽然只能在 JDK 上用……(Kolin 好像没 sorted sets?)