LoginSignup
0
0

More than 1 year has passed since last update.

多段階選抜 (Pascal/Cobra)

Last updated at Posted at 2019-01-16
多段階選抜 解答日 シリーズ:yieldの練習/ジェネレータを入れ子に/整数平方根・立方根の実装
問題   http://nabetani.sakura.ne.jp/hena/ord24eliseq/
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)
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に等しい(ことの証明)
https://qiita.com/cielavenir/items/21a6711afd6be8c18c55

Pascal

PascalABC.NET実装です。
つまり…実質C#です…
FPCがFiberに対応した際の足がかりとでも思っておきます…

tyama_hena24_enum.pas
// http://qiita.com/Nabetani/items/1c83005a854d2c6cbb69
// http://nabetani.sakura.ne.jp/hena/ord24eliseq/

program hena24;
uses
    System;
var
    i: longint;
    g: sequence of longint;
    s: string;
    z: IEnumerator<longint>;

function isqrt(n: longint): longint;
var
    x: longint;
    y: longint;
begin
    if(n<=0) then
        isqrt:=0
    else if(n<4) then
        isqrt:=1
    else begin
        x:=0;
        y:=n;
        while((x<>y) and (x+1<>y)) do begin
            x:=y;
            y:=(n div y+y) div 2;
        end;
        isqrt:=x;
    end;
end;

function icbrt(n: longint): longint;
var
    x: longint;
    y: longint;
begin
    if(n<0) then
        icbrt:=0
    else if(n<8) then
        icbrt:=1
    else begin
        x:=0;
        y:=n;
        while((x<>y) and (x+1<>y)) do begin
            x:=y;
            y:=(n div y div y+y*2) div 3;
        end;
        icbrt:=x;
    end;
end;

function is_sq(n: longint): boolean;
var
    x: longint;
begin
    x:=isqrt(n);
    is_sq:=x*x=n;
end;

function is_cb(n: longint): boolean;
var
    x: longint;
begin
    x:=icbrt(n);
    is_cb:=x*x*x=n;
end;

function is_multiple(i:longint; n: longint): boolean;
begin
    is_multiple:=i mod n=0;
end;

function is_le(i:longint; n: longint): boolean;
begin
    is_le:=i<=n;
end;

function generate(): sequence of longint;
var
    i: longint;
begin
    i:=1;
    while true do begin
        yield i;
        i:=i+1;
    end;
end;

function drop_prev(check: function(x:longint):boolean; _prev: sequence of longint): sequence of longint;
var
    a: longint;
    b: longint;
    prev: IEnumerator<longint>;
begin
    prev:=_prev.GetEnumerator();
    prev.MoveNext();
    a:=prev.Current;
    prev.MoveNext();
    b:=prev.Current;
    while true do begin
        if not check(b) then yield a;
        a:=b;
        prev.MoveNext();
        b:=prev.Current;
    end;
end;

function drop_next(check: function(x:longint):boolean; _prev: sequence of longint): sequence of longint;
var
    a: longint;
    b: longint;
    prev: IEnumerator<longint>;
begin
    prev:=_prev.GetEnumerator();
    prev.MoveNext();
    a:=prev.Current;
    prev.MoveNext();
    b:=prev.Current;
    yield a;
    while true do begin
        if not check(a) then yield b;
        a:=b;
        prev.MoveNext();
        b:=prev.Current;
    end;
end;

function drop_n(check: function(x:longint;y:longint):boolean; n: longint; _prev: sequence of longint): sequence of longint;
var
    a: longint;
    i: longint;
    prev: IEnumerator<longint>;
begin
    prev:=_prev.GetEnumerator();
    i:=0;
    while true do begin
        i:=i+1;
        prev.MoveNext();
        a:=prev.Current;
        if not check(i,n) then yield a;
    end;
end;

begin
    var f:=new Dictionary<char,Func<sequence of longint,sequence of longint>>();
    f['S']:=x->drop_next(is_sq,x);
    f['s']:=x->drop_prev(is_sq,x);
    f['C']:=x->drop_next(is_cb,x);
    f['c']:=x->drop_prev(is_cb,x);
    f['h']:=x->drop_n(is_le,100,x);
    for i:=2 to 9 do begin
        var j:=i;
        f[char(48+j)]:=x->drop_n(is_multiple,j,x);
    end;

    while true do begin
        s:=Console.ReadLine();
        if s=nil then break;
        g:=generate();
        for i:=1 to length(s) do g:=f[s[i]](g);
        z:=g.GetEnumerator();
        for i:=0 to 9 do begin
            if i>0 then write(',');
            z.MoveNext();
            write(z.Current);
        end;
        writeln();
        Console.Out.Flush();
    end;
end.

Cobra

処理系 http://cobra-language.com/downloads/

CLR系で水増しとか言わない^^;;

Booの答案をいじったらできた模様。コロン不要だと改行しなきゃという気持ちになっていいですねorz
そういえばコロン不要な言語にCoffeeScriptというのがあった気がしますが、JavaScriptはまだ安定してなかったはずですし、それこそキリが無くなるので汗

にしても、CLR APIの命名とかこだわりを感じるんですが、Linqが使えないという致命傷を抱えているんですよね…

tyama_hena24_enum.cobra
#!/usr/bin/env cobra
#http://qiita.com/Nabetani/items/1c83005a854d2c6cbb69
#http://nabetani.sakura.ne.jp/hena/ord24eliseq/
use System
#use System.Linq.Enumerable
use System.Collections.Generic

class Hena24
    def isqrt(n as int) as int
        if n<=0
            return 0
        if n<4
            return 1
        x,y=0,n
        while x<>y and x+1<>y
            x,y=y,(n//y+y)//2
        return x

    def icbrt(n as int) as int
        if n<0
            return -(.icbrt(-n))
        if n==0
            return 0
        if n<8
            return 1
        x,y=0,n
        while x<>y and x+1<>y
            x,y=y,(n//y // y+y*2) // 3
        return x

    def generate as IEnumerable<of int>
        i=1
        while true
            yield i
            i+=1

    def drop_prev(check as Func<of int,bool>,prev_ as IEnumerable<of int>) as IEnumerable<of int>
        prev=prev_.getEnumerator
        prev.moveNext
        a=prev.current
        prev.moveNext
        b=prev.current
        while true
            if not check(b)
                yield a
            prev.moveNext
            a,b=b,prev.current

    def drop_next(check as Func<of int,bool>,prev_ as IEnumerable<of int>) as IEnumerable<of int>
        prev=prev_.getEnumerator
        prev.moveNext
        a=prev.current
        prev.moveNext
        b=prev.current
        yield a
        while true
            if not check(a)
                yield b
            prev.moveNext
            a,b=b,prev.current

    def drop_n(check as Func<of int,int,bool>,n as int,prev_ as IEnumerable<of int>) as IEnumerable<of int>
        prev=prev_.getEnumerator
        i=0
        while true
            i+=1
            prev.moveNext
            a=prev.current
            if not check(i,n)
                yield a

    def is_sq(n as int) as bool
        return (x=.isqrt(n))*x==n
    def is_cb(n as int) as bool
        return (x=.icbrt(n))*x*x==n
    def is_multiple(i as int,n as int) as bool
        return i%n==0
    def is_le(i as int,n as int) as bool
        return i<=n

    def main
        f=Dictionary<of char,Func<of IEnumerable<of int>,IEnumerable<of int>>>()
        f[c'S']=do(x as IEnumerable<of int>)=.drop_next(ref .is_sq,x)
        f[c's']=do(x as IEnumerable<of int>)=.drop_prev(ref .is_sq,x)
        f[c'C']=do(x as IEnumerable<of int>)=.drop_next(ref .is_cb,x)
        f[c'c']=do(x as IEnumerable<of int>)=.drop_prev(ref .is_cb,x)
        f[c'h']=do(x as IEnumerable<of int>)=.drop_n(ref .is_le,100,x)

        #error: Unexpected call.
        #for e in 2 : 10
        #   z=e
        #   f[(48+z) to char]=(do(n as int)=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,n,x))(z)

        f[c'2']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,2,x)
        f[c'3']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,3,x)
        f[c'4']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,4,x)
        f[c'5']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,5,x)
        f[c'6']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,6,x)
        f[c'7']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,7,x)
        f[c'8']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,8,x)
        f[c'9']=do(x as IEnumerable<of int>)=.drop_n(ref .is_multiple,9,x)

        while true
            line=Console.readLine
            if line==nil
                break
            first=true
            #cS => f['S'](f['c'](.generate))
            g=.generate
            for c in line
                g=f[c](g)
            for n in g.take(10)
                if not first
                    Console.write(',')
                first=false
                Console.write(n)
            Console.writeLine
            Console.out.flush
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0