POH!4Liteが簡単すぎたので鯖を調べた


はじめに

POHでC#はCライブラリを直接呼んだり自前で文字列数値変換するなどの行為は一部で不評を買っていた。
前回、鯖の中身がUbuntuだと気付いたのでデバイスファイル経由ならいいんじゃないかと思ったがそうでもなかった。
そしてその過程で/dev/stdoutが使えないことに気付いた。

調査

どうやって調べればいいかについてだが以下の様にbashでコマンドを打てばよい。

;結果は
lrwxrwxrwx 1 root root 15 Dec 4 10:29 /dev/stdout -> /proc/self/fd/1 
l-wx------ 1 runner2 ubuntu 64 Dec 4 10:29 /proc/self/fd/1 -> /workspace/exec_stdout.txt 
-rw-r--r-- 1 root root 160 Dec 4 10:29 /workspace/exec_stdout.txt 
Linux 263a4c739076 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

上記のように/workspace/exec_stdout.txtにリダイレクトされているが肝心のwrite権が無いのでシンボリックリンクにwrite権があってもだめなのであった。
なおuserはrunnerXであり、root以外書けないexec_stdout.txtにはどうしようもない。

そしてgccとかが動くのでシェルを叩いてあらゆる言語についてcソースコンパイルして実行でクリア出来る筈である。
本当はその手を今回使うつもりだったが、課題が簡単すぎてやめた。

ソース

今見て気付いたがheadとtailが逆?(どっちでもいいような気もする)。何故かバックするウナギと言う事にしておいてほしい。
なお、コメント部分を復帰してreadとprintfを削除すれば一応C#のみのコードになるので、実行時間を比較してみるとよいかもしれない。
ReadIntといいつつuintなのは300000x10000が21億を超えることへの対応でありリネーム忘れでもある。

using System;
using System.IO;
using System.Runtime.InteropServices;
public class Query3
{
    [DllImport("libc")]
    static extern int read(int handle, byte[] buf, int n);
    [DllImport("libc")]
    static extern void printf(string format, uint value);
    static byte[] buf = new byte[10000000];
    static int index = 0;
    static uint ReadInt()
    {
        uint ret = 0, tmp;
        while ((tmp = buf[index++]) >= '0')
            ret = ret * 10 + (tmp - '0');
        return ret;
    }
    static void Main(string[] args)
    {
        //var f = File.OpenRead("/dev/stdin");
      // f.Read(buf, 0, 10000000);
        read(0, buf, 10000000);
        var t = ReadInt();
        var n = ReadInt();
        uint sum = 0, tail = 0, max = 0, head = 0;
        uint[] array = new uint[n];
        var loop = t;
        while ((loop--) > 0)
        {
            sum += array[tail++] = ReadInt();
        }
        max = sum;
        loop = n - t;
        while ((loop--) > 0)
        {
            sum = sum + (array[tail++] = ReadInt()) - array[head++];
            if (sum > max)
            {
                max = sum;
            }
        }
        //Console.WriteLine(max);
        printf("%u\n", max);
    }
}