Problem:
マヤの大予言

真也君はテレビで「マヤの大予言！2012年で世界が終る？」という番組を見ました。結局、世界が終るかどうかはよくわかりませんでしたが、番組で紹介されていたマヤの「長期暦」という暦に興味を持ちました。その番組では以下のような説明をしていました。

マヤ長期暦は、右の表のような単位からなる、全部で13バクトゥン(187万2000日)で構成される非常に長い暦である。ある計算法では、この暦は紀元前3114年8月11日に始まり2012年12月21日に終わると考えられていて、このため今年の12月21日で世界が終るという説が唱えられている。しかし、13バクトゥンで１サイクルとなり、今の暦が終わったら新しいサイクルに入るだけという考えもある。

１キン＝１日

１ウィナル＝２０キン

１トゥン＝１８ウィナル

１カトゥン＝２０トゥン

１バクトゥン＝２０カトゥン

 

「ぼくの二十歳の誕生日はマヤ暦だと何日になるのかな？」真也君はいろいろな日をマヤ長期暦で表してみたくなりました。

では、真也君の代わりに、西暦とマヤ長期暦とを相互変換するプログラムを作成してください。

入力

入力は複数のデータセットからなる。入力の終わりは#１つの行で示される。各データセットは以下の形式で与えられる。

b.ka.t.w.ki

または

y.m.d

データセットは１つの文字列を含む１行からなる。b.ka.t.w.ki はマヤ長期暦の日付、y.m.d は西暦の日付である。与えられる単位は以下の通りである。

マヤ長期暦

b

バクトゥン

(0 ≤ b< 13)

ka

カトゥン

(0 ≤ ka < 20)

t

トゥン

(0 ≤ t< 20)

w

ウィナル

(0 ≤ w < 18)

ki

キン

(0 ≤ ki < 20)

西暦

y

年

(2012 ≤ y ≤ 10,000,000)

m

月

(1 ≤ m ≤ 12)

d

日

(1 ≤ d ≤ 31)

西暦の日の最大値は、大の月、小の月、うるう年かどうかで変わる(うるう年は 4 の倍数の年のうち、100 で割り切れない年か、400 で割り切れる年である)。マヤ長期暦の日付の範囲は 0.0.0.0.0 から 12.19.19.17.19 までとする。ただし、マヤ長期暦の 0.0.0.0.0 は西暦の 2012.12.21 に対応する。また、西暦の日付の範囲は 2012.12.21から 10000000.12.31 までとする。

データセットの数は 500 を超えない。

出力

入力が西暦のときはマヤ長期暦を、マヤ長期暦のときは西暦を、それぞれ入力と同じ形式で出力する。
入力された西暦を換算した結果、マヤ長期暦の次のサイクルに入った場合でも b.ka.t.w.ki の形式で出力してよい。

入力例

2012.12.31
2.12.16.14.14
7138.5.13
10.5.2.1.5
10000000.12.31
#

出力例

0.0.0.0.10
3054.8.15
0.0.0.0.10
6056.2.29
8.19.3.13.2

Solution in JAVA (judge verdict: Accepted)

import java.util.*;

public class Main {
	boolean isLeapYear(long y) {
		if(y%4==0) {
			if(y%100!=0 || y%400==0) {
				return true;
			}
		}
		
		return false;
	}
	
	long y2d(long y) {
		long day = 365;
		if( isLeapYear(y) ) {
				++day;
		}
		
		return day;
	}
	
	long ally2d(long y) {
		long day = 0;
		for( int i = 0; i < y; ++i ) {
			day += y2d(i);
		}
		
		return day;
	}
	
	long m2d(long y, long d) {
		switch((int)d){
		case 2:
			long day = 28;
			if( isLeapYear(y) ) {
				++day;
			}
			return day;
		case 4:
		case 6:
		case 9:
		case 11:
			return 30;
		default:
			return 31;
		}
	}
	
	long[] miniy = new long[]{ 2, 4, 6, 9, 11 };
	long allm2d(long y, long m) {
		long day = 0;
		for( int i = 1; i < m; ++i ) {
			day += m2d(y, i);
		}
		
		return day;
	}
	
	long cycle;
	long[] d4y;
	
	long[] max_may_n = new long[]{13, 20, 20, 19, 20};
	String usu2may(ArrayList<Integer> list) {
		long day = d4y[list.get(0)];
		day += allm2d(list.get(0), list.get(1));
		day += (long)list.get(2);
		
		day -= cycle;
		
		String ans = "";
		
		for( int i = 0; i < 5; ++i ) {
			if( i > 0 ) {
				ans += ".";
			}
			ans += (day / mayas_day[i])%max_may_n[i];
			day %= mayas_day[i];
		}
		
		return ans;
	}
	
	long ki = 1;
	long w  = 20*ki;
	long t  = 18*w;
	long ka = 20*t;
	long b  = 20*ka;
	long mayas_day[] = {b, ka, t, w, ki};
	String may2usu(ArrayList<Integer> list) {
		long day = 0;
		for( int i = 0; i < 5; ++i ) {
			day += mayas_day[i]*(long)list.get(i);
		}
		
		day += cycle;
		
		long y = 0;
		while(day > y2d(y)) {
			day -= y2d(y);
			++y;
		}
		long m = 1;
		while(day > m2d(y, m)) {
			day -= m2d(y, m);
			++m;
		}
		long d = day;
		
		return y + "." + m + "." + d;
	}
	
	void solve() {
		Scanner sc = new Scanner(System.in);
		
		cycle = 0;
		cycle += ally2d(2012);
		cycle += allm2d(2012, 12);
		cycle += 21;
		
		d4y = new long[10000001];
		d4y[0] = 0;
		for( int i = 1; i <= 10000000; ++i ) {
			d4y[i] = d4y[i-1] + y2d(i-1);
		}
		
		while(true) {
			String str = sc.nextLine();

			if( str.equals("#") ) {
				break;
			}
			
			ArrayList<Integer> list = new ArrayList<Integer>();
			for( String ite : str.split("\\.") ) {
				list.add(Integer.parseInt(ite));
			}
			
			System.out.println(list.size() == 3 ? usu2may(list) : may2usu(list));
		}
		
		sc.close();
	}
	
	public static void main(String[] args) {
		new Main().solve();
	}
	
	void debug(Object... os) {
		System.err.println(Arrays.deepToString(os));
	}
}