duangsues.is_a? SaltedFish
60 subscribers
609 photos
6 videos
91 files
562 links
🌶🐔🐟 duangsuse 的日常
尤其喜欢发些奇奇怪怪的东西
和转载别人的东西
Download Telegram
Forwarded from 螺莉莉的黑板报
浏览器内部流式 parse ogg 文件的 code 已经准备好了!
比如像 ogg 一直到 boe 都是媒体数据,元数据在前两个 page 就已经全都写完了
Forwarded from 螺莉莉的黑板报
来来来,开始撕包
Forwarded from 螺莉莉的黑板报
奇怪,ffmpeg 转出来了一个错误的 opus package,这个 package 本身是不符合这条 spec 的:
https://datatracker.ietf.org/doc/html/rfc6716#ref-R5

这我得怎么 fallback……
Forwarded from dnaugsuz
#js #code
let
bsCaf=(oggOpus.toCaf(oggOpu.fetch(target)),
caf=toBlobBuf(await allItems(bsCaf))


// [].let{ xz.each{push(it)} }
allItems=xz=>{let a=[], x
for await(x of xz)a.push(x)
return a
}
// new Blob(bs).arrayBuffer()
toBlobBuf=bs=>{let
size=bs.reduce((A,B)=>A+B.byteLength, 0),
buf=new Uint8Array(size), i=0
bs.forEach(b=>{buf.set(b, i); i+= b.byteLength})
return buf
}
Forwarded from 螺莉莉的黑板报
OK,只有这三处是不一样的,胜利在望了 QwQ|||
Forwarded from 螺莉莉的黑板报
今天下午做完的事情是:
1. 清理掉 legacy 的数据加载机制,他那玩意是基于事件的(跟 IDB 一个尿性),这种写法会把数据流的控制搞得很乱,给重构成 Async Generator 了,这部分测试下来都没问题;
2. 清理掉他自己写的 EventTarget,他自己写了个 EventTarget 的 Polyfill,而且还是残的,甚至还复制粘贴了两次,换成了 Web Media 下面标准的 Event Target 了;
3. 重写数据分片加载的机制,之前已经把 MP3 的加载给抽出来了,这次进一步把它整理了一下,没整理完,删东西删的太狠了,编码解码出 bug 了(
Forwarded from 螺莉莉的黑板报
啊,丢了一步,我说怎么不对,消到正常范围内了,还剩一个 bug,明天把它修掉!
Forwarded from 螺莉莉的黑板报
这东西的做法其实真的非常简单,librespot 已经把所有 Code 都写完了,只需要在播放那块加一个函数,把 Key Dump 出来,然后用 deno 写一个小脚本从缓存池里面把加密的 ogg 捞出来用 AES 解开就行了,元信息可以用 spotifly 那个库直接从它的官方数据库提取。碎掉的 Container 用 VLC 修一下,元信息用 tageditor-cli 填进去就好了 ˊ_>ˋ
Forwarded from 螺莉莉的黑板报
ˊ_>ˋ 水多了加面面多了加水:
1. ffmpeg 不认 spotify 裁过的 ogg 容器,用 VLC 转;
2. VLC 转完的文件没有 metadata,用 kid3 克隆元信息;
3. VLC 把媒体文件长度整没了,用 ffmpeg 补一遍……
#py
def match_parentheses(s):
# 创建一个栈来存储左括号
stack = []
# 创建一个字典来存储左右括号的对应关系
pairs = {"(": ")", "[": "]", "{": "}"}
# 遍历字符串中的每个字符
for c in s:
# 如果是左括号,就把它压入栈中
if c in pairs:
stack.append(c)
# 如果是右括号,就检查栈是否为空,以及栈顶的左括号是否与它匹配
elif c in pairs.values():
if not stack or pairs[stack.pop()] != c:
# 如果不匹配,就返回False
return False
# 最后检查栈是否为空,如果为空,说明所有的括号都匹配了
return not stack



# 匹配左右括号
pairs = {'(':')', '[':']', '{':'}'}
def eat(s,c0):
for c in s:
# 如果是左括号,就把它压入栈中
if c in pairs: eat(s,pairs[c])
elif c==c0:return # 如果是右括号,左括号便与之匹配
else: assert'','多余项而栈空'
assert c0=='eof','栈尚不为空'

def catchy(f,*a):
try:return f(*a)
except Exception as e:return e

[catchy(eat,iter(s),'eof')\
for s in "([]) ()[]{} ({[()]}) ( []]".split() ]


#learn
基于栈的算法不全都可以转化为基于递归。有些问题本身就不具有分治和回溯的特性,只会空间复杂度。
后缀表达式求值,不适合用递归来实现,因为它没有主动的终止条件和子问题划分
汉诺塔问题,不适合用栈来实现,因为它需要记录A->B,而栈只能记录最后一个盘子的位置。

DP算法都能转化为递归,反之亦然
动态规划通常采用自底向上(bottom-up)的方式,从最简单的子问题开始逐步向上组合;如归并排序、DFA,AC树
递归通常采用自顶向下(top-down)的方式,从原问题开始逐步向下分解出更简单的子问题;如快速排序、递归下降流读写

迭代法、递推循环(尾递归)不是自底向上,因为问题范围不会扩大
贪心、模拟法只是解题思想,是因为不熟练而采取的省事做法

DFS 和暴力都能使用逻辑式来实现,即将问题抽象为等式组,然后使用 DFS 来搜索满足'='等调用的变量
Prolog
:- use_module(library(clpfd)).

% 定义搜索:鸡和兔子的总数为 N,总腿数为 M
solve(N, M, A, B) :-
A + B #= N, 2*A+4*B#=M,
[A, B] ins 0..sup. % 区间,如 A+B#=3 , [A,B] ins 0..sup, label([A,B]).

main :- solve(14,38,A,B), format("~w鸡~w兔~n", [A, B]).


%九九
A * B #= C,
[A,B]ins 1..9, label([A,B]),
format('~w*~w=~w ',[A,B,C]), (A=1 -> write('\n');true).

html(table([class([table, 'table-striped'])], [\foreach(between(1,9,A),
html(tr([\foreach((between(1,9,B),C is A*B ,A>=B), html(td([B,*,A,=,C] )) )] )) )
]))

https://leetcode.cn/problems/two-sum/
two_sum(Nums,X, I, J) :-
nth0(I, Nums, A), nth0(J, Nums, B), I \= J,
% A+B=X
A is X - B.

/** <examples>
?- two_sum([2, 7, 11, 15], 9, I, J).
?- two_sum([3,2,4], 6, I, J).
*/
#zhihu 编程的范式

- “初学·面向运气编程”。编程是用英文理解,体验几行代码触发的效果,靠dnSpy修改既有程序的反编译
或创,建样板项目,排开UI“设置”点击,在CSDN上搜索些即贴即用小功能加进去,反复打包安装、调试print 一周里的机械化过程
甚至是让精灵表演舞台动作:拖拽各种动作方块到某事件下方,延时修改角度和距离

只需要魔改别人的源码片段,搜索CtrlV所缺少的变量和平台;像Copilot一样进步着,甚至不如。但,“学会”写法后,你才会有选择与灵感

- “过程式”以语言提供的基元值、控制结构、数据/集合操作构造需要的程序,产生效果或返回值
函数和流控、structs和弱检查的指针*、运算和IO

- 面向对象。是以发送者给接受者发送参数消息为模式设计,实现程序模块
你学了函数变量循环判断,甚至类结构,但没什么用
删掉 this.mXX 的m不行,不用 System.out.print/sleep 就做不到,alert()的同类不去查; for(:)add觉得自己牛了,需try{http.get}编译失败觉得头疼
因为,你不知道“调用栈”会卡死线程、读“文件”需要open和decode ,就只是想做脚本或UI,偶尔对新奇语法照猫画虎

- “老程序员”是用所选语言的语法/数据结构 +目标平台API,顺常规的业务流程,组织能解决问题的程序
阮和张鑫旭这些人都是非常有见识和个性的JSer
从领域动名词集和实际API起手,创建复用函数,编写单线程命令工具或应用,考虑数据(库)形式的统一、生命周期和交互事件、外部组件和算法、内存CPU瓶颈和开销

- “定义式”是用与数据明显相呼应的程序,描述问题之间的关系,并处理转化从API拿到的数据
编写能读改类型成员的代码,从而减少样板代码
用函数的组合树定义对流、对结构体的操作DSL
人的智慧很有限,一定要100%耗在核心逻辑上。难以验证的成本,会麻烦你的下游
片段(函数)有没有主语, 作为变量有多强类型、XML TOML YAML、数学的几何的向量一次算一组的,可视化的Scratch,还有描述软件分类和特色的小作文;都是抽象程度不同的代码

- “设计·程序”是让人与算力、领域与领域融恰,以使有物理类型的信息肆意碰撞,解决眼下和未知、用户和同行、语法和蕴意的问题
对功能点-片段有先验。不为了酷一股脑地换风格,亦不束缚于专业
没有一张频谱图,会显示每堆def贡献了多少功能,没有一种排序法,会关心几句解释带来多少顿悟

有比这些都重要的:对技术和API的“选择力”。灵感、联想和避坑的能力,大智若愚、求知若饥,才是真正的编程范式

技术,只是“设计”的通识和副产物。让电脑更丰富的并不是“懂”,而是代码里没有人名却层次分明的思想
Forwarded from dnaugsuz
#bing

#48 在GL里直接用Vec2极座标? 原来是np.rot+90(T矩阵).. 这不叫数学吧
matrix[:] = zip(*matrix[::-1])
#
a.reverse()
for i in range(len(a)): #行列调换,j是对角线
for j in range(i):a[i][j], a[j][i] = a[j][i], a[i][j]

#54 定义式解法
[[0 1 2]
[7 8 3]
[6 5 4]]
#range(0,9) => spiral(cols=3)
def unrot(a, out):
while a.size: out.extend(a[0]); a=np.rot90(a[1:])

def rot(a, m):
ia=np.reshape(range(len(a)), (m,-1))
unrot(ia, ord:=[])
return np.vectorize(lambda i:a[ord.index(i)] )(ia)


a=rot([*range(0,9)], 3)
unrot(a, na:=[])
[a,na]

>请把它从np.array 移植到 [[]] 类型

def unrot(a, out):
while a:
out.extend(a[0]); a=list(zip(*a[1:]))[::-1] #T矩阵=逐列逆序

def rot(a, m):
ia=[list(range(i*m, (i+1)*m)) for i in range(m)]
unrot(ia, ord:=[]) #格子ID的序号
return [[a[ord.index(i)] for i in row] for row in ia]


#73
- Nd<Int> setZeros
at shape==[n m]
at now Bool: i0 j0 // 清零首行(记号行)

(0~<n):[i] (0~<m):[j] if this[i,j]==0:
i0=i0 or i==0; j0=j0 or j==0
this[i,0]=0
this[0,j]=0 //稍后清零此行列

(1~<n):[i] (1~<m):[j]
if this[i,0]==0 or this[0,j]==0: this[i,j]=0

if j0:(0~<n):[i] this[i,0]=0
if i0:(0~<m):[j] this[0,j]=0

#240 从下到右能找到最大值,所以自右上
- Nd bsearch(it:N) Bool
if size==0: return $N
at shape==[n m]
at now:
i 0; j m-1 //TR corner
loop if i<n & j!<0:
when this[i,j].sorts(it):
Eq:return $Y
MaxAt0: j goesL
MinAt0: i goesR //go down
return $N
Forwarded from dnaugsuz
感觉都是很 practical 的算法,所以用自己的思路来做会很..

48矩阵转置这种也太.. 反正螺旋矩阵用模拟法真的很蠢,就是大while(n*m步) {朝右下左上走; 跳到 (1,1), 边界-(1,1) ,...}
定义式10行除了遍历,连生成都写完了(btw. rot 应该把spiralFn作为参数,毕竟有其他方法也算"迷宫排序")

(原来真有人mat.T都模拟 , i=j行列对调+reverse的事)
写2048时也用过模拟法,不过我是把 2048 的扫描合并对接到遍历, 然后用矩阵+四向实现它(还不如直接旋转矩阵)想必用螺旋模拟贪吃蛇也很好玩吧(网格碰撞

240和之前”螺旋“数组(拆二,找有序半)深遍历 很像,完全分治比预处理好

这种 old-school 的算法,如果没能列出易读的公式,感觉即便AC了也是收获不大..
我更喜欢#73 这种,虽然莫名觉得有更简洁的写法
Forwarded from dnaugsuz
#code AIDL 服务-客户 示例,包含 int n 的监听、 List<Str> users() 的回调

// src/main/aidl/ISvc.aidl
package my.svc;
import my.svc.ISvcCB;

interface ISvc {
void setListener(in ISvcCB callback);//int n 变化时通知客户端
//没有找到针对 Kotlin 的 AIDL 框架,但创建.aidl时, xml清单会自动更新
int getN();void setN(int n);
void getUsers(in ISvcCB callback);// 回调得 List<Str>
}

// 另起一文
package my.svc;
import java.util.List;

interface ISvcCB {
void onNChanged(int n);
void onGetUsers(List<Str> users);
}

// src/main/kotlin/ISvc.kt
class ISvc: Service() {
var n=0
onBind(intent)=binder
val binder=object: ISvc.Stub() {
getN()=n //set,users 要调回调,以此类推
}
}

// MyActivity.java

class MyActivity : RpcActivity() {
onCreate()=makeRpc<ISvc>()
inline fun <reified T> makeRpc() {//连接(intent,conn)
val conn=object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, binder: IBinder?)
{rpc = T.Stub.asInterface(binder)}
override fun onServiceDisconnected(name: ComponentName?) {rpc=null}
}
bindService(Intent.at(T::class.java), conn, BIND_AUTO_CREATE)
close={unbindService(conn)}
}
onDestroy()=_close()
var close:()->Unit
}
fun Intent.Companion.at(T:Class<*>) = Intent().apply {
component = ComponentName(T.`package`.name, T.name)
}
duangsues.is_a? SaltedFish
#py def match_parentheses(s): # 创建一个栈来存储左括号 stack = [] # 创建一个字典来存储左右括号的对应关系 pairs = {"(": ")", "[": "]", "{": "}"} # 遍历字符串中的每个字符 for c in s: # 如果是左括号,就把它压入栈中 if c in pairs: stack.append(c) # 如果是右括号,就检查栈是否为空,以及栈顶的左括号是否与它匹配 …
#sql #code LC#200
:- use_rendering(table).
pixel([
[0, 0, 1],
[1, 1, 1],
[0, 0, 0]]).

% 像素[xy]
v(P, C) :- P = [X,Y],
pixel(M),
nth0(Y, M, R),nth0(X, R, C).

% 相邻颜色
conn(P0,P1) :- P0 = [X0,Y0],P1 = [X1,Y1],
v(P0,C),v(P1,C),
abs(X0 - X1) + abs(Y0 - Y1) =:= 1.

% 追溯联通
dfs(A,B,V) :- A=B; conn(A,C), not(member(C,V)), dfs(C,B,[C|V]).

% 列出
fill(P, S) :- setof(X, dfs(P,X, []), S).

/** <examples>
?- fill([2,1], R).
?- distinct([X], (fill(_,X))).
?- v(P, 0), P=[X, 0].
?- conn([2,1], P1).
*/


#py
import numpy as np

def islands(a):
LRUD = np.array([[0, -1], [0, 1], [-1, 0], [1, 0]])
m, n = a.shape
all=set()
f=dfs((isl:=[]).append, lambda P:(tuple(x) for x in P+LRUD if (lambda x,y :\
(0<=y<n)and(0<=x<m) and a[x,y]== 1)(*x)) )

for P,c in np.ndenumerate(a):
f(P); vis.clear(); all.add(tuple(sorted(isl))); isl.clear()
return all
vis=set()
def dfs(fvis,Links):
def at(P0):
for P in Links(P0):
if P not in vis: fvis(P);vis.add(P); at(P)
return at

# 创建一个 'L' 型九宫格的示例
_L = np.array([
[1,0,0],
[1,0,0],
[1,1,0],
])

islands(_L)



LC#994 则是用BFS,浅先,并记录布数; 从所有烂橘子开始,直到走不动或橘子全烂
#plt #code 本来 mul([1,*,2],[], R) 正确算为 乘(1,2)
验算也OK,但反运算不行!

关系式无法调试print,我内联参数勉强查出了“把 R= 往前挪,就能正确推导”

AI直接傻了,说了一些奇怪的话:

“ 这时 mul(S,[], 乘(1, 2)) 能用,但规则的含义变了。你原来说 S 是一个乘法表达式,现在的 mul 里 S 和 R 都是乘法表达式 (废话!)

这样允许了一些不合理的情况,例如 mul([1,*,2],[], 3) 也可以成功(??),因为 R = 3 可以无视S匹配 R =.. [乘,E1,E2] ,这样会破坏你的逻辑。你应该定义 mul(S,[],R)

:- use_module(library(dcg/basics)).
:- set_prolog_flag(double_quotes, chars).

e(E) -->{E = [I,Ea,Eb]},
e1(Ea), op(I,"+-"), e(Eb); e1(E).
e1(E) -->{E = [I,Ea,Eb]},
e2(Ea), op(I," */"), e1(Eb); e2(E).

e2(X) --> number(X); ("(", e(X), ")"), !.
op(I,W) --> [C], { nth0(I0,W,C),nth0(I0,"加减乘除",I) }.

%原理: 吃前缀,吃内项,吐返回
parse(S,E) :- add(S,[],E), !.
kw(W,S,SR) :- S = [W|SR].
num(S,SR,R) :-
S = [R|SR], integer(R); phrase(number(R), S,SR).

add(S,SR,R) :- R =.. [加,E1,E2],
mul(S,S1,E1),kw('+',S1,S2),add(S2,SR,E2); mul(S,SR,R). %chainl. 这些S只是“流后缀”

mul(S,SR,R) :-
R =.. [乘,E1,E2], %FUCK, 想反算R必须在前,num必须在后?
num(S,S1,E1), kw('*',S1,S2), num(S2,SR,E2); num(S,SR,R).

%split_string \d+
% cutD("123acbc12", [123, a, c, b, c,1,2]) 失败了
cutD(S, L) :-
phrase(number(N), S,SR), cutD(SR,L0),L=[N|L0], !; S=L, !;
phrase(string(X), S,SR), cutD(SR,L0),L=[X|L0].
Forwarded from Deleted Account
在 Rust 中,你可以结合 HTML-style UI 框架和 imgui 绑定来实现 label("你好") 的效果。下面是一个简单的例子,使用 web-viewimgui-rs 来实现:

首先,在 Cargo.toml 文件中添加相关依赖:

[dependencies]
web-view = "0.7.0"
imgui = "0.4.0"
imgui-winit-support = "0.6.0"


接下来,创建一个名为 main.rs 的文件,并将以下代码添加到文件中:

use web_view::*;
use imgui::*;
use imgui_winit_support::WinitPlatform;

fn main() {
// 创建 web view,指定 HTML 内容和窗口大小
let webview = web_view::builder()
.title("Hello Label Example")
.content(Content::Html(include_str!("index.html")))
.size(800, 600)
.resizable(true)
.debug(true)
.user_data(())
.invoke_handler(|_webview, _arg| {
Ok(())
})
.build()
.unwrap();

// 创建 imgui 上下文
let mut imgui = imgui::Context::create();
imgui.set_ini_filename(None);

// 创建 imgui-winit-support 并初始化
let mut platform = WinitPlatform::init(&mut imgui);
platform.attach_window(
imgui.io_mut(),
platform
.create_window(
imgui.io_mut(),
Default::default(),
imgui_winit_support::HiDpiMode::Default,
)
.0,
imgui_winit_support::HiDpiMode::Default,
);

// 主循环
while webview.step().unwrap() {
let ui = imgui.frame();

// 在 imgui 中创建一个 Label 控件
ui.text("你好");

// imgui 渲染
let mut platform_state = platform.prepare_frame(imgui.io_mut(), &webview.window());
platform_state.prepare_render(&ui, &webview.window());
webview.eval(&platform_state.render()).unwrap();
}
}


接下来,创建一个名为 index.html 的文件,并将以下代码添加到文件中:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Label Example</title>
</head>
<body>
</body>
</html>


最后,使用 cargo run 命令来运行程序。

这个示例会创建一个带有 "你好" 标签的 HTML-style UI 窗口。你可以根据需要进一步扩展和定制该示例。

请确保 Cargo.toml 中的依赖项与代码示例中提供的版本号匹配,以确保能够成功构建和运行该程序。同时,你可能还需要根据自己的操作系统和开发环境进行必要的配置和调整。

希望这能帮助到你!如果有任何进一步的问题,请随时提问。🙂