fork download
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Text;
  5.  
  6. namespace Automaton
  7. {
  8. class Program
  9. {
  10. const string INDENT = "\t";
  11.  
  12. static void Main(string[] args)
  13. {
  14. Checker checker = new DateTimeChecker();
  15.  
  16. List<Tuple<string, bool>> testCase = new List<Tuple<string, bool>>();
  17. testCase.Add(Tuple.Create("2018/11/16 12:34:56.789", true));
  18. testCase.Add(Tuple.Create("2018/11/16 12:34:56.78", false));
  19. testCase.Add(Tuple.Create("2018/11/16 12:34:56.7", false));
  20. testCase.Add(Tuple.Create("2018/11/16 12:34:56.", false));
  21. testCase.Add(Tuple.Create("2018/11/16 12:34:56", true));
  22. testCase.Add(Tuple.Create("2018/11/16 12:34:5", false));
  23. testCase.Add(Tuple.Create("2018/11/16 12:34:", false));
  24. testCase.Add(Tuple.Create("2018/11/16 12:34", true));
  25. testCase.Add(Tuple.Create("2018/11/16 12:3", false));
  26. testCase.Add(Tuple.Create("2018/11/16 12:", false));
  27. testCase.Add(Tuple.Create("2018/11/16 12", true));
  28. testCase.Add(Tuple.Create("2018/11/16 1", false));
  29. testCase.Add(Tuple.Create("2018/11/16 ", false));
  30. testCase.Add(Tuple.Create("2018/11/16", true));
  31. testCase.Add(Tuple.Create("2018/11/1", false));
  32. testCase.Add(Tuple.Create("2018/11/", false));
  33. testCase.Add(Tuple.Create("2018/11", true));
  34. testCase.Add(Tuple.Create("2018/1", false));
  35. testCase.Add(Tuple.Create("2018/", false));
  36. testCase.Add(Tuple.Create("2018", false));
  37. testCase.Add(Tuple.Create("201", false));
  38. testCase.Add(Tuple.Create("20", false));
  39. testCase.Add(Tuple.Create("2", false));
  40. testCase.Add(Tuple.Create("", false));
  41. TestDateTime(checker, testCase);
  42. checker.Reset();
  43. testCase.Clear();
  44.  
  45. testCase.Add(Tuple.Create("18/11/16 12:34:56.789", true));
  46. testCase.Add(Tuple.Create("18/11/16 12:34:56.78", false));
  47. testCase.Add(Tuple.Create("18/11/16 12:34:56.7", false));
  48. testCase.Add(Tuple.Create("18/11/16 12:34:56.", false));
  49. testCase.Add(Tuple.Create("18/11/16 12:34:56", true));
  50. testCase.Add(Tuple.Create("18/11/16 12:34:5", false));
  51. testCase.Add(Tuple.Create("18/11/16 12:34:", false));
  52. testCase.Add(Tuple.Create("18/11/16 12:34", true));
  53. testCase.Add(Tuple.Create("18/11/16 12:3", false));
  54. testCase.Add(Tuple.Create("18/11/16 12:", false));
  55. testCase.Add(Tuple.Create("18/11/16 12", true));
  56. testCase.Add(Tuple.Create("18/11/16 1", false));
  57. testCase.Add(Tuple.Create("18/11/16 ", false));
  58. testCase.Add(Tuple.Create("18/11/16", true));
  59. testCase.Add(Tuple.Create("18/11/1", false));
  60. testCase.Add(Tuple.Create("18/11/", false));
  61. testCase.Add(Tuple.Create("18/11", true)); // cannot be distinguished from MM/dd
  62. testCase.Add(Tuple.Create("18/1", false));
  63. testCase.Add(Tuple.Create("18/", false));
  64. testCase.Add(Tuple.Create("18", false));
  65. testCase.Add(Tuple.Create("1", false));
  66. TestDateTime(checker, testCase);
  67. checker.Reset();
  68. testCase.Clear();
  69.  
  70. testCase.Add(Tuple.Create("11/16 12:34:56.789", true));
  71. testCase.Add(Tuple.Create("11/16 12:34:56.78", false));
  72. testCase.Add(Tuple.Create("11/16 12:34:56.7", false));
  73. testCase.Add(Tuple.Create("11/16 12:34:56.", false));
  74. testCase.Add(Tuple.Create("11/16 12:34:56", true));
  75. testCase.Add(Tuple.Create("11/16 12:34:5", false));
  76. testCase.Add(Tuple.Create("11/16 12:34:", false));
  77. testCase.Add(Tuple.Create("11/16 12:34", true));
  78. testCase.Add(Tuple.Create("11/16 12:3", false));
  79. testCase.Add(Tuple.Create("11/16 12:", false));
  80. testCase.Add(Tuple.Create("11/16 12", true));
  81. testCase.Add(Tuple.Create("11/16 1", false));
  82. testCase.Add(Tuple.Create("11/16 ", false));
  83. testCase.Add(Tuple.Create("11/16", true)); // cannot be distinguished from yy/MM
  84. testCase.Add(Tuple.Create("11/1", false));
  85. testCase.Add(Tuple.Create("11/", false));
  86. testCase.Add(Tuple.Create("11", false));
  87. testCase.Add(Tuple.Create("1", false));
  88. TestDateTime(checker, testCase);
  89. checker.Reset();
  90. testCase.Clear();
  91.  
  92. testCase.Add(Tuple.Create("12:34:56.789", true));
  93. testCase.Add(Tuple.Create("12:34:56.78", false));
  94. testCase.Add(Tuple.Create("12:34:56.7", false));
  95. testCase.Add(Tuple.Create("12:34:56.", false));
  96. testCase.Add(Tuple.Create("12:34:56", true));
  97. testCase.Add(Tuple.Create("12:34:5", false));
  98. testCase.Add(Tuple.Create("12:34:", false));
  99. testCase.Add(Tuple.Create("12:34", true)); // cannot be distinguished from mm:ss
  100. testCase.Add(Tuple.Create("12:3", false));
  101. testCase.Add(Tuple.Create("12:", false));
  102. testCase.Add(Tuple.Create("12", false));
  103. testCase.Add(Tuple.Create("1", false));
  104. TestDateTime(checker, testCase);
  105. checker.Reset();
  106. testCase.Clear();
  107.  
  108. testCase.Add(Tuple.Create("34:56.789", true));
  109. testCase.Add(Tuple.Create("34:56.78", false));
  110. testCase.Add(Tuple.Create("34:56.7", false));
  111. testCase.Add(Tuple.Create("34:56.", false));
  112. testCase.Add(Tuple.Create("34:56", true)); // cannot be distinguished from HH:mm
  113. testCase.Add(Tuple.Create("34:5", false));
  114. testCase.Add(Tuple.Create("34:", false));
  115. testCase.Add(Tuple.Create("34", false));
  116. testCase.Add(Tuple.Create("3", false));
  117. TestDateTime(checker, testCase);
  118. checker.Reset();
  119. testCase.Clear();
  120. }
  121.  
  122. static void TestDateTime(Checker checker, IList<Tuple<string, bool>> testCase)
  123. {
  124. foreach (Tuple<string, bool> t in testCase)
  125. {
  126. Console.Write("[" + t.Item1 + "] ");
  127. checker.Reset();
  128. foreach (char ch in t.Item1)
  129. {
  130. checker.MoveNext(ch);
  131. if (checker.IsError())
  132. {
  133. Console.Write(INDENT);
  134. Console.WriteLine(":ERROR");
  135. Debug.Assert(!t.Item2, "asersion failed!!");
  136. break;
  137. }
  138. }
  139.  
  140.  
  141. if (!checker.IsError())
  142. {
  143. if (checker.IsAcceptable())
  144. {
  145. Console.Write(INDENT);
  146. Console.WriteLine(":OK");
  147. Debug.Assert(t.Item2, t.Item1 + " asersion failed!!");
  148. }
  149. else
  150. {
  151. Console.Write(INDENT);
  152. Console.WriteLine(":NG");
  153. Debug.Assert(!t.Item2, "asersion failed!!");
  154. }
  155. }
  156. }
  157. }
  158. }
  159.  
  160. interface Checker
  161. {
  162. void Reset();
  163. void MoveNext(char ch);
  164. bool IsAcceptable();
  165. bool IsError();
  166. bool IsNextError(char ch);
  167. string Current();
  168. }
  169.  
  170. class DateTimeChecker : Checker
  171. {
  172. enum States
  173. {
  174. Error,
  175. State00,
  176. State01,
  177. State02,
  178. State03,
  179. State04,
  180. State05,
  181. State06,
  182. State07,
  183. State08,
  184. State09,
  185. State10,
  186. State11,
  187. State12,
  188. State13,
  189. State14,
  190. State15,
  191. State16,
  192. State17,
  193. State18,
  194. State19,
  195. State20,
  196. State21,
  197. State22,
  198. State23,
  199. State24,
  200. State25,
  201. State26,
  202. State27,
  203. State28,
  204. State29,
  205. }
  206.  
  207. StringBuilder _sb;
  208. States _state;
  209.  
  210. public DateTimeChecker()
  211. {
  212. _sb = new StringBuilder();
  213. Reset();
  214. }
  215.  
  216. public void Reset()
  217. {
  218. _state = States.State00;
  219. _sb.Clear();
  220. }
  221.  
  222. public void MoveNext(char ch)
  223. {
  224. _sb.Append(ch);
  225. _state = GetNext(ch);
  226. }
  227.  
  228. public bool IsAcceptable()
  229. {
  230. return
  231. _state == States.State10
  232. || _state == States.State11
  233. || _state == States.State17
  234. || _state == States.State22
  235. || _state == States.State23
  236. || _state == States.State24
  237. || _state == States.State27
  238. || _state == States.State29;
  239. }
  240.  
  241. public bool IsError()
  242. {
  243. return _state == States.Error;
  244. }
  245.  
  246. public bool IsNextError(char ch)
  247. {
  248. States next = GetNext(ch);
  249. return IsError(next);
  250. }
  251.  
  252. public string Current()
  253. {
  254. return _sb.ToString();
  255. }
  256.  
  257. States GetNext(char ch)
  258. {
  259. States next = States.Error;
  260. switch (_state)
  261. {
  262. case States.State00:
  263. next = Transition(ch, States.State01, States.Error, States.Error, States.Error, States.Error);
  264. break;
  265. case States.State01:
  266. next = Transition(ch, States.State02, States.Error, States.Error, States.Error, States.Error);
  267. break;
  268. case States.State02:
  269. next = Transition(ch, States.State03, States.State04, States.Error, States.State05, States.Error);
  270. break;
  271. case States.State03:
  272. next = Transition(ch, States.State06, States.Error, States.Error, States.Error, States.Error);
  273. break;
  274. case States.State04:
  275. next = Transition(ch, States.State07, States.Error, States.Error, States.Error, States.Error);
  276. break;
  277. case States.State05:
  278. next = Transition(ch, States.State08, States.Error, States.Error, States.Error, States.Error);
  279. break;
  280. case States.State06:
  281. next = Transition(ch, States.Error, States.State09, States.Error, States.Error, States.Error);
  282. break;
  283. case States.State07:
  284. next = Transition(ch, States.State10, States.Error, States.Error, States.Error, States.Error);
  285. break;
  286. case States.State08:
  287. next = Transition(ch, States.State11, States.Error, States.Error, States.Error, States.Error);
  288. break;
  289. case States.State09:
  290. next = Transition(ch, States.State12, States.Error, States.Error, States.Error, States.Error);
  291. break;
  292. case States.State10:
  293. next = Transition(ch, States.Error, States.State13, States.State14, States.Error, States.Error);
  294. break;
  295. case States.State11:
  296. next = Transition(ch, States.Error, States.Error, States.Error, States.State15, States.State16);
  297. break;
  298. case States.State12:
  299. next = Transition(ch, States.State17, States.Error, States.Error, States.Error, States.Error);
  300. break;
  301. case States.State13:
  302. next = Transition(ch, States.State18, States.Error, States.Error, States.Error, States.Error);
  303. break;
  304. case States.State14:
  305. next = Transition(ch, States.State19, States.Error, States.Error, States.Error, States.Error);
  306. break;
  307. case States.State15:
  308. next = Transition(ch, States.State20, States.Error, States.Error, States.Error, States.Error);
  309. break;
  310. case States.State16:
  311. next = Transition(ch, States.State21, States.Error, States.Error, States.Error, States.Error);
  312. break;
  313. case States.State17:
  314. next = Transition(ch, States.Error, States.State13, States.Error, States.Error, States.Error);
  315. break;
  316. case States.State18:
  317. next = Transition(ch, States.State22, States.Error, States.Error, States.Error, States.Error);
  318. break;
  319. case States.State19:
  320. next = Transition(ch, States.State23, States.Error, States.Error, States.Error, States.Error);
  321. break;
  322. case States.State20:
  323. next = Transition(ch, States.State24, States.Error, States.Error, States.Error, States.Error);
  324. break;
  325. case States.State21:
  326. next = Transition(ch, States.State25, States.Error, States.Error, States.Error, States.Error);
  327. break;
  328. case States.State22:
  329. next = Transition(ch, States.Error, States.Error, States.State14, States.Error, States.Error);
  330. break;
  331. case States.State23:
  332. next = Transition(ch, States.Error, States.Error, States.Error, States.State26, States.Error);
  333. break;
  334. case States.State24:
  335. next = Transition(ch, States.Error, States.Error, States.Error, States.Error, States.State16);
  336. break;
  337. case States.State25:
  338. next = Transition(ch, States.State27, States.Error, States.Error, States.Error, States.Error);
  339. break;
  340. case States.State26:
  341. next = Transition(ch, States.State28, States.Error, States.Error, States.Error, States.Error);
  342. break;
  343. case States.State27:
  344. next = Transition(ch, States.Error, States.Error, States.Error, States.Error, States.Error);
  345. break;
  346. case States.State28:
  347. next = Transition(ch, States.State29, States.Error, States.Error, States.Error, States.Error);
  348. break;
  349. case States.State29:
  350. next = Transition(ch, States.Error, States.Error, States.Error, States.State15, States.Error);
  351. break;
  352. default:
  353. next = States.Error;
  354. break;
  355. }
  356. return next;
  357. }
  358.  
  359. static States Transition(char ch, States whenDigit, States whenSlash, States whenSpace, States whenColon, States whenDot)
  360. {
  361. States next = States.Error;
  362.  
  363. if (char.IsDigit(ch))
  364. {
  365. next = whenDigit;
  366. }
  367. else if (ch == '/')
  368. {
  369. next = whenSlash;
  370. }
  371. else if (ch == ' ')
  372. {
  373. next = whenSpace;
  374. }
  375. else if (ch == ':')
  376. {
  377. next = whenColon;
  378. }
  379. else if (ch == '.')
  380. {
  381. next = whenDot;
  382. }
  383. else
  384. {
  385. next = States.Error;
  386. }
  387.  
  388. return next;
  389. }
  390.  
  391. static bool IsError(States state)
  392. {
  393. return state == States.Error;
  394. }
  395. }
  396. }
  397.  
Success #stdin #stdout 0s 131520KB
stdin
Standard input is empty
stdout
[2018/11/16 12:34:56.789] 	:OK
[2018/11/16 12:34:56.78] 	:NG
[2018/11/16 12:34:56.7] 	:NG
[2018/11/16 12:34:56.] 	:NG
[2018/11/16 12:34:56] 	:OK
[2018/11/16 12:34:5] 	:NG
[2018/11/16 12:34:] 	:NG
[2018/11/16 12:34] 	:OK
[2018/11/16 12:3] 	:NG
[2018/11/16 12:] 	:NG
[2018/11/16 12] 	:OK
[2018/11/16 1] 	:NG
[2018/11/16 ] 	:NG
[2018/11/16] 	:OK
[2018/11/1] 	:NG
[2018/11/] 	:NG
[2018/11] 	:OK
[2018/1] 	:NG
[2018/] 	:NG
[2018] 	:NG
[201] 	:NG
[20] 	:NG
[2] 	:NG
[] 	:NG
[18/11/16 12:34:56.789] 	:OK
[18/11/16 12:34:56.78] 	:NG
[18/11/16 12:34:56.7] 	:NG
[18/11/16 12:34:56.] 	:NG
[18/11/16 12:34:56] 	:OK
[18/11/16 12:34:5] 	:NG
[18/11/16 12:34:] 	:NG
[18/11/16 12:34] 	:OK
[18/11/16 12:3] 	:NG
[18/11/16 12:] 	:NG
[18/11/16 12] 	:OK
[18/11/16 1] 	:NG
[18/11/16 ] 	:NG
[18/11/16] 	:OK
[18/11/1] 	:NG
[18/11/] 	:NG
[18/11] 	:OK
[18/1] 	:NG
[18/] 	:NG
[18] 	:NG
[1] 	:NG
[11/16 12:34:56.789] 	:OK
[11/16 12:34:56.78] 	:NG
[11/16 12:34:56.7] 	:NG
[11/16 12:34:56.] 	:NG
[11/16 12:34:56] 	:OK
[11/16 12:34:5] 	:NG
[11/16 12:34:] 	:NG
[11/16 12:34] 	:OK
[11/16 12:3] 	:NG
[11/16 12:] 	:NG
[11/16 12] 	:OK
[11/16 1] 	:NG
[11/16 ] 	:NG
[11/16] 	:OK
[11/1] 	:NG
[11/] 	:NG
[11] 	:NG
[1] 	:NG
[12:34:56.789] 	:OK
[12:34:56.78] 	:NG
[12:34:56.7] 	:NG
[12:34:56.] 	:NG
[12:34:56] 	:OK
[12:34:5] 	:NG
[12:34:] 	:NG
[12:34] 	:OK
[12:3] 	:NG
[12:] 	:NG
[12] 	:NG
[1] 	:NG
[34:56.789] 	:OK
[34:56.78] 	:NG
[34:56.7] 	:NG
[34:56.] 	:NG
[34:56] 	:OK
[34:5] 	:NG
[34:] 	:NG
[34] 	:NG
[3] 	:NG