Problem:
Score : 100 points

Problem Statement

You are given a string S as input. This represents a valid date in the year 2019 in the yyyy/mm/dd format. (For example, April 30, 2019 is represented as 2019/04/30.)

Write a program that prints Heisei if the date represented by S is not later than April 30, 2019, and prints TBD otherwise.

Constraints

S is a string that represents a valid date in the year 2019 in the yyyy/mm/dd format.

Input

Input is given from Standard Input in the following format:

S

Output

Print Heisei if the date represented by S is not later than April 30, 2019, and print TBD otherwise.

Sample Input 1

2019/04/30

Sample Output 1

Heisei

Sample Input 2

2019/11/01

Sample Output 2

TBD

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.IO;
using System.Text.RegularExpressions;
using System.Text;
using System.Diagnostics;
using System.Globalization;
using static System.Math;

namespace A
{
	public class Program
	{
		// variables

		void Run(string[] args)
		{
			// main program
			var date_regex = new Regex(@"(\d+)/(\d+)/(\d+)");
			var match = date_regex.Match(Word);
			var year = int.Parse(match.Groups[1].Value);
			var month = int.Parse(match.Groups[2].Value);
			var date = int.Parse(match.Groups[3].Value);
			if (2019 < year
				|| 2019 == year && 4 < month)
			{
				PrintLine("TBD");
			}
			else
			{
				PrintLine("Heisei");
			}
		}

		// methods

		// utilities
		static void Main(string[] args)
		{
			new Program().Run(args);
#if DEBUG
			Console.Write("Press any key...");
			Console.ReadKey();
#endif
		}

		/// <summary>
		/// Make an array
		/// </summary>
		/// <typeparam name="T">type of element</typeparam>
		/// <param name="count">number of elements</param>
		/// <param name="input">element generator</param>
		/// <returns>array</returns>
		static T[] MakeArray<T>(int count, Func<int, T> input)
		{
			var array = new T[count];
			for (var i = 0; i < count; ++i)
			{
				array[i] = input(i);
			}
			return array;
		}
		/// <summary>
		/// Make a 2-dimensional array
		/// </summary>
		/// <typeparam name="T">type of element</typeparam>
		/// <param name="count1">size of first dimension</param>
		/// <param name="count2">size of second dimension</param>
		/// <param name="input">element generator</param>
		/// <returns>2-dimensional array</returns>
		static T[,] MakeArray<T>(int count1, int count2, Func<int, int, T> input)
		{
			var array = new T[count1, count2];
			for (var i = 0; i < count1; ++i)
			{
				for (var j = 0; j < count2; ++j)
				{
					array[i, j] = input(i, j);
				}
			}
			return array;
		}
		/// <summary>
		/// Make a 3-dimensional array
		/// </summary>
		/// <typeparam name="T">type of element</typeparam>
		/// <param name="count1">size of first dimension</param>
		/// <param name="count2">size of second dimension</param>
		/// <param name="count3">size of third dimension</param>
		/// <param name="input">element generator</param>
		/// <returns>3-dimensional array</returns>
		static T[,,] MakeArray<T>(int count1, int count2, int count3, Func<int, int, int, T> input)
		{
			var array = new T[count1, count2, count3];
			for (var i = 0; i < count1; ++i)
			{
				for (var j = 0; j < count2; ++j)
				{
					for (var k = 0; k < count3; ++k)
					{
						array[i, j, k] = input(i, j, k);
					}
				}
			}
			return array;
		}

		/// <summary>
		/// Output any value
		/// </summary>
		/// <typeparam name="T">type of value.</typeparam>
		/// <param name="value">value</param>
		[DebuggerNonUserCode]
		static void Print<T>(T value) => Console.Write(value);
		/// <summary>
		/// Output any value on a line
		/// </summary>
		/// <typeparam name="T">type of value</typeparam>
		/// <param name="value">value</param>
		[DebuggerNonUserCode]
		static void PrintLine<T>(T value) => Console.WriteLine(value);
		/// <summary>
		/// Output a line break
		/// </summary>
		[DebuggerNonUserCode]
		static void PrintLine() => Console.WriteLine();

		/// <summary>
		/// Input a word
		/// </summary>
		static string Word
		{
			[DebuggerNonUserCode]
			get
			{
				char c;
				while (char.IsWhiteSpace(c = (char)Console.Read()))
				{
					continue;
				}

				var builder = new StringBuilder();
				do
				{
					builder.Append(c);
				}
				while (!char.IsWhiteSpace(c = (char)Console.Read()));

				return builder.ToString();
			}
		}
		/// <summary>
		/// Input a line
		/// </summary>
		static string Line
		{
			[DebuggerNonUserCode]
			get
			{
				return Console.ReadLine();
			}
		}
		/// <summary>
		/// Input bool
		/// </summary>
		static bool Bool
		{
			[DebuggerNonUserCode]
			get
			{
				return bool.Parse(Word);
			}
		}
		/// <summary>
		/// Input char
		/// </summary>
		static char Char
		{
			[DebuggerNonUserCode]
			get
			{
				return char.Parse(Word);
			}
		}
		/// <summary>
		/// Input byte
		/// </summary>
		static byte Byte
		{
			[DebuggerNonUserCode]
			get
			{
				return byte.Parse(Word);
			}
		}
		/// <summary>
		/// Input ushort
		/// </summary>
		static ushort UShort
		{
			[DebuggerNonUserCode]
			get
			{
				return ushort.Parse(Word);
			}
		}
		/// <summary>
		/// Input uint
		/// </summary>
		static uint UInt
		{
			[DebuggerNonUserCode]
			get
			{
				return uint.Parse(Word);
			}
		}
		/// <summary>
		/// Input ulong
		/// </summary>
		static ulong ULong
		{
			[DebuggerNonUserCode]
			get
			{
				return ulong.Parse(Word);
			}
		}
		/// <summary>
		/// Input sbyte
		/// </summary>
		static sbyte SByte
		{
			[DebuggerNonUserCode]
			get
			{
				return sbyte.Parse(Word);
			}
		}
		/// <summary>
		/// Input short
		/// </summary>
		static short Short
		{
			[DebuggerNonUserCode]
			get
			{
				return short.Parse(Word);
			}
		}
		/// <summary>
		/// Input int
		/// </summary>
		static int Int
		{
			[DebuggerNonUserCode]
			get
			{
				return int.Parse(Word);
			}
		}
		/// <summary>
		/// Input long
		/// </summary>
		static long Long
		{
			[DebuggerNonUserCode]
			get
			{
				return long.Parse(Word);
			}
		}
		/// <summary>
		/// Input decimal
		/// </summary>
		static decimal Decimal
		{
			[DebuggerNonUserCode]
			get
			{
				return decimal.Parse(Word);
			}
		}
		/// <summary>
		/// Input variable length integer
		/// </summary>
		static BigInteger Integer
		{
			[DebuggerNonUserCode]
			get
			{
				return BigInteger.Parse(Word);
			}
		}
		/// <summary>
		/// Input float
		/// </summary>
		static float Float
		{
			[DebuggerNonUserCode]
			get
			{
				return float.Parse(Word);
			}
		}
		/// <summary>
		/// Input double
		/// </summary>
		static double Double
		{
			[DebuggerNonUserCode]
			get
			{
				return double.Parse(Word);
			}
		}

		/// <summary>
		/// Input hex int
		/// </summary>
		static int Hex
		{
			[DebuggerNonUserCode]
			get
			{
				return int.Parse(Word, NumberStyles.HexNumber);
			}
		}
		/// <summary>
		/// Input hex int
		/// </summary>
		static int HexInt
		{
			[DebuggerNonUserCode]
			get
			{
				return Hex;
			}
		}
		/// <summary>
		/// Input hex long
		/// </summary>
		static long HexLong
		{
			[DebuggerNonUserCode]
			get
			{
				return long.Parse(Word, NumberStyles.HexNumber);
			}
		}
		/// <summary>
		/// Input variable length hex integer
		/// </summary>
		static BigInteger HexInteger
		{
			[DebuggerNonUserCode]
			get
			{
				return BigInteger.Parse(Word, NumberStyles.HexNumber);
			}
		}

		/// <summary>
		/// Calculate GCD
		/// </summary>
		/// <typeparam name="T">type of value</typeparam>
		/// <typeparam name="TOp">operator struct of value</typeparam>
		/// <param name="a">first value</param>
		/// <param name="b">second value</param>
		/// <returns>the GCD between <c>a</c> and <c>b</c></returns>
		static T Gcd<T, TOp>(T a, T b)
			where TOp : struct, IDividable<T>
		{
			T x, y;
			return Gcd<T, TOp>(a, b, out x, out y);
		}
		/// <summary>
		/// Calculate GCD
		/// </summary>
		/// <typeparam name="T">type of value</typeparam>
		/// <typeparam name="TOp">operator struct of value</typeparam>
		/// <param name="a">first value</param>
		/// <param name="b">second value</param>
		/// <param name="x">return the coefficient of <c>a</c></param>
		/// <param name="y">return the coefficient of <c>b</c></param>
		/// <returns>the GCD between <c>a</c> and <c>b</c></returns>
		static T Gcd<T, TOp>(T a, T b, out T x, out T y)
			where TOp : struct, IDividable<T>
		{
			T x1 = default(TOp).Zero;
			T x2 = default(TOp).One;
			T y1 = default(TOp).One;
			T y2 = default(TOp).Zero;
			T q = default(TOp).Zero;

			while (0 != default(TOp).Compare(b, default(TOp).Zero))
			{
				var tmp = x2;
				x2 = default(TOp).Subtract(x1, default(TOp).Multiply(q, x2));
				x1 = tmp;
				tmp = y2;
				y2 = default(TOp).Subtract(y2, default(TOp).Multiply(q, y2));
				y1 = tmp;
				q = default(TOp).Divide(a, b);
				tmp = b;
				b = default(TOp).Modulo(a, b);
				a = tmp;
			}

			x = x2;
			y = y2;
			return a;
		}

		/// <summary>
		/// Union-find tree
		/// </summary>
		class UnionFind : UnionFind<Unit, UnitOp>
		{
			/// <param name="count">number of elements</param>
			public UnionFind(int count) : base(count)
			{ }
		}
		/// <summary>
		/// Union-find tree
		/// </summary>
		class UnionFind<TPotential, TPotentialOp>
			where TPotentialOp : struct, IAddable<TPotential>
		{
			/// <summary>
			/// parent indices
			/// </summary>
			readonly int[] Parent;

			/// <summary>
			/// tree rank
			/// </summary>
			readonly int[] Rank;

			/// <summary>
			/// potential
			/// </summary>
			readonly TPotential[] DiffPotential;

			/// <param name="count">number of elements</param>
			public UnionFind(int count)
			{
				Parent = MakeArray(count, i => i);
				Rank = MakeArray(count, i => 0);
				DiffPotential = MakeArray(count, i => default(TPotentialOp).Zero);
			}

			/// <summary>
			/// Get root element
			/// </summary>
			/// <param name="x">element index</param>
			/// <returns>root element index of <c>x</c></returns>
			public int Root(int x)
			{
				if (Parent[x] == x)
				{
					return x;
				}
				else
				{
					var root = Root(Parent[x]);
					DiffPotential[x] = default(TPotentialOp).Add(DiffPotential[x], DiffPotential[Parent[x]]);
					return Parent[x] = root;
				}
			}

			/// <summary>
			/// Get whether two elements belong to the same set.
			/// </summary>
			/// <param name="x">first element index</param>
			/// <param name="y">second element index</param>
			/// <returns>whether two elements belong to the same set</returns>
			public bool Same(int x, int y)
				=> Root(x) == Root(y);


			/// <summary>
			/// Unite two elements
			/// </summary>
			/// <param name="x">first element index</param>
			/// <param name="y">second element index</param>
			public bool Unite(int x, int y)
				=> Unite(x, y, default(TPotentialOp).Zero);

			/// <summary>
			/// Unite two elements
			/// </summary>
			/// <param name="x">first element index</param>
			/// <param name="y">second element index</param>
			/// <param name="potential">potential from <c>x</c> to <c>y</c></param>
			public bool Unite(int x, int y, TPotential potential)
			{
				potential = default(TPotentialOp).Add(potential, Potential(x));
				potential = default(TPotentialOp).Subtract(potential, Potential(y));
				x = Root(x);
				y = Root(y);

				if (x == y) return false;

				if (Rank[x] < Rank[y])
				{
					// Join x to y
					Parent[x] = y;
					DiffPotential[x] = default(TPotentialOp).Negate(potential);
				}
				else
				{
					// Join y to x
					Parent[y] = x;
					if (Rank[x] == Rank[y]) ++Rank[x];
					DiffPotential[y] = potential;
				}
				return true;
			}

			/// <summary>
			/// Get potential difference from root.
			/// </summary>
			/// <param name="x">element index</param>
			/// <returns>potential difference between the element and the root</returns>
			public TPotential Potential(int x)
			{
				Root(x);
				return DiffPotential[x];
			}

			/// <summary>
			/// Get potential difference between two element.
			/// </summary>
			/// <param name="x">first element index</param>
			/// <param name="y">second element index</param>
			/// <returns>potential difference between two element</returns>
			public TPotential Diff(int x, int y)
				=> default(TPotentialOp).Subtract(Potential(y), Potential(x));
		}

		struct Unit
		{ }
		struct UnitOp : IDividable<Unit>
		{
			public Unit Zero => default(Unit);
			public Unit One => default(Unit);
			public Unit Negate(Unit x) => default(Unit);
			public Unit Add(Unit x, Unit y) => default(Unit);
			public Unit Multiply(Unit x, Unit y) => default(Unit);
			public Unit Divide(Unit x, Unit y) => default(Unit);
			public Unit Modulo(Unit x, Unit y) => default(Unit);
			public int Compare(Unit x, Unit y) => 0;
		}
		struct IntOp : IDividable<int>
		{
			public int Zero => 0;
			public int One => 1;
			public int Negate(int x) => -x;
			public int Add(int x, int y) => x + y;
			public int Multiply(int x, int y) => x * y;
			public int Divide(int x, int y) => x / y;
			public int Modulo(int x, int y) => x % y;
			public int Compare(int x, int y) => x.CompareTo(y);
		}
		struct LongOp : IDividable<long>
		{
			public long Zero => 0L;
			public long One => 1L;
			public long Negate(long x) => -x;
			public long Add(long x, long y) => x + y;
			public long Multiply(long x, long y) => x * y;
			public long Divide(long x, long y) => x / y;
			public long Modulo(long x, long y) => x % y;
			public int Compare(long x, long y) => x.CompareTo(y);
		}
		struct FloatOp : IDividable<float>
		{
			public float Zero => 0.0F;
			public float One => 1.0F;
			public float Negate(float x) => -x;
			public float Add(float x, float y) => x + y;
			public float Multiply(float x, float y) => x * y;
			public float Divide(float x, float y) => x / y;
			public float Modulo(float x, float y) => x % y;
			public int Compare(float x, float y) => x.CompareTo(y);
		}
		struct DoubleOp : IDividable<double>
		{
			public double Zero => 0.0;
			public double One => 1.0;
			public double Negate(double x) => -x;
			public double Add(double x, double y) => x + y;
			public double Multiply(double x, double y) => x * y;
			public double Divide(double x, double y) => x / y;
			public double Modulo(double x, double y) => x % y;
			public int Compare(double x, double y) => x.CompareTo(y);
		}
	}

	interface IDividable<T> : IMultipliable<T>
	{
		T Divide(T x, T y);
		T Modulo(T x, T y);
	}
	interface IMultipliable<T> : IAddable<T>
	{
		T One { get; }
		T Multiply(T x, T y);
	}
	interface IAddable<T> : IComparer<T>
	{
		T Zero { get; }
		T Negate(T x);
		T Add(T x, T y);
	}

	static class OperationExtensions
	{
		public static T Subtract<T, TOp>(this TOp op, T x, T y)
			where TOp : struct, IAddable<T>
		{
			return default(TOp).Add(x, default(TOp).Negate(y));
		}
		public static T Sum<T, TOp>(this TOp op, params T[] items)
			where TOp : struct, IAddable<T>
		{
			var sum = default(TOp).Zero;
			foreach (var item in items)
				sum = default(TOp).Add(sum, item);
			return sum;
		}
		public static T Product<T, TOp>(this TOp op, params T[] items)
			where TOp : struct, IMultipliable<T>
		{
			var sum = default(TOp).One;
			foreach (var item in items)
				sum = default(TOp).Multiply(sum, item);
			return sum;
		}
	}
}