パソコン甲子園

2006年のパソコン甲子園の本選の問題(PDF)の3問目に違和感を感じると思ったら、2:15の場合の判定がおかしい。

問題の概略は、
「時計の長針と短針が重なったときにいたずらが発生するから、警戒するために長針と短針が近ければ"alert"、遠ければ"safe"、その中間なら"warning"と表示させるプログラムをつくれ」
ということだけど、この問題、短針のほうが遅いことを考慮していない。入力例に2:15があるけど、この状況だと短針のほうが後ろにいるから、警戒する必要はない。

ってことで、ここらへんの判定も行うプログラムを作ってみた。適当。

import java.io.*;

public class Q03 {
    private static double toDegree(int hour, int minute) {
        return hour * 30 + (minute / 12.0) * 6;     // 1時間30度、12分6度
    }
    
    private static double toDegree(int minute) {
        return minute * 6.0;    // 1分6度
    }
    
    public static enum Kind {
        ALERT, SAFE, WARNING;
    }
    
    public static Kind judge(double h, double m) {
        double delta = m - h;
        if (delta < 0) delta = 360 + delta; // 360 - (-delta)
        
        if (delta > 330) return Kind.ALERT;
        if (delta <= 270) return Kind.SAFE;
        return Kind.WARNING;
    }
    
    public static void main(String[] args) throws IOException {
        BufferedReader in = null;
        try {
            in = new BufferedReader(
                new InputStreamReader(System.in));
            
            int num = Integer.parseInt(in.readLine());
            Kind[] results = new Kind[num];
            for (int i = 0; i < num; i++) {
                String[] elements = in.readLine().split(":");
                int hour    = Integer.parseInt(elements[0]);
                int minute  = Integer.parseInt(elements[1]);
                
                double hourDeg      = toDegree(hour, minute);
                double minuteDeg    = toDegree(minute);
                
                results[i] = judge(hourDeg, minuteDeg);
            }
            for (Kind result : results)
                System.out.println(result.toString().toLowerCase());
        } finally {
            if (in != null) in.close();
        }
    }
}

たまにはこういう息抜きもいいとは思うものの、こういう問題を時間を決められてガリガリとくのはいやだなぁ。こういう大会で上位に行ける人はすごいと思う*1

*1:自分は速く正確に解くのが苦手なんで・・・