-- Solution to Advent of Code 2020, Day 04, Part Two ----------------------------------------------------- -- Passport Processing -- -- Full Ada version. -- -- https://adventofcode.com/2020/day/04 -- with Ada.Characters.Handling, Ada.Strings.Fixed, Ada.Text_IO; with Interfaces; procedure AoC_2020_04_b_Full_Ada is use Ada.Characters.Handling, Ada.Strings.Fixed, Ada.Text_IO, Interfaces; -- function Val (s : String) return Integer_64 is begin return Integer_64'Value (s); exception when others => return -1; end Val; -- type Cat is (byr, iyr, eyr, hgt, hcl, ecl, pid); ok : Boolean; f : File_Type; cats, cat_idx, total : Integer := 0; tok_begin, tok_end : Integer; begin Open (f, In_File, "aoc_2020_04.txt"); while not End_Of_File (f) loop declare s : constant String := Get_Line (f); begin if s = "" then cats := 0; end if; for c in Cat loop cat_idx := Index (s, To_Lower (Cat'Image (c)) & ':'); if cat_idx > 0 then tok_begin := cat_idx + 4; tok_end := Index (s, " ", tok_begin); if tok_end > 0 then tok_end := tok_end - 1; else tok_end := s'Last; end if; declare tok : String renames s (tok_begin .. tok_end); begin case c is when byr => ok := Val (tok) in 1920 .. 2002; when iyr => ok := Val (tok) in 2010 .. 2020; when eyr => ok := Val (tok) in 2020 .. 2030; when hcl => ok := Val ("16" & tok & '#') > 0; when pid => ok := tok'Length = 9 and then Val (tok) > 0; when ecl => ok := Index ("amb blu brn gry grn hzl oth", tok) > 0; -- ^ Idea: Maxim Reznik, replaces checking each value when hgt => ok := ((Val (s (tok_begin .. tok_end - 2)) in 150 .. 193 and then s (tok_end - 1 .. tok_end) = "cm") or else (Val (s (tok_begin .. tok_end - 2)) in 59 .. 76 and then s (tok_end - 1 .. tok_end) = "in") ); end case; end; if ok then cats := cats + 1; end if; end if; end loop; if cats = 7 then total := total + 1; -- Prevent incrementing total if there is garbage -- or a "cid:" until next blank line: cats := 0; end if; end; end loop; Close (f); Put_Line ("Valid passports (criteria #2):" & Integer'Image (total)); end AoC_2020_04_b_Full_Ada;