/*
・参照透過性は考慮していない
・型のパラメータ化?には挑戦してない
・パターンマッチ再現?にも挑戦してない
・クロージャが欲しいところには呼び出し元の文脈を手渡して誤魔化す
・グローバル変数一個使ってノードの再利用を試みてる
・とにかくlist_qsort内部がそれっぽい感じの手順になってたらヨシ
*/
#include <stdlib.h>
#include <stdio.h>
struct node {
int value;
struct node *next;
};
struct node *list_pop(struct node *list, struct node **p) {
return (*p = list) ? list->next : list;
}
struct node *list_push(struct node *list, struct node *p) {
if (!p)
return list;
else {
p->next = list;
return p;
}
}
struct node *list_new() {
return malloc(sizeof (struct node
)); }
void list_each(void (f)(int), const struct node *list) {
for (; list; list = list->next) f(list->value);
}
int list_length(const struct node *list) {
int len = 0;
for (; list; list = list->next) len++;
return len;
}
struct node *available = 0;
struct node *list_available_pop() {
struct node *p = 0;
available = list_pop(available, &p);
return p;
}
void list_available_free() {
struct node *p;
while (p
= list_available_pop
()) free(p
); }
void list_available_push(struct node *p) {
available = list_push(available, p);
}
void list_available_push_all(struct node *list) {
struct node *next = 0;
for (; list; list = next) {
next = list->next;
list_available_push(list);
}
}
int list_available_length() {
return list_length(available);
}
struct node *list_cons(int value, struct node *next) {
struct node *p = list_available_pop();
if (!p) p = list_new();
p->value = value, p->next = next;
return p;
}
struct node *rev(const struct node *list) {
struct node *p = 0;
for (; list; list = list->next) p = list_cons(list->value, p);
return p;
}
struct node *list_append(const struct node *a, const struct node *b) {
struct node *c = 0, *p, *next;
for (p = rev(b); p; p = next) next = p->next, p->next = c, c = p;
for (p = rev(a); p; p = next) next = p->next, p->next = c, c = p;
return c;
}
void list_partition(void *context, int (predicate)(void *, int), const struct node *list, struct node **a, struct node **b) {
struct node *p, *next, **x;
for (*a = 0, *b = 0, p = rev(list); p; p = next)
x = predicate(context, p->value) ? a : b, next = p->next, p->next = *x, *x = p;
}
int less_than_context(void *context, int value) {
return value < *(int *)context;
}
void list_available_push_all4(struct node *a, struct node *b, struct node *c, struct node *d) {
list_available_push_all(a), list_available_push_all(b), list_available_push_all(c), list_available_push_all(d);
}
struct node *list_qsort(const struct node *list) {
int pivot;
struct node *sorted = 0, *tail, *smaller, *rest, *a, *b;
if (list) {
pivot = list->value, tail = list->next;
list_partition(&pivot, less_than_context, tail, &smaller, &rest);
sorted = list_append(a = list_qsort(smaller), b = list_cons(pivot, list_qsort(rest)));
list_available_push_all4(smaller, rest, a, b);
}
return sorted;
}
void print_int
(int x
) {printf("%d", x
);} int main() {
struct node *list = list_cons(4, list_cons(8, list_cons(8, list_cons(3, 0))));
struct node *sorted = list_qsort(list);
list_each
(print_int
, list
);puts(""); list_each
(print_int
, sorted
);puts(""); list_available_push_all(list), list = 0;
list_available_push_all(sorted), sorted = 0;
list_available_free();
return 0;
}
LyoKICDjg7vlj4LnhafpgI/pgY7mgKfjga/ogIPmha7jgZfjgabjgYTjgarjgYQKICDjg7vlnovjga7jg5Hjg6njg6Hjg7zjgr/ljJbvvJ/jgavjga/mjJHmiKbjgZfjgabjgarjgYQKICDjg7vjg5Hjgr/jg7zjg7Pjg57jg4Pjg4Hlho3nj77vvJ/jgavjgoLmjJHmiKbjgZfjgabjgarjgYQKICDjg7vjgq/jg63jg7zjgrjjg6PjgYzmrLLjgZfjgYTjgajjgZPjgo3jgavjga/lkbzjgbPlh7rjgZflhYPjga7mlofohIjjgpLmiYvmuKHjgZfjgaboqqTprZTljJbjgZkKICDjg7vjgrDjg63jg7zjg5Djg6vlpInmlbDkuIDlgIvkvb/jgaPjgabjg47jg7zjg4njga7lho3liKnnlKjjgpLoqabjgb/jgabjgosKICDjg7vjgajjgavjgYvjgY9saXN0X3Fzb3J05YaF6YOo44GM44Gd44KM44Gj44G944GE5oSf44GY44Gu5omL6aCG44Gr44Gq44Gj44Gm44Gf44KJ44Oo44K3CiovCiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CnN0cnVjdCBub2RlIHsKICBpbnQgdmFsdWU7CiAgc3RydWN0IG5vZGUgKm5leHQ7Cn07CnN0cnVjdCBub2RlICpsaXN0X3BvcChzdHJ1Y3Qgbm9kZSAqbGlzdCwgc3RydWN0IG5vZGUgKipwKSB7CiAgcmV0dXJuICgqcCA9IGxpc3QpID8gbGlzdC0+bmV4dCA6IGxpc3Q7Cn0Kc3RydWN0IG5vZGUgKmxpc3RfcHVzaChzdHJ1Y3Qgbm9kZSAqbGlzdCwgc3RydWN0IG5vZGUgKnApIHsKICBpZiAoIXApCiAgICByZXR1cm4gbGlzdDsKICBlbHNlIHsKICAgIHAtPm5leHQgPSBsaXN0OwogICAgcmV0dXJuIHA7CiAgfQp9CnN0cnVjdCBub2RlICpsaXN0X25ldygpIHsKICByZXR1cm4gbWFsbG9jKHNpemVvZiAoc3RydWN0IG5vZGUpKTsKfQp2b2lkIGxpc3RfZWFjaCh2b2lkIChmKShpbnQpLCBjb25zdCBzdHJ1Y3Qgbm9kZSAqbGlzdCkgewogIGZvciAoOyBsaXN0OyBsaXN0ID0gbGlzdC0+bmV4dCkgZihsaXN0LT52YWx1ZSk7Cn0KaW50IGxpc3RfbGVuZ3RoKGNvbnN0IHN0cnVjdCBub2RlICpsaXN0KSB7CiAgaW50IGxlbiA9IDA7CiAgZm9yICg7IGxpc3Q7IGxpc3QgPSBsaXN0LT5uZXh0KSBsZW4rKzsKICByZXR1cm4gbGVuOwp9CgpzdHJ1Y3Qgbm9kZSAqYXZhaWxhYmxlID0gMDsKc3RydWN0IG5vZGUgKmxpc3RfYXZhaWxhYmxlX3BvcCgpIHsKICBzdHJ1Y3Qgbm9kZSAqcCA9IDA7CiAgYXZhaWxhYmxlID0gbGlzdF9wb3AoYXZhaWxhYmxlLCAmcCk7CiAgcmV0dXJuIHA7Cn0Kdm9pZCBsaXN0X2F2YWlsYWJsZV9mcmVlKCkgewogIHN0cnVjdCBub2RlICpwOwogIHdoaWxlIChwID0gbGlzdF9hdmFpbGFibGVfcG9wKCkpIGZyZWUocCk7Cn0Kdm9pZCBsaXN0X2F2YWlsYWJsZV9wdXNoKHN0cnVjdCBub2RlICpwKSB7CiAgYXZhaWxhYmxlID0gbGlzdF9wdXNoKGF2YWlsYWJsZSwgcCk7Cn0Kdm9pZCBsaXN0X2F2YWlsYWJsZV9wdXNoX2FsbChzdHJ1Y3Qgbm9kZSAqbGlzdCkgewogIHN0cnVjdCBub2RlICpuZXh0ID0gMDsKICBmb3IgKDsgbGlzdDsgbGlzdCA9IG5leHQpIHsKICAgIG5leHQgPSBsaXN0LT5uZXh0OwogICAgbGlzdF9hdmFpbGFibGVfcHVzaChsaXN0KTsKICB9Cn0KaW50IGxpc3RfYXZhaWxhYmxlX2xlbmd0aCgpIHsKICByZXR1cm4gbGlzdF9sZW5ndGgoYXZhaWxhYmxlKTsKfQpzdHJ1Y3Qgbm9kZSAqbGlzdF9jb25zKGludCB2YWx1ZSwgc3RydWN0IG5vZGUgKm5leHQpIHsKICBzdHJ1Y3Qgbm9kZSAqcCA9IGxpc3RfYXZhaWxhYmxlX3BvcCgpOwogIGlmICghcCkgcCA9IGxpc3RfbmV3KCk7CiAgcC0+dmFsdWUgPSB2YWx1ZSwgcC0+bmV4dCA9IG5leHQ7CiAgcmV0dXJuIHA7Cn0Kc3RydWN0IG5vZGUgKnJldihjb25zdCBzdHJ1Y3Qgbm9kZSAqbGlzdCkgewogIHN0cnVjdCBub2RlICpwID0gMDsKICBmb3IgKDsgbGlzdDsgbGlzdCA9IGxpc3QtPm5leHQpIHAgPSBsaXN0X2NvbnMobGlzdC0+dmFsdWUsIHApOwogIHJldHVybiBwOwp9CnN0cnVjdCBub2RlICpsaXN0X2FwcGVuZChjb25zdCBzdHJ1Y3Qgbm9kZSAqYSwgY29uc3Qgc3RydWN0IG5vZGUgKmIpIHsKICBzdHJ1Y3Qgbm9kZSAqYyA9IDAsICpwLCAqbmV4dDsKICBmb3IgKHAgPSByZXYoYik7IHA7IHAgPSBuZXh0KSBuZXh0ID0gcC0+bmV4dCwgcC0+bmV4dCA9IGMsIGMgPSBwOwogIGZvciAocCA9IHJldihhKTsgcDsgcCA9IG5leHQpIG5leHQgPSBwLT5uZXh0LCBwLT5uZXh0ID0gYywgYyA9IHA7CiAgcmV0dXJuIGM7Cn0Kdm9pZCBsaXN0X3BhcnRpdGlvbih2b2lkICpjb250ZXh0LCBpbnQgKHByZWRpY2F0ZSkodm9pZCAqLCBpbnQpLCBjb25zdCBzdHJ1Y3Qgbm9kZSAqbGlzdCwgc3RydWN0IG5vZGUgKiphLCBzdHJ1Y3Qgbm9kZSAqKmIpIHsKICBzdHJ1Y3Qgbm9kZSAqcCwgKm5leHQsICoqeDsKICBmb3IgKCphID0gMCwgKmIgPSAwLCBwID0gcmV2KGxpc3QpOyBwOyBwID0gbmV4dCkKICAgIHggPSBwcmVkaWNhdGUoY29udGV4dCwgcC0+dmFsdWUpID8gYSA6IGIsIG5leHQgPSBwLT5uZXh0LCBwLT5uZXh0ID0gKngsICp4ID0gcDsKfQppbnQgbGVzc190aGFuX2NvbnRleHQodm9pZCAqY29udGV4dCwgaW50IHZhbHVlKSB7CiAgcmV0dXJuIHZhbHVlIDwgKihpbnQgKiljb250ZXh0Owp9CnZvaWQgbGlzdF9hdmFpbGFibGVfcHVzaF9hbGw0KHN0cnVjdCBub2RlICphLCBzdHJ1Y3Qgbm9kZSAqYiwgc3RydWN0IG5vZGUgKmMsIHN0cnVjdCBub2RlICpkKSB7CiAgbGlzdF9hdmFpbGFibGVfcHVzaF9hbGwoYSksIGxpc3RfYXZhaWxhYmxlX3B1c2hfYWxsKGIpLCBsaXN0X2F2YWlsYWJsZV9wdXNoX2FsbChjKSwgbGlzdF9hdmFpbGFibGVfcHVzaF9hbGwoZCk7Cn0Kc3RydWN0IG5vZGUgKmxpc3RfcXNvcnQoY29uc3Qgc3RydWN0IG5vZGUgKmxpc3QpIHsKICBpbnQgcGl2b3Q7CiAgc3RydWN0IG5vZGUgKnNvcnRlZCA9IDAsICp0YWlsLCAqc21hbGxlciwgKnJlc3QsICphLCAqYjsKICBpZiAobGlzdCkgewogICAgcGl2b3QgPSBsaXN0LT52YWx1ZSwgdGFpbCA9IGxpc3QtPm5leHQ7CiAgICBsaXN0X3BhcnRpdGlvbigmcGl2b3QsIGxlc3NfdGhhbl9jb250ZXh0LCB0YWlsLCAmc21hbGxlciwgJnJlc3QpOwogICAgc29ydGVkID0gbGlzdF9hcHBlbmQoYSA9IGxpc3RfcXNvcnQoc21hbGxlciksIGIgPSBsaXN0X2NvbnMocGl2b3QsIGxpc3RfcXNvcnQocmVzdCkpKTsKICAgIGxpc3RfYXZhaWxhYmxlX3B1c2hfYWxsNChzbWFsbGVyLCByZXN0LCBhLCBiKTsKICB9CiAgcmV0dXJuIHNvcnRlZDsKfQp2b2lkIHByaW50X2ludChpbnQgeCkge3ByaW50ZigiJWQiLCB4KTt9CmludCBtYWluKCkgewogIHN0cnVjdCBub2RlICpsaXN0ID0gbGlzdF9jb25zKDQsIGxpc3RfY29ucyg4LCBsaXN0X2NvbnMoOCwgbGlzdF9jb25zKDMsIDApKSkpOwogIHN0cnVjdCBub2RlICpzb3J0ZWQgPSBsaXN0X3Fzb3J0KGxpc3QpOwogIGxpc3RfZWFjaChwcmludF9pbnQsIGxpc3QpO3B1dHMoIiIpOwogIGxpc3RfZWFjaChwcmludF9pbnQsIHNvcnRlZCk7cHV0cygiIik7CiAgbGlzdF9hdmFpbGFibGVfcHVzaF9hbGwobGlzdCksIGxpc3QgPSAwOwogIGxpc3RfYXZhaWxhYmxlX3B1c2hfYWxsKHNvcnRlZCksIHNvcnRlZCA9IDA7CiAgbGlzdF9hdmFpbGFibGVfZnJlZSgpOwogIHJldHVybiAwOwp9Cg==