多段階選抜 (Zig/Zen)


|多段階選抜|解答日|シリーズ:yieldの練習/ジェネレータを入れ子に/整数平方根・立方根の実装|
|:--|:--|:--|
|問題|　|http://nabetani.sakura.ne.jp/hena/ord24eliseq/<br>https://qiita.com/Nabetani/items/1c83005a854d2c6cbb69|
|Ruby|2014/8/2(当日)|https://qiita.com/cielavenir/items/9f15e29b73ecf98968a5|
|C#/Python|2014/8/4|https://qiita.com/cielavenir/items/a1156e6a4f71ddbe5dcb|
| |　|ここから上はdrop_prev_square/drop_prev_cubicをまとめる前の答案|
|Go/C#/Ruby/Python|2014/8/5|https://qiita.com/cielavenir/items/2a685d3080862f2c2c47|
|PHP/JavaScript|2014/9/9|https://qiita.com/cielavenir/items/28d613ac3823afbf8407|
|VB|2014/9/10|https://qiita.com/cielavenir/items/cb7266abd30eadd71c04|
|D|2015/12/21|https://qiita.com/cielavenir/items/47c9e50ee60bef2847ec|
|Perl|2017/3/10|https://qiita.com/cielavenir/items/6dfbff749d833c0fd423|
|Lua|2017/3/13|https://qiita.com/cielavenir/items/c60fe7e8da73487ba062|
|C++20(TS)|2017/3/15|https://qiita.com/cielavenir/items/e1129ca185008f49cbab (MSVC)<br>https://qiita.com/cielavenir/items/1cfa90d73d11bb7dc3d4 (clang)|
|F#|2017/3/17|https://qiita.com/cielavenir/items/a698d6a26824ff53de81|
|Boo/Nemerle|2017/5/13|https://qiita.com/cielavenir/items/e2a783f0fe4b0fe0ed48|
|Perl6|2017/5/15|https://qiita.com/cielavenir/items/656ea17fa96c865c4498|
|Kotlin|2017/5/25|https://qiita.com/cielavenir/items/9c46ce8d9d12e51de285|
|Crystal|2018/5/8|https://qiita.com/cielavenir/items/1815bfa6a860fd1f90db|
|MoonScript|2018/6/16|https://qiita.com/cielavenir/items/8b03cce0386f4537b5ad|
|Julia/Rust|2018/12/20|https://qiita.com/cielavenir/items/3ddf72b06d625da0c4a5|
|Nim|2018/12/26|https://qiita.com/cielavenir/items/5728944867e609fd52a7|
|Tcl|2018/12/31|https://qiita.com/cielavenir/items/76cbd9c2022b48c9a2c9|
|Pascal/Cobra|2019/1/16|https://qiita.com/cielavenir/items/81b81baf8dfc1f877903|
|Icon|2019/1/17|https://qiita.com/cielavenir/items/889622dcc721f5a4da24|
|Swift|2020/5/31|https://qiita.com/cielavenir/items/3b0b84a218e35d538f7f|
|Java/Groovy/Scala|2020/5/31|https://qiita.com/cielavenir/items/7f058203a8fd03b65870|
|V|2020/10/17|https://qiita.com/cielavenir/items/df30a6c101a97a713df5|
|Zig/Zen|2020/10/17|https://qiita.com/cielavenir/items/9cced9e4a94dcd70df0f|
|Pike|2020/11/2|https://qiita.com/cielavenir/items/3a8248f41611302b34fd|
|Vala/Smalltalk|2020/11/29|https://qiita.com/cielavenir/items/085dabe593cd916af5e8|
|Objective-C|2020/11/30|https://qiita.com/cielavenir/items/a1736e38789a3dd5cc5a|
|Ruby(Ractor)|2021/1/2|https://qiita.com/cielavenir/items/f493c6d512b63cc571cc|
|Python(_xxsubinterpreters)|2021/6/29|https://qiita.com/cielavenir/items/f1f581a055db918954f1|
|Falcon/Scheme|2021/9/5|https://qiita.com/cielavenir/items/c13d12cf44f0d17f4a94|
|Clojure/Lisp|2021/9/7|https://qiita.com/cielavenir/items/7458ba076f4e5bc0f196|
|(icbrtの実装に関する)補題|2017/5/11|整数除算であってもn/(x*y)はn/x/yに等しい(ことの証明)<br>https://qiita.com/cielavenir/items/21a6711afd6be8c18c55|

ドキュメントが少なく、極めてわかりにくいのですが…
https://github.com/ziglang/zig/issues/5611#issuecomment-644851433 のコメントをなんとか解読することができました。

https://jp.quora.com/これから間違いなく需要があるプログラミング言語/answers/142473162 で触れられている4言語を全て抑えることができました！

しかし、重大な問題として、async frameが行番号か何かで管理されているのか、 **同じ文字を複数回与えると"resumed a non-suspended function"が発生します。**
今回はやむを得ず、文字が与えられるたびに行番号を変えてframelstに入れるようにしています。
そのため、この答案では5回までしか同じ文字を入れられません。yhpgでは全テストケースが始めから可視なので良いですが、そうでなければ厳しいですね。。

ただ、まあ、`anyframe->void`を関数の引数にすることは標準的な解法でないと思われるので、言語自体の進化に期待ということでしょうか…。

いや、それよりも、 **関数ポインタに対しasyncできない** ほうがもっと問題か…

```zig
//usr/bin/env zig run "$0" "$@";exit
const std = @import("std");

fn isqrt(n:i64)i64{
    if(n<=0){return 0;}
    if(n<4){return 1;}
    var x:i64=0;
    var y:i64=n;
    while(x!=y and x+1!=y){x=y;y=@divFloor(@divFloor(n,y)+y,2);}
    return x;
}
fn icbrt(n:i64)i64{
    if(n<0){return -icbrt(-n);}
    if(n==0){return 0;}
    if(n<8){return 1;}
    var x:i64=0;
    var y:i64=n;
    while(x!=y and x+1!=y){x=y;y=@divFloor(@divFloor(@divFloor(n,y),y)+y*2,3);}
    return x;
}

fn is_sq(n:i64)bool{
    var x=isqrt(n);
    return x*x==n;
}
fn is_cb(n:i64)bool{
    var x=icbrt(n);
    return x*x*x==n;
}
fn is_multiple(i:i64,n:i64)bool{return @mod(i,n)==0;}
fn is_le(i:i64,n:i64)bool{return i<=n;}

fn generate(val:*i64)void{
    val.* = 1;
    while(true){
        suspend;
        val.* += 1;
    }
}

fn drop_prev(val:*i64,check:fn(i64)bool,prevvalue:*i64,prevframe:anyframe->void)void{
    var a = prevvalue.*;
    resume prevframe;
    var b = prevvalue.*;
    while(true){
        if(!check(b)){val.* = a;suspend;}
        a = b;
        resume prevframe;
        b = prevvalue.*;
    }
}

fn drop_next(val:*i64,check:fn(i64)bool,prevvalue:*i64,prevframe:anyframe->void)void{
    var a = prevvalue.*;
    resume prevframe;
    var b = prevvalue.*;
    val.* = a;
    suspend;
    while(true){
        if(!check(a)){val.* = b;suspend;}
        a = b;
        resume prevframe;
        b = prevvalue.*;
    }
}

fn drop_n(val:*i64,check:fn(i64,i64)bool,n:i64,prevvalue:*i64,prevframe:anyframe->void)void{
    var i:i64 = 0;
    while(true){
        i+=1;
        var a:i64 = prevvalue.*;
        if(!check(i,n)){val.* = a;suspend;}
        resume prevframe;
    }
}

pub fn main()!void{
    var stdin_ = std.io.getStdIn().inStream();
    var stdin = std.io.bufferedInStream(stdin_).inStream();
    var stdout_ = std.io.getStdOut().outStream();
    var stdout = std.io.bufferedOutStream(stdout_).outStream();
    var buf: [99]u8 = undefined;

    while(true){
        if(try stdin.readUntilDelimiterOrEof(buf[0..], '\n')) |user_input|{
            var h = std.AutoHashMap(u8,i64).init(std.heap.page_allocator);
            defer h.deinit();
            _ = try h.put('S',0);
            _ = try h.put('s',0);
            _ = try h.put('C',0);
            _ = try h.put('c',0);
            _ = try h.put('h',0);
            _ = try h.put('2',0);
            _ = try h.put('3',0);
            _ = try h.put('4',0);
            _ = try h.put('5',0);
            _ = try h.put('6',0);
            _ = try h.put('7',0);
            _ = try h.put('8',0);
            _ = try h.put('9',0);

            var len = user_input.len;
            var reslst = try std.heap.page_allocator.alloc(i64,len+1);
            defer std.heap.page_allocator.free(reslst);
            var framelst = try std.heap.page_allocator.alloc(anyframe->void,len+1);
            defer std.heap.page_allocator.free(framelst);
            framelst[0] = &(async generate(&reslst[0]));
            var i:usize=0;
            while(i<len){
                // async frameが行番号か何かで管理されているのか、同じ文字を複数回与えると"resumed a non-suspended function"が発生します。
                // やむを得ず、文字が与えられるたびに行番号を変えてframelstに入れるようにしています。本当にひどい。
                if(user_input[i]=='S'){
                    if(h.get('S').? == 0)framelst[i+1] = &(async drop_next(&reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.get('S').? == 1)framelst[i+1] = &(async drop_next(&reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.get('S').? == 2)framelst[i+1] = &(async drop_next(&reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.get('S').? == 3)framelst[i+1] = &(async drop_next(&reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.get('S').? == 4)framelst[i+1] = &(async drop_next(&reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    _ = try h.put('S',h.get('S').?+1);
                }
                if(user_input[i]=='s'){
                    if(h.get('s').? == 0)framelst[i+1] = &(async drop_prev(&reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.get('s').? == 1)framelst[i+1] = &(async drop_prev(&reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.get('s').? == 2)framelst[i+1] = &(async drop_prev(&reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.get('s').? == 3)framelst[i+1] = &(async drop_prev(&reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.get('s').? == 4)framelst[i+1] = &(async drop_prev(&reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    _ = try h.put('s',h.get('s').?+1);
                }
                if(user_input[i]=='C'){
                    if(h.get('C').? == 0)framelst[i+1] = &(async drop_next(&reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.get('C').? == 1)framelst[i+1] = &(async drop_next(&reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.get('C').? == 2)framelst[i+1] = &(async drop_next(&reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.get('C').? == 3)framelst[i+1] = &(async drop_next(&reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.get('C').? == 4)framelst[i+1] = &(async drop_next(&reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    _ = try h.put('C',h.get('C').?+1);
                }
                if(user_input[i]=='c'){
                    if(h.get('c').? == 0)framelst[i+1] = &(async drop_prev(&reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.get('c').? == 1)framelst[i+1] = &(async drop_prev(&reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.get('c').? == 2)framelst[i+1] = &(async drop_prev(&reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.get('c').? == 3)framelst[i+1] = &(async drop_prev(&reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.get('c').? == 4)framelst[i+1] = &(async drop_prev(&reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    _ = try h.put('c',h.get('c').?+1);
                }
                if(user_input[i]=='h'){
                    if(h.get('h').? == 0)framelst[i+1] = &(async drop_n(&reslst[i+1],is_le,100,&reslst[i],framelst[i]));
                    if(h.get('h').? == 1)framelst[i+1] = &(async drop_n(&reslst[i+1],is_le,100,&reslst[i],framelst[i]));
                    if(h.get('h').? == 2)framelst[i+1] = &(async drop_n(&reslst[i+1],is_le,100,&reslst[i],framelst[i]));
                    if(h.get('h').? == 3)framelst[i+1] = &(async drop_n(&reslst[i+1],is_le,100,&reslst[i],framelst[i]));
                    if(h.get('h').? == 4)framelst[i+1] = &(async drop_n(&reslst[i+1],is_le,100,&reslst[i],framelst[i]));
                    _ = try h.put('h',h.get('h').?+1);
                }
                if(user_input[i]=='2'){
                    if(h.get('2').? == 0)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,2,&reslst[i],framelst[i]));
                    if(h.get('2').? == 1)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,2,&reslst[i],framelst[i]));
                    if(h.get('2').? == 2)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,2,&reslst[i],framelst[i]));
                    if(h.get('2').? == 3)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,2,&reslst[i],framelst[i]));
                    if(h.get('2').? == 4)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,2,&reslst[i],framelst[i]));
                    _ = try h.put('2',h.get('2').?+1);
                }
                if(user_input[i]=='3'){
                    if(h.get('3').? == 0)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,3,&reslst[i],framelst[i]));
                    if(h.get('3').? == 1)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,3,&reslst[i],framelst[i]));
                    if(h.get('3').? == 2)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,3,&reslst[i],framelst[i]));
                    if(h.get('3').? == 3)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,3,&reslst[i],framelst[i]));
                    if(h.get('3').? == 4)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,3,&reslst[i],framelst[i]));
                    _ = try h.put('3',h.get('3').?+1);
                }
                if(user_input[i]=='4'){
                    if(h.get('4').? == 0)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,4,&reslst[i],framelst[i]));
                    if(h.get('4').? == 1)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,4,&reslst[i],framelst[i]));
                    if(h.get('4').? == 2)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,4,&reslst[i],framelst[i]));
                    if(h.get('4').? == 3)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,4,&reslst[i],framelst[i]));
                    if(h.get('4').? == 4)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,4,&reslst[i],framelst[i]));
                    _ = try h.put('4',h.get('4').?+1);
                }
                if(user_input[i]=='5'){
                    if(h.get('5').? == 0)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,5,&reslst[i],framelst[i]));
                    if(h.get('5').? == 1)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,5,&reslst[i],framelst[i]));
                    if(h.get('5').? == 2)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,5,&reslst[i],framelst[i]));
                    if(h.get('5').? == 3)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,5,&reslst[i],framelst[i]));
                    if(h.get('5').? == 4)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,5,&reslst[i],framelst[i]));
                    _ = try h.put('5',h.get('5').?+1);
                }
                if(user_input[i]=='6'){
                    if(h.get('6').? == 0)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,6,&reslst[i],framelst[i]));
                    if(h.get('6').? == 1)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,6,&reslst[i],framelst[i]));
                    if(h.get('6').? == 2)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,6,&reslst[i],framelst[i]));
                    if(h.get('6').? == 3)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,6,&reslst[i],framelst[i]));
                    if(h.get('6').? == 4)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,6,&reslst[i],framelst[i]));
                    _ = try h.put('6',h.get('6').?+1);
                }
                if(user_input[i]=='7'){
                    if(h.get('7').? == 0)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,7,&reslst[i],framelst[i]));
                    if(h.get('7').? == 1)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,7,&reslst[i],framelst[i]));
                    if(h.get('7').? == 2)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,7,&reslst[i],framelst[i]));
                    if(h.get('7').? == 3)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,7,&reslst[i],framelst[i]));
                    if(h.get('7').? == 4)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,7,&reslst[i],framelst[i]));
                    _ = try h.put('7',h.get('7').?+1);
                }
                if(user_input[i]=='8'){
                    if(h.get('8').? == 0)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,8,&reslst[i],framelst[i]));
                    if(h.get('8').? == 1)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,8,&reslst[i],framelst[i]));
                    if(h.get('8').? == 2)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,8,&reslst[i],framelst[i]));
                    if(h.get('8').? == 3)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,8,&reslst[i],framelst[i]));
                    if(h.get('8').? == 4)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,8,&reslst[i],framelst[i]));
                    _ = try h.put('8',h.get('8').?+1);
                }
                if(user_input[i]=='9'){
                    if(h.get('9').? == 0)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,9,&reslst[i],framelst[i]));
                    if(h.get('9').? == 1)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,9,&reslst[i],framelst[i]));
                    if(h.get('9').? == 2)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,9,&reslst[i],framelst[i]));
                    if(h.get('9').? == 3)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,9,&reslst[i],framelst[i]));
                    if(h.get('9').? == 4)framelst[i+1] = &(async drop_n(&reslst[i+1],is_multiple,9,&reslst[i],framelst[i]));
                    _ = try h.put('9',h.get('9').?+1);
                }
                i+=1;
            }
            i = 0;
            while(i<10){
                if(i>0)try stdout.print(",",.{});
                try stdout.print("{}",.{reslst[len]});
                resume framelst[len];
                i+=1;
            }
            try stdout.print("\n",.{});
            try stdout.context.flush();
        }else{
            break;
        }
    }
}
```

さて、Zigと来れば、Zenにも触れておいたほうが良いのかなと思います。
ZenはZig 0.3.0のほぼパクらしいですね。「ZigのプログラムであればZenでもコンパイルできる」であれば困らないのですが、そうではないので困る。
HSPの作者も[言語仕様を変えるなと言うてますしね](http://www.onionsoft.net/hsp/openhsp/)

あと、標準入出力の方法がわからず、webarchiveにあるサンプルを使った…。
https://web.archive.org/web/20200321133238/https://tomo-wait-for-it-yuki.hatenablog.com/entry/2020/02/17/205859

```
//usr/bin/env zen run "$0" "$@";exit
const std = @import("std");

fn isqrt(n:i64)i64{
    if(n<=0){return 0;}
    if(n<4){return 1;}
    var x:i64=0;
    var y:i64=n;
    while(x!=y and x+1!=y){x=y;y=@divFloor(@divFloor(n,y)+y,2);}
    return x;
}
fn icbrt(n:i64)i64{
    if(n<0){return -icbrt(-n);}
    if(n==0){return 0;}
    if(n<8){return 1;}
    var x:i64=0;
    var y:i64=n;
    while(x!=y and x+1!=y){x=y;y=@divFloor(@divFloor(@divFloor(n,y),y)+y*2,3);}
    return x;
}

fn is_sq(n:i64)bool{
    var x=isqrt(n);
    return x*x==n;
}
fn is_cb(n:i64)bool{
    var x=icbrt(n);
    return x*x*x==n;
}
fn is_multiple(i:i64,n:i64)bool{return @mod(i,n)==0;}
fn is_le(i:i64,n:i64)bool{return i<=n;}

fn generate(val:*mut i64)void{
    val.* = 1;
    while(true){
        suspend;
        val.* += 1;
    }
}

fn drop_prev(val:*mut i64,check:fn(i64)bool,prevvalue:*i64,prevframe:anyframe->void)void{
    var a = prevvalue.*;
    resume prevframe;
    var b = prevvalue.*;
    while(true){
        if(!check(b)){val.* = a;suspend;}
        a = b;
        resume prevframe;
        b = prevvalue.*;
    }
}

fn drop_next(val:*mut i64,check:fn(i64)bool,prevvalue:*i64,prevframe:anyframe->void)void{
    var a = prevvalue.*;
    resume prevframe;
    var b = prevvalue.*;
    val.* = a;
    suspend;
    while(true){
        if(!check(a)){val.* = b;suspend;}
        a = b;
        resume prevframe;
        b = prevvalue.*;
    }
}

fn drop_n(val:*mut i64,check:fn(i64,i64)bool,n:i64,prevvalue:*i64,prevframe:anyframe->void)void{
    var i:i64 = 0;
    while(true){
        i+=1;
        var a:i64 = prevvalue.*;
        if(!check(i,n)){val.* = a;suspend;}
        resume prevframe;
    }
}

pub fn main()!void{
    var stdin = try std.fs.getStdIn();
    //somehow making stdin buffered causes failure to read correctly
    //var stdin = std.io.BufferedInStream(std.fs.File.ReadError){
    //    .unbuffered_in_stream = &mut stdin_
    //};
    var stdout_ = try std.fs.getStdOut();
    var stdout = std.io.BufferedOutStream(std.fs.File.WriteError){
        .unbuffered_out_stream = &mut stdout_
    };
    var buf: [99]u8 = undefined;

    while(true){
        var user_input = std.fs.read.until(&mut stdin, &mut buf, '\n') catch |err| break;
        if(true){
            var h = std.container.AutoHashMap(u8,i64){.allocator = std.heap.page_allocator};
            defer h.deinit();
            _ = try h.put('S',0);
            _ = try h.put('s',0);
            _ = try h.put('C',0);
            _ = try h.put('c',0);
            _ = try h.put('h',0);
            _ = try h.put('2',0);
            _ = try h.put('3',0);
            _ = try h.put('4',0);
            _ = try h.put('5',0);
            _ = try h.put('6',0);
            _ = try h.put('7',0);
            _ = try h.put('8',0);
            _ = try h.put('9',0);

            var len = user_input.len-1;
            var reslst = try std.heap.alloc(std.heap.page_allocator,i64,len+1);
            defer std.heap.free(std.heap.page_allocator,reslst);
            var framelst = try std.heap.alloc(std.heap.c_allocator,anyframe->void,len+1);
            //defer std.heap.free(std.heap.page_allocator,framelst);
            framelst[0] = &(async generate(&mut reslst[0]));
            var i:usize=0;
            while(i<len){
                // async frameが行番号か何かで管理されているのか、同じ文字を複数回与えると"resumed a non-suspended function"が発生します。
                // やむを得ず、文字が与えられるたびに行番号を変えてframelstに入れるようにしています。本当にひどい。
                if(user_input[i]=='S'){
                    if(h.getValue('S').? == 0)framelst[i+1] = &(async drop_next(&mut reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.getValue('S').? == 1)framelst[i+1] = &(async drop_next(&mut reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.getValue('S').? == 2)framelst[i+1] = &(async drop_next(&mut reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.getValue('S').? == 3)framelst[i+1] = &(async drop_next(&mut reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.getValue('S').? == 4)framelst[i+1] = &(async drop_next(&mut reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    _ = try h.put('S',h.getValue('S').?+1);
                }
                if(user_input[i]=='s'){
                    if(h.getValue('s').? == 0)framelst[i+1] = &(async drop_prev(&mut reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.getValue('s').? == 1)framelst[i+1] = &(async drop_prev(&mut reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.getValue('s').? == 2)framelst[i+1] = &(async drop_prev(&mut reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.getValue('s').? == 3)framelst[i+1] = &(async drop_prev(&mut reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    if(h.getValue('s').? == 4)framelst[i+1] = &(async drop_prev(&mut reslst[i+1],is_sq,&reslst[i],framelst[i]));
                    _ = try h.put('s',h.getValue('s').?+1);
                }
                if(user_input[i]=='C'){
                    if(h.getValue('C').? == 0)framelst[i+1] = &(async drop_next(&mut reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.getValue('C').? == 1)framelst[i+1] = &(async drop_next(&mut reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.getValue('C').? == 2)framelst[i+1] = &(async drop_next(&mut reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.getValue('C').? == 3)framelst[i+1] = &(async drop_next(&mut reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.getValue('C').? == 4)framelst[i+1] = &(async drop_next(&mut reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    _ = try h.put('C',h.getValue('C').?+1);
                }
                if(user_input[i]=='c'){
                    if(h.getValue('c').? == 0)framelst[i+1] = &(async drop_prev(&mut reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.getValue('c').? == 1)framelst[i+1] = &(async drop_prev(&mut reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.getValue('c').? == 2)framelst[i+1] = &(async drop_prev(&mut reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.getValue('c').? == 3)framelst[i+1] = &(async drop_prev(&mut reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    if(h.getValue('c').? == 4)framelst[i+1] = &(async drop_prev(&mut reslst[i+1],is_cb,&reslst[i],framelst[i]));
                    _ = try h.put('c',h.getValue('c').?+1);
                }
                if(user_input[i]=='h'){
                    if(h.getValue('h').? == 0)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_le,100,&reslst[i],framelst[i]));
                    if(h.getValue('h').? == 1)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_le,100,&reslst[i],framelst[i]));
                    if(h.getValue('h').? == 2)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_le,100,&reslst[i],framelst[i]));
                    if(h.getValue('h').? == 3)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_le,100,&reslst[i],framelst[i]));
                    if(h.getValue('h').? == 4)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_le,100,&reslst[i],framelst[i]));
                    _ = try h.put('h',h.getValue('h').?+1);
                }
                if(user_input[i]=='2'){
                    if(h.getValue('2').? == 0)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,2,&reslst[i],framelst[i]));
                    if(h.getValue('2').? == 1)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,2,&reslst[i],framelst[i]));
                    if(h.getValue('2').? == 2)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,2,&reslst[i],framelst[i]));
                    if(h.getValue('2').? == 3)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,2,&reslst[i],framelst[i]));
                    if(h.getValue('2').? == 4)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,2,&reslst[i],framelst[i]));
                    _ = try h.put('2',h.getValue('2').?+1);
                }
                if(user_input[i]=='3'){
                    if(h.getValue('3').? == 0)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,3,&reslst[i],framelst[i]));
                    if(h.getValue('3').? == 1)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,3,&reslst[i],framelst[i]));
                    if(h.getValue('3').? == 2)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,3,&reslst[i],framelst[i]));
                    if(h.getValue('3').? == 3)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,3,&reslst[i],framelst[i]));
                    if(h.getValue('3').? == 4)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,3,&reslst[i],framelst[i]));
                    _ = try h.put('3',h.getValue('3').?+1);
                }
                if(user_input[i]=='4'){
                    if(h.getValue('4').? == 0)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,4,&reslst[i],framelst[i]));
                    if(h.getValue('4').? == 1)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,4,&reslst[i],framelst[i]));
                    if(h.getValue('4').? == 2)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,4,&reslst[i],framelst[i]));
                    if(h.getValue('4').? == 3)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,4,&reslst[i],framelst[i]));
                    if(h.getValue('4').? == 4)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,4,&reslst[i],framelst[i]));
                    _ = try h.put('4',h.getValue('4').?+1);
                }
                if(user_input[i]=='5'){
                    if(h.getValue('5').? == 0)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,5,&reslst[i],framelst[i]));
                    if(h.getValue('5').? == 1)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,5,&reslst[i],framelst[i]));
                    if(h.getValue('5').? == 2)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,5,&reslst[i],framelst[i]));
                    if(h.getValue('5').? == 3)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,5,&reslst[i],framelst[i]));
                    if(h.getValue('5').? == 4)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,5,&reslst[i],framelst[i]));
                    _ = try h.put('5',h.getValue('5').?+1);
                }
                if(user_input[i]=='6'){
                    if(h.getValue('6').? == 0)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,6,&reslst[i],framelst[i]));
                    if(h.getValue('6').? == 1)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,6,&reslst[i],framelst[i]));
                    if(h.getValue('6').? == 2)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,6,&reslst[i],framelst[i]));
                    if(h.getValue('6').? == 3)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,6,&reslst[i],framelst[i]));
                    if(h.getValue('6').? == 4)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,6,&reslst[i],framelst[i]));
                    _ = try h.put('6',h.getValue('6').?+1);
                }
                if(user_input[i]=='7'){
                    if(h.getValue('7').? == 0)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,7,&reslst[i],framelst[i]));
                    if(h.getValue('7').? == 1)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,7,&reslst[i],framelst[i]));
                    if(h.getValue('7').? == 2)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,7,&reslst[i],framelst[i]));
                    if(h.getValue('7').? == 3)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,7,&reslst[i],framelst[i]));
                    if(h.getValue('7').? == 4)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,7,&reslst[i],framelst[i]));
                    _ = try h.put('7',h.getValue('7').?+1);
                }
                if(user_input[i]=='8'){
                    if(h.getValue('8').? == 0)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,8,&reslst[i],framelst[i]));
                    if(h.getValue('8').? == 1)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,8,&reslst[i],framelst[i]));
                    if(h.getValue('8').? == 2)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,8,&reslst[i],framelst[i]));
                    if(h.getValue('8').? == 3)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,8,&reslst[i],framelst[i]));
                    if(h.getValue('8').? == 4)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,8,&reslst[i],framelst[i]));
                    _ = try h.put('8',h.getValue('8').?+1);
                }
                if(user_input[i]=='9'){
                    if(h.getValue('9').? == 0)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,9,&reslst[i],framelst[i]));
                    if(h.getValue('9').? == 1)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,9,&reslst[i],framelst[i]));
                    if(h.getValue('9').? == 2)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,9,&reslst[i],framelst[i]));
                    if(h.getValue('9').? == 3)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,9,&reslst[i],framelst[i]));
                    if(h.getValue('9').? == 4)framelst[i+1] = &(async drop_n(&mut reslst[i+1],is_multiple,9,&reslst[i],framelst[i]));
                    _ = try h.put('9',h.getValue('9').?+1);
                }
                i+=1;
            }
            i = 0;
            while(i<10){
                if(i>0)try std.fs.write.print(&mut stdout,",",.{});
                try std.fs.write.print(&mut stdout,"{}",.{reslst[len]});
                resume framelst[len];
                i+=1;
            }
            try std.fs.write.print(&mut stdout,"\n",.{});
            try stdout.flush();
        //}else{
        //    break;
        }
    }
}
```

残念ながらresumed a non-suspended function問題はZenにも健在。Zigよりも先に解決するなら「独自に進化を遂げたプログラミング言語」を名乗ってもいいんじゃない(煽りw)

Zig 0.7.0 / Zen 0.8.0で動作確認。今後動かなくなる可能性はVの答案より高いw