読者です 読者をやめる 読者になる 読者になる

矮小

井の中の蛙

CODE THANKS FESTIVAL 2014 B日程 A,B,C問題

CODE THANKS FESTIVAL,略すとCTFになって全く別のもの (Capture The Flag) になってしまうので来年もやるなら何とかしたほうがいいと思います.

Tasks - code thanks festival 2014 B日程(オープンコンテスト) | AtCoder

今回解くにあたってRubyD言語で結構悩んだんですが,最終的に個性を発揮していこうということでD言語で書きました.僕以外にD言語を提出していたのはarukukaさん(F, G問題)だけでした.やっぱりアルゴリズム中心にプログラムを書くときはこっちの方が書きやすい気がする.ネイティブ吐くからC++並に速い(はず)なのでおすすめです.

A 朝食

コーヒーを淹れるのにかかる時間とトーストを焼くのにかかる時間が与えられるので,この2つを同時に始めた時に最終的に何分かかるのかを答える.

解法:maxを取る

import std.stdio;
import std.algorithm;
import std.range;
import std.string;
import std.conv;

void main() {
    auto input = readln.chomp.split.map!(to!int);
    writeln(input[0] > input[1] ? input[0] : input[1]);
}

結構面倒な書き方をしちゃったけどD言語にはstd.algorithm.maxがあるのでこれを使えばいいだけだった.ちなみにこれを使うとmax(input[0], input[1]).writelnになる.

B 電卓ゲーム

3つの数字が与えられるので,足し算と掛け算を使って一番大きくなる数を求める.

解法:数の順番は同じだから全事象は4通りなので,全部やる

import std.stdio;
import std.algorithm;
import std.range;
import std.string;
import std.conv;

void main() {
    int a = readln.chomp.to!int;
    int b = readln.chomp.to!int;
    int c = readln.chomp.to!int;

    int pp = a + b + c;
    int pm = (a + b) * c;
    int mp = (a * b) + c;
    int mm = a * b * c;

    writeln(max(pp, pm, mp, mm));
}

いちいち代入せずに全部直接引数に書けばよかった.以下の通りになる.

max(a + b + c, (a + b) * c, (a * b) + c, a * b * c).writeln;

std.algorithm.maxの引数は2個以上です.可変長です.ちなみに配列の中で最小の要素を求めたいときはstd.algorithm.minPosを使います.この関数は引数の配列の中で最小の値が先頭になるような部分配列を返します.テンプレート引数に述語を渡すとその述語を元に大小を判断するようになります.公式ライブラリリファレンスにもある通り,この理由によりmaxPos関数はありません.以下のように動作します.

import std.stdio;
import std.algorithm;

void main() {
    int[] ary = [ 5, 9, 2, 3 ];
    ary.minPos.writeln; // [2, 3]
    ary.minPos!("a > b").writeln; // [9, 2, 3]
    ary.minPos!("a > b")[0].writeln; // 9
}

C 人気投票ゲーム

全ての投票数の数列ときつね派の投票数の数列が与えられるので,各列についてきつね派が過半数を取った列を数える.

解法:過半数の定義は「半分より大きい」なので,この点に注意して比較する.

import std.stdio;
import std.algorithm;
import std.range;
import std.string;
import std.conv;

void main() {
    readln;
    auto v = readln.chomp.split.map!(to!int);
    auto f = readln.chomp.split.map!(to!int);

    int count = 0;

    foreach (e; zip(v, f)) {
        if (e[1] * 2 > e[0]) {
            count++;
        }
    }

    count.writeln;
}

きつね派の投票数が全体の投票数の2倍より大きければOK.基本的に割る系の処理は誤差とか切り捨てとか怖いので使わない方向で.あとD言語にもzip関数はあります (std.algorithm.zip).zip([[1, 2, 3], [4, 5, 6]])[[1, 4], [2, 5], [3, 6]]になるタイプのやつです.あとforeachも言語仕様でサポートされています.foreach_reverseもあります.reverseの方はあんまり使ったことないけど.