AOJ0261 Mayan Crucial Prediction

問題リンク Mayan Crucial Prediction

  • 解法

入力された日が基準日(0.0.0.0.0 or 2012/12/21)から何日離れているかを計算して、もう片方の暦の上でその日数分、日にちを進めました。
1日ずつカウントするとえらいことになるので、1周期(マヤなら13*20*20*18*20日、西暦なら(365or366)日)まとめて動かしてやれば速く計算できます。

  • ソース
import java.util.Scanner;

//Mayan Crucial Prediction
public class AOJ0261 {

	int[] day = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	int MOD = 13*20*20*18*20;
	int B = 20*20*18*20;
	int KA = 20*18*20;
	int T = 18*20;
	int W = 20;
	
	void run(){
		Scanner sc = new Scanner(System.in);
		for(;;){
			String in = sc.next();
			if("#".equals(in))break;
			String[] t = in.split("\\.");
			int n = t.length;
			int[] a = new int[n];
			for(int i=0;i<n;i++)a[i]=Integer.parseInt(t[i]);
			if(n==5)toSeireki(a[0], a[1], a[2], a[3], a[4]);
			else toMayan(a[0], a[1], a[2]);
		}
	}
	
	void toSeireki(int b, int ka, int t, int w, int ki){
		int days = b*B + ka*KA + t*T + w*W + ki;
		int y = 2012, m = 12, d = 21;
		while(0 < days){
			if(m==1 && d==1){
				int yearDay = 365 + leap(y);
				if(yearDay <= days){
					y++;
					days-=yearDay;
					continue;
				}
			}
			if(m==2){
				if(d==day[2]+leap(y)){
					m++; d=1;
				}
				else d++;
			}
			else{
				if(d==day[m]){
					m++; d=1;
					if(m==13){
						y++; m=1;
					}
				}
				else d++;
			}
			days--;
		}
		System.out.printf("%d.%d.%d\n", y, m, d);
	}

	int leap(int y){
		return y%4==0 && (y%100!=0 || y%400==0) ? 1 : 0;
	}
	
	void toMayan(int y, int m, int d){
		int Y = 2012, M = 12, D = 21;
		int days = 0;
		while(Y!=y || M!=m || D!=d){
			if(MOD <= days)days-=MOD;
			if(M==1 && D==1){
				if(Y!=y){
					int year = 365+leap(Y);
					days+=year;
					Y++;
					continue;
				}
			}
			if(M==2){
				if(D==day[2]+leap(Y)){
					M++; D=1;
				}
				else D++;
			}
			else{
				if(D==day[M]){
					M++; D=1;
					if(M==13){
						Y++; M=1;
					}
				}
				else D++;
			}
			days++;
		}
		if(MOD <= days)days-=MOD;
		int b = days/B; days%=B;
		int ka = days/KA; days%=KA;
		int t = days/T; days%=T;
		int w = days/W; days%=W;
		int ki = days;
		System.out.printf("%d.%d.%d.%d.%d\n", b, ka, t, w, ki);
	}

	public static void main(String[] args) {
		new AOJ0261().run();
	}
}