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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
duangsuse::Echo
failure.tar
结论:因为已经花费了一个小时,我觉得很累就算了...
duangsuse::Echo
结论:因为已经花费了一个小时,我觉得很累就算了...
现在改成仅仅使用 FreeType 画图然后 libGD2 输出即可

*... 的确是很累... 如果用 Java 和 Canvas 的话或许会简单一些?

图片 转 字符画 彩色 🔍 DuckDuckGo
暂时打算:

1. 一个图片蒙版文字的独立 CLI 程序,使用 FreeType 和图形库
2. MinBase64 Kotlin 翻译
3. Telegram 补丁
4. Haskell ftree 实现
duangsues.is_a? SaltedFish
暂时打算: 1. 一个图片蒙版文字的独立 CLI 程序,使用 FreeType 和图形库 2. MinBase64 Kotlin 翻译 3. Telegram 补丁 4. Haskell ftree 实现
关于这个字符画的问题,其实我说的所谓『蒙板字符画』
就是现在一些设计杂志封面上会使用的、以及 一个木函 现在支持的字符画模式

实际上没有真正弄出文本输出,过程类似于(抽象 PorterDuff 混成模式的):

图层 1(dst):自动折行的文本视图,无限重复『字符画文字』直到布满整个视图,视图大小和图层 0 一致,使用 SrcOver | DstIn 模式(只绘制图层 0 与图层 1 交汇的地方,置顶图层 0)
图层 0(src):原图片

另一种模式是类似冰封博客上教的那种,利用颜色/灰度分析取平均什么的拿到总结的数据,然后实际上输出字符序列

还有一种是输出图片,不过不是无限重复字符画文字,而是基于像素视图灰度综合选取 ASCII 字符填上的,反正都差不多。
#PL https://github.com/qnnnnez/rs

曾经在百度贴吧看到的邮电二进制序列化大佬... 现在居然也写 Sexp 语言解释器了...

二进制处理的算法我之前也写过,没有这位的那么高级那么实用,是解包一游戏的数据的。
而且也不如这个 C++ 的... 跨平台、内建序列化框架、C++ template 使用、各种图像纹理和波形、字体字形 glyph 解包打包什么的...

不过,我看(Sexp 解析器)的时候居然估计错了一个,真是该打... 太菜了...

https://github.com/qnnnnez/rs/blob/master/src/sexpr.rs#L53

我居然蠢到以为 self 里不保存扩号开闭堆叠状态的话肯定是不行的,然后一厢情愿地认为肯定是分配了新对象然后递归...
其实是单纯递归就可以了... 这次是我突然脑抽了一下,其实我还是知道的,之前我设计的 SubsequenceParser 就是属于上面那种脑残做法,而后来我设计的 HeapParser 其实就是递归下降解析,不过不把递归信息保存在栈上而是保存在堆上

伪代码(顺便教可能不了解解析器的你们如何手写解析器,当然是 parser combinator style 的 『广义』解析器):

Peekable<char> input; // 可以理解为字符流 Stream<Character>,标准输入
char current_char; // 当前字符,方便在函数直接传递

/* 常量 */
char PAREN_OPEN = '(';
char PAREN_CLOS = ')';
char BLANK = ' '; // 要跳过的空格

/* 辅助函数 auxilary */
fn nextChar() { current_char = input.peek(); }
fn getChar() -> char { return current_char; }

nextChar(); // seek 到第一个 char(虽然此操作不真正是 seek)

/* 解析:无解析状态 */
fn lexToplevel() -> Vec<Sexp> {
let mut result_vec = vec![];

loop {
match getChar() {
PAREN_OPEN => result_vec.push(lexList()), // 如果是列表,则进入列表分词状态
/* 不应该出现不对称的闭扩号,对应(有开有闭)的闭扩号应该在解析列表时已经跳过了,不应该在顶层出现 */
PAREN_CLOS => panic!("Unmatched parenthesis: Shold NOT seen closing paren lexing toplevel"),
BLANK => next, // skip blanks
EOS => break,
_ => result_vec.push(lexAtom())
}
nextChar();
}
return result_vec;
}

fn lexList() -> Vec<Sexp> {
assert!(getChar() == PAREN_OPEN);
nextChar(); // 跳过开始的 '(' 字符
let mut ret = vec![];
while (getChar() != PAREN_CLOS && getChar() != EOS) {
ret.push(lexToplevel()); // 直到最后看到列表结束符 ')',我们知道列表嵌套的问题已经在 lexToplevel() 里处理好了,所以不去管这个递归定义
nextChar();
}
if (getChar() == EOS) panic!("Unclosed parnthesis till EOS");
nextChar(); // 之前的状态应该是 getChar() == PAREN_CLOS,nextChar() 跳过这个闭扩号
return ret
}
fn lexAtom() -> Atom { /* implementation omitted */ }

~~所以这里啊我们可以看到现在流行的一个解析组合子的逻辑结构,多么优美,一切状态可以通过递归组合传递,语言层面的支持,不像那些循环 state based lexer,一大堆 yystat、pushState 很难看~~

那么我们来看看它如何解析一些简单的小程序(虽然都是简单的东西,感到羞愧。)

()
首先 seek 到输入 (,lexToplevel 分派到 lexList,
while 循环直接没进(因为 ( 后面已经是 ) 了
nextChar 到 eos,返回 toplevel 后结束分词

()()
[()()]lexToplevel => [()()]lexList{[]}[()] |> {[]}[()]lexToplevel => lexList{[][]}() |> {[][]}lexToplevel

(()) 这个比较有意思,因为开始使用调用栈记录嵌套了
首先 ( 分派 lexList,lexList 再 lexToplevel,lexToplevel 看见第二个 ( 又调用 lexList
此时调用栈是这样的:

lexList $j = [ $k ]
lexToplevel $i = $j
lexList [ $i ]
lexToplevel (())

递归到这里(栈顶)实际上已经结束了,因为中间第二个 ( 后面直接就是 ),没有别的,然后递归回溯得到结果

$k = (none)
$j = []
$i = []
lexToplevel (()) = [[]]

(1 ())

lexToplevel (1 ()) =
lexList 1 () : [] =
lexAtom 1 : lexList () : [] =
1 : [] : [] = [1 []]

((1) 2222 hhhhh ())

lexToplevel ((1) 2222 hhhhh ()) =
(in lexList) {(1) 2222 hhhhh ()} : [] =
(in lexList) {{1 : []} 2222 hhhhh ()} : [] =
(in lexAtom) {{#1 : []} 2222 hhhhh ()} : [] =
(in lexAtom) {{#1 : []} #2222 hhhhh ()} : [] =
(in lexAtom) {{#1 : []} #2222 #hhhhh ()} : [] =
(in lexList) {{#1 : []} #2222 #hhhhh {[]}} : [] =

— 开始回溯归约 —
{{#1 : []} #2222 #hhhhh []} : []
{{#1 : []} #2222 hhhhh []} : []
{{#1 : []} 2222 hhhhh []} : []
{{1 : []} 2222 hhhhh []} : []
{[1] 2222 hhhhh []} : []
[[1] 2222 hhhhh []]

((()) 这个有意思的地方在于它会失败,因为没有闭扩号就 EOS 了,猜猜在哪里 EOS,那时调用栈是啥样(

比起 HeapParser 手动维护的数据结构,系统调用栈记录的可能更多,一个调用(call)没有返回(return)的时候,调用者(caller)处于尚没有完成执行的状态,等待被调用者(callee)求值完成
我比较奇怪就是单靠记录一个 level 和一个 heap 上的 list 可不可以就直接像 recursive descent method (递归下降解析法)一样直接能解析了,奇怪的是好像无法做到区分 ()()()() (1)((1)) 这种嵌套一样
递归的确是比较好玩的,因为实际上,类似现在 Coroutines 和各种 CPS 一样,调用帧记录了返回地址,也即函数的 continuation,所以被挂起没有完成执行的函数实际上有足够的信息在恢复执行时规约到完整的 AST(因为我们实际上的确记录了要把项目插入在哪里(通过记录返回地址的函数调用完成))

递归之美。

看看 Rust 的 enum ADT(代数数据~~结构~~ 类型) 多么优雅(

#[derive(Debug)]
pub enum SExpr {
Atom(SAtom),
List(Vec<SExpr>),
Quote(Box<SExpr>),
}

#[derive(Debug)]
pub enum SAtom {
Symbol(String),
Integer(i64),
Bool(bool),
Char(char),
}
duangsuse::Echo
#PL https://github.com/qnnnnez/rs 曾经在百度贴吧看到的邮电二进制序列化大佬... 现在居然也写 Sexp 语言解释器了... 二进制处理的算法我之前也写过,没有这位的那么高级那么实用,是解包一游戏的数据的。 而且也不如这个 C++ 的... 跨平台、内建序列化框架、C++ template 使用、各种图像纹理和波形、字体字形 glyph 解包打包什么的... 不过,我看(Sexp 解析器)的时候居然估计错了一个,真是该打... 太菜了... https://g…
总之呢... 不管怎么样的话自己工程能力都是欠佳的吧...
唉...

只能指望以后能有点长进就是了,现在也想不到什么严谨准确一点的方法能够加快这类模型的处理的...
结果是连文件树算法都不会写呢?

dfs... 怎么不应该会写,解析器嵌套二维文法处理的话如果不会就惨了...

C 语言上面的目前是考虑到一些过程式的逻辑和语言特性、库函数还不熟悉,尤其是 C 的各种函数库因为 API 封装不良好,又没有好的 IDE 智能感知推荐的话,设计起来比 OOP 们烧脑一些,比 Java EE 入门还耗时
C++ 又是特性一大把,各种语法设计太多了,学起来坡也是很陡
算法的话自然都是要花时间的,伪代码逻辑都需要时间,这个无所谓。
各种新的数据模型,比如 Glyph、Font face 什么的由于是新模型自然理解要花时间
比上 Android 的话其实 Android 某些新 GUI 控件学习也得花时间,控件布局模型基础也得花时间,都是必须的,不过因为做的多做的久的缘故就可以不那么多的学习新东西,不过 Android 的话有各种博客可以看,我自己看的是稍微麻烦一点的 C API 的英文文档和示例,这么看其实我平时失败是有缘由的(疯狂自我安慰)

不过现在好歹也有个 CRT (C 运行时)的底层视角,干什么也方便一些(疯···)
不过现在好歹弄完也会总结一下命名模式、生命周期、使用流程什么的了,起码不虚此行(疯···)
不过 JavaEE 那些是属于 DevOps、代码外的 XML 配置、运维什么的涉及得比较多,和编程能力无关(疯···)
不过我打字再快一点说不定就好很多(疯···)
不过我一些技巧性的模式性的东西肯定学得比别人快(疯···)
反正别人也没有这能力,那我不会也罢(...来,你说别人不会,你看看这个,它可以代表现在的一些你所认为『简单』的串行(单线程顺序模型)程序逻辑复杂度了〖考虑到某些框架、库使用的缘由〗)

另外,单单会做和做好还有区别啊... 不能一下子写出良好实践做到优化的话,比较不像是好程序员的样子。
https://github.com/drakeet/XiaoaiBot/blob/master/app.py#L311
#Python 居然还有这种语法.... Haskell 有没?哦 Haskell 只有 List Comprehension... 不过可以 ZipWith 成 [[a]] 就是了
aliases_dict = {x.get('key'): x.get('value') for x in alises}

NOTE,ANTLR Grammarsv4 这 TM 什么鬼玩意...
Python 还真是有趣...
duangsuse::Echo
#recommended #PL #tech #dev #Android #GitHub #share #backend #Python #Java #Kotlin 随便推荐一些东西 — Android 库/应用 — https://github.com/alexstyl/RadiusTransition https://github.com/oasisfeng/island — Python — https://github.com/trekhleb/learn-python https://gi…
总的来说,我觉得大家的技术都很不错,都有被尊重的必要。
不管是怎么样,只要做得出来,就理所应当的应该有回报。
duangsuse::Echo
#PL https://github.com/qnnnnez/rs 曾经在百度贴吧看到的邮电二进制序列化大佬... 现在居然也写 Sexp 语言解释器了... 二进制处理的算法我之前也写过,没有这位的那么高级那么实用,是解包一游戏的数据的。 而且也不如这个 C++ 的... 跨平台、内建序列化框架、C++ template 使用、各种图像纹理和波形、字体字形 glyph 解包打包什么的... 不过,我看(Sexp 解析器)的时候居然估计错了一个,真是该打... 太菜了... https://g…
当然,Haskell 里这类解释器实现是很常见了,包括 Haskell 标准库还有专门的解析组合子
有没有人投个自己写的过来(

要求可以使用 + 这个 closure 和 print 这个 closure,只要支持这些都行,闭包创建都不用支持
直接从标准输入获得代码,一旦(语法上)成功 match 就即时执行打印结果

示例程序:

(print (+ 1 1))
(+ (+ (+ 6 9) 3) 1)
https://docs.rs/rusttype/0.7.3/rusttype/#glyphs

然后我准备弄个命令行程序使用 GD2 和 Freetype 渲染字符串到 png 图片的
duangsuse::Echo
https://docs.rs/rusttype/0.7.3/rusttype/#glyphs 然后我准备弄个命令行程序使用 GD2 和 Freetype 渲染字符串到 png 图片的
考虑到如果用 C 写可能阻塞到明天 3 点多(绝望)导致我一直睡不了觉
我决定做一个痛苦的决定:用 Python 写,PIL、Freetype-py

... 反正和图像处理、以及各种和现实世界有交集的代码都特别难写... 唉

https://pillow.readthedocs.io/en/5.3.x/reference/Image.html
https://freetype-py.readthedocs.io/en/latest/
txt2png.py
2 KB
第一个能用的版本
duangsuse::Echo
txt2png.py
This media is not supported in your browser
VIEW IN TELEGRAM
总算可以睡觉喽...
txt2png_bit_unfinished_fin.py
1.5 KB
一点没有完成的成品,对于 FreeType 的 Bitmap 稍微理解了一点,但还不能自己完成 draw_bitmap 函数。折行算法比较搞笑,只有一行 hhhh #Python #learn #backend #Haha #Freetype #CG