Forwarded from dnaugsuz
如果一个算法很复杂,加注释也没用。
在确保已经使用了尽可能易于理解的命名方式、尽可能自然的表达风格后,还需要外部文档。
真像JDK一样,对类似 LinkedList, TreeSet 这样弄大片的『文档』嵌在代码里事无巨细都详细得跟蔡徐鲲打篮球没什么两样,我不觉得有什么好看的,尽管JDK是为了javadoc网页方便。
在确保已经使用了尽可能易于理解的命名方式、尽可能自然的表达风格后,还需要外部文档。
真像JDK一样,对类似 LinkedList, TreeSet 这样弄大片的『文档』嵌在代码里事无巨细都详细得跟蔡徐鲲打篮球没什么两样,我不觉得有什么好看的,尽管JDK是为了javadoc网页方便。
// 但是我没用 stl 的 map<k,v>
template<typename T>
class UnionFind {
private:
T* up; unsigned* size;
T* findFamily(T self)
{ while (up[self] != self) self = up[self]; return self; }
public:
UnionFind(size_t n): up(new T[n]), size(new unsigned[n]) {
for (int i=0; i<n; i++) { up[i]=i; size[i]=0; }
}
boolean connects(T a, T b) { return findFamily(a) == findFamily(b); }
void unite(T a, T b) {
auto pa = findFamily(a), pb = findFamily(b);
if (pa == pb) return;
if (size[pa] < size[pb]) up[pa] = pb, size[pb] += size[pa];
else up[pb] = pa, size[pa] += size[pb];
}
} 带权重的合并树查找(相等关系传递)
#include <bits/stdc++.h>修复版本
template<typename T>
class UnionFind {
private:
T* up; unsigned* size;
size_t family(T self)
{ while (up[self] != self) self = up[self]; return self; }
public:
UnionFind(size_t n): up(new T[n]), size(new unsigned[n]) {
for (int i=0; i<n; i++) { up[i]=i; size[i]=1; }
}
bool connects(T a, T b) { return family(a) == family(b); }
void connect(T a, T b) {
auto pa = family(a), pb = family(b);
if (pa == pb) return;
if (size[pa] < size[pb])
up[pa] = pb, size[pb] += size[pa];
else up[pb] = pa, size[pa] += size[pb];
}
};
using namespace std;
const size_t N = 1000;
int main() { int a, b;
UnionFind<int> uf(N);
while (cin >> a >> b) {
if (uf.connects(a, b)) continue;
uf.connect(a, b); cout <<a<<" "<<b<<endl;
}
}
#include <map>当然也可以用 std::map,不过要实现的话必须定义一个 map 子类型……
#include <cstddef>
template<typename T>
class UnionFind {
private:
template<typename A>
using M = std::map<T, A>;
M<T> up; M<unsigned> size;
T *family(T self) {
while (up[self] != self) self = up[self];
return &up[self];
}
~UnionFind() { delete up, size; }
public:
explicit UnionFind(size_t n): up(), size() {
for (int i=0; i<n; i++) up[i]=i, size[i]=1;
}
bool connects(T a, T b) { return family(a) == family(b); }
void connect(T a, T b) {
auto fa = family(a), fb = family(b);
if (fa == fb) return;
auto pa = *fa, pb = *fb;
if (size[pa] < size[pb])
up[pa] = pb, size[pb] += size[pa];
else up[pb] = pa, size[pa] += size[pb];
}
};
#include <iostream>
using namespace std;
const size_t N = 1000;
int main() { int a, b;
auto uf = new UnionFind<int>(N);
while (cin >> a >> b) {
if (uf->connects(a, b)) continue;
uf->connect(a, b); cout <<a<<" "<<b<<endl;
}
}
总是觉得合并查找不如快速查找优雅,快速 a(up[b]) b(up[c]) c(up[d]) 传递一下就解决了、合并总感觉好像数据结构有点多一样,不好想……
我在想,其实
我在想,其实
up 不用 M<T> (non-null)的话,也可以直接上 nullptr, 不就可以在不用子类型判断 contains 的情况下知道一个子树是否为 root 了?
duangsuse::Echo
总是觉得合并查找不如快速查找优雅,快速 a(up[b]) b(up[c]) c(up[d]) 传递一下就解决了、合并总感觉好像数据结构有点多一样,不好想…… 我在想,其实 up 不用 M<T> (non-null)的话,也可以直接上 nullptr, 不就可以在不用子类型判断 contains 的情况下知道一个子树是否为 root 了?
要应用这个修改非常简单:
辣鸡C++好像不能用function extendsion?
T *family(T self) {
while (up[self] != nullptr) self = up[self];
return &up[self];
}
explicit UnionFind(size_t n): up(), size() {}
//...
if (size.get_or_init(pa, 1) < size.get_or_init(pb, 1))
up[pa] = pb, size[pb] += size[pa];
else up[pb] = pa, size[pa] += size[pb]; 辣鸡C++好像不能用function extendsion?
Haskell 版本的用 Data.Vector 写,可以用 Unboxed 优化(Int 等基本类型)
当然 OI 的话必须 Unboxed.Mutable,传来传去(到处复制) TLE 的
GHC 也得开O2(星野说是「吸氧」)
当然 OI 的话必须 Unboxed.Mutable,传来传去(到处复制) TLE 的
GHC 也得开O2(星野说是「吸氧」)
接下来的计划是:
+ 利用现在的 ParserKt 写出 JSON 和 Kotlin 解析器
+ 讲一下 Infix 解析优化、OverlapRangeMap
+ 编写基本的 Montage Python 程序,生成一些彩色艺术画
+ 写 Binarie 框架
+ 彻底重写 ParserKt
+ 利用现在的 ParserKt 写出 JSON 和 Kotlin 解析器
+ 讲一下 Infix 解析优化、OverlapRangeMap
+ 编写基本的 Montage Python 程序,生成一些彩色艺术画
+ 写 Binarie 框架
+ 彻底重写 ParserKt
duangsuse::Echo
ParserKt 对曾经设计上一个不方便的地方为了想当然的「优雅」少定义了一个接口,结果害得成这样…… Fold 数据结构都有误
我错了!我的定义完全写错了……
可怜的 IDEA,它还帮我指出了 position 分明是一个被该对象 this 引用的 upvalue
它的生命周期已经完全超出应该的每parse一个,导致了这次我浪费大量时间来分析,为什么会出现基于『调用顺序』发生的bug!
可怜的 IDEA,它还帮我指出了 position 分明是一个被该对象 this 引用的 upvalue
它的生命周期已经完全超出应该的每parse一个,导致了这次我浪费大量时间来分析,为什么会出现基于『调用顺序』发生的bug!
这个 Fold 根本不该被定义为 Effect Fold,它应该是普通 Fold 的……
下次不应该胡乱设计,或者过分执着于某些「优雅性」,如果要那种优雅为什么不用继承子类,或者干脆不要写Kotlin了,换成Haskell呢?
我开始觉得保存流位置这件事应该是由 items("abc") 这样的解析器,而不是 seq, or 什么的解析器完成了
duangsuse::Echo
我开始觉得保存流位置这件事应该是由 items("abc") 这样的解析器,而不是 seq, or 什么的解析器完成了
finally,在我死肝debug两个小时后,一吃完饭我才最后成功弄 pass 了 tests
只是加了一个 AtomParser 的 mark/reset 调用而已,居然……
我一点都想不明白,为什么seq里的tryRead(也用了MarkReset)不行,单独MarkReset可以?是不是还有bug?
只是加了一个 AtomParser 的 mark/reset 调用而已,居然……
我一点都想不明白,为什么seq里的tryRead(也用了MarkReset)不行,单独MarkReset可以?是不是还有bug?
Null 『传递』就导致 MarkReset as? 的结果和你后来 let, run 里面逻辑的 null 可能性混淆了,这是一个不常见的坑…… #Kotlin
Forwarded from dnaugsuz
动不动就是 null,Kotlin 的编译器检查不出来,它不知道有些东西(比如lazy、inline getter 的)的一些数据还没初始化
我改了很多次,基本都是:
+ map 要用到的 val element 没实际上拿到 val scalar 的值
+ scalar 是空的
+ init {} 陷入无尽递归……
hhhhh,后来我想了半天只得写了个
有没有大佬知道,是不是怎么安排可以避免使用架构器外的
我改了很多次,基本都是:
+ map 要用到的 val element 没实际上拿到 val scalar 的值
+ scalar 是空的
+ init {} 陷入无尽递归……
hhhhh,后来我想了半天只得写了个
deferred Parser,因为构造的时候没法直接拿到循环的指针嘛…… 为了保证不空只能等实际用的时候才能断言需求已经架构好有没有大佬知道,是不是怎么安排可以避免使用架构器外的
deferred(只是好奇)